in reply to (OT) Help with test design

The canonical order to do things is to first write the documentation, then from the documentation write the tests, then write code until the tests pass. Of course, in practice that doesn't happen because your design evolves as you write the code and so you need to add/remove/change tests.

Your situation is slightly different in that you already have code, but I would suggest that you should first document what you've written do far. Documentation should include, for each method:

Then write tests which check that your methods do indeed do what you expect them to do. Be aggressive in your testing, ensuring that you perform some tests with deliberately pathological data - for instance, if your documentation says "this method will die if the username is invalid" then check the situations where no username is passed (ie it's undef), where an empty username is passed (the empty string, '') and where a username like 'snafflegarb' or something equally silly is passed; if you have a method that expects a numeric argument, call it with argument 'pineapple', and with a reference, and with outrageously small numbers, stupidly big numbers, negative numbers ... If you're feeling particularly nasty, try testing with Math::Big* objects.

If you are implementing complex algorithms, you should in theory derive the results to test your code's correctness in some other way, but if you are confident that your results are correct, then I'd say it's OK to cheat and to use the module to generate its test results, provided that you throw in a couple of the simpler results calculated by hand yourself. Using the module to generate results which you then hard-code into the test suite is still useful, as it provides a check in the future to make sure you haven't inadvertently broken the algorithm in the next release.

Replies are listed 'Best First'.
Re: Re: (OT) Help with test design
by dragonchild (Archbishop) on Sep 11, 2003 at 15:00 UTC
    Speaking of documentation, that's the other hot item on my to-do list. How would you document 26 classes and how they all go together, given that all of the leaf classes have multiple inheritance. (This is because Board-specific functionality is stored in Games::Board and Othello-specific functionality is in Games::Othello, so Games::Board::Othello inherits from Games::Board and Games::Othello.)

    Part of my issue seems to be that the design grew organic, so attempting to organize it looks like a huge problem, in my mind. I'm running into the "too big for my head" block.

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Personally, I like maps. So I would probably start with an Entity Relationship Diagram. After that, I would probably do some kind of interaction diagram.

      I have been at that place before, it does help to have a map just to keep straight in my brain where in the code I am.
      I would still document each class seperately, pointing out when it takes instances of your other classes as parameters - eg "this method takes named parameters. The 'bar' parameter is required, and must be a Bar object, the 'baz' parameteris optional ...". Document what the method does, including how it interacts with the objects passed to it. However, if any of those objects in turn do stuff to other objects, that is properly documented in their docs, not in the ones for the original class.

      As for documenting inheritance, that's pretty simple. Something like this, perhaps:

      =head1 INHERITANCE This module inherits methods from Foo and Bar =head1 METHODS The following methods override methods in Foo: ... The following methods override methods in Bar: ... The following methods are additionally defined: ...
      If you end up inheriting the same method name from two seperate base classes, then I suggest that you provide your own implementation which explicitly calls the correct base method, and you should also document that prominently.

      So you will end up with a bunch of docs explaining what each method of each class does and how those methods interact with the outside world. From that, you can write your tests and it will probably now be a lot clearer to you what all the interactions are. Then some documentation covering very briefly what each class does and what it represents, and what their interdependencies are should be quite easy to write. You might be able to draw a diagram for that if it's reasonable simple - and if you can, do so, as pictures convey an awful lot more information than words in this situation. I believe there are automated tools for doing this, such as Autodia, although I don't use such things myself, preferring to grovel over the docs and draw on real paper with a real pencil ;-)