Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

starting to write automated tests

by geektron (Curate)
on Dec 28, 2004 at 16:52 UTC ( #417790=perlquestion: print w/ replies, xml ) Need Help??
geektron has asked for the wisdom of the Perl Monks concerning the following question:

I've *finally* had enough of the application I've been stuck maintaining and its random, buggy behaviour. There are 2 long outstanding bugs that I just can't replicate ... no matter how hard I've tried using 'crafty' non-automated testing.

So, it's time to bite the bullet and start writing a test harness for the bloody thing. It's a large, strange, re-blessed custom-rolled shopping cart application. The checkout process is my starting point ... somewhere along the line important data gets lost, and orders can't complete.

i picked up a copy of Perl Medic recently to get me started on this task. And I'm looking at Test::More to get things rolling, but the points that I need to test the most are a few steps into checkout process ( credit card processing, address insertion into the database, etc. ).

so, that all said ... where are some good places to look re: building these tests from 'legacy' code ... not building new code, writing tests first a la XP ... but finding trouble spots in older code and building a working test harness around it?

Comment on starting to write automated tests
Re: starting to write automated tests
by dragonchild (Archbishop) on Dec 28, 2004 at 17:04 UTC
    The first thing I'd do is define your use cases - what are the standard steps a user should take to do X, Y, or Z. Once you have those, then write system tests for those paths.

    Second, I'd look at what objects you have and what their API should be. Then, write unit tests for those objects.

    You can use Test::More along with some friends to get both of those items done. For example, WWW::Mechanize can be helpful to write automated system tests.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      well, a use case scenario isn't too difficult. it's a more or less linear path from items in cart to credit card processing.

      right now i'm stuck on *why* one of the Test::Simple tests is not returning the "status" message:

      #!/usr/bin/perl use strict; use Test::Simple tests => 4; use ShopDB::AuthorizeCard; my $authCard = ShopDB::AuthorizeCard->new(); ok( defined( $authCard ), "new() successful" ); ok( ref $authCard eq 'ShopDB::AuthorizeCard', "blessed into right package" ); ok( defined( $authCard ) and ref $authCard eq 'ShopDB::AuthorizeCard', + "new() successful, blessed into right package" ); ok( $authCard->can( 'AuthorizeCard' ), "found the AuthorizeCard() method" );
      gives me:
      1..4 ok 1 - new() successful ok 2 - blessed into right package ok 3 ok 4 - found the AuthorizeCard() method
      test 3 is just a combination of tests one and two ... but i don't get the ok message back, and i don't get it.
        Try changing the 'and' to a &&. 'and' has a lower precedence than ',' - that's what's causing the problem.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Aside from the precedence issue pointed out by dragonchild, I have to wonder why you have test 3 at all? Test 1 and 2 already tested both of those conditions. What's the point of testing them again? Might they have suddenly changed between the tests?

        use warnings;
        and
        use diagnostics;
        would be your friends, if you let them.

        Be well,
        rir

        First, start with Test::More, not Test::Simple. Use the convenience functions, like so:
        my $authCard = ShopDB::AuthorizeCard->new(); isa_ok( $authCard, 'ShopDB::AuthorizeCard' ); can_ok( $authCard, 'AuthorizeCard' );
        Those convenience methods will save you hassle AND problems like you had. isa_ok() specifically checks definedness for you.

        xoxo,
        Andy

      And Test::WWW::Mechanize combines them both, so you can do stuff like
      $mech->get( $homepage ); $mech->content_contains( "Contact us" ); $mech->content_unlike( qr/Under construction/i );

      xoxo,
      Andy

Re: starting to write automated tests
by McMahon (Chaplain) on Dec 28, 2004 at 23:18 UTC
Re: starting to write automated tests
by eyepopslikeamosquito (Canon) on Dec 29, 2004 at 00:32 UTC
Re: starting to write automated tests
by jplindstrom (Monsignor) on Dec 29, 2004 at 17:47 UTC
    We're just beginning to add tests to a large code base (C++) at work, so I've gone through a little of what you face. A couple of thoughts...

    The Perl Medic book is good in general, and also specifically about your situation.

    If you have code without tests, it's probably not easy to start writing tests; the classes aren't decoupled enough and there are lots of dependencies all over the place. That's my experience anyway, you may be more lucky.

    But you have to start somewhere. You can probably nail down the system-as-a-whole using e.g. WWW::Mechanize, just by looking at the system from a user perspective. Start there, that's the most important thing to a) not break, and b) understand/define. Looking at the entire system has the advantage that it doesn't have any dependencies (since it's, uh... the entire system), but the disadvantage that you don't have a stable state wrt data.

    When you have the outside view defined and tested, start at the bottom and try to break out classes and functions to test. Start with very, very simple tests, often it's a lot of work just to instantiate an object without all the other objects it depends on. Test::MockObject may help you there.

    Test as far as you can, then refactor to make it possible to test further. You'll probably come across methods that are too long or too "fuzzy" to test. Those are good candidates to both document and break up into smaller well-defined parts.

    Try not to fix bugs at the same time as you refactor, tings will easily get mixed up.

    At times you may need to refactor without having the safety net of tests, but sometimes life just sucks, eh? :)

    Well, that's all I could think of just now.

    Good luck!

    /J

      If you have code without tests, it's probably not easy to start writing tests; the classes aren't decoupled enough and there are lots of dependencies all over the place. That's my experience anyway, you may be more lucky.
      oh, i won't be as lucky. i started documenting the whole ordering process yesterday, and it's the usual mess. in an attempt to decouple some functionality, modules are sliced too thinly. in other cases, too much goes on in a module that really isn't related.
      Try not to fix bugs at the same time as you refactor, tings will easily get mixed up.
      i've already learned *that* one the hard way. never again.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://417790]
Approved by Old_Gray_Bear
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (11)
As of 2014-07-30 09:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (230 votes), past polls