Testing the World Away: Recovery mission





0/5 (0 vote)
No technique can stop testing from being a fag.
I was recently reviewing the DUnit website and I noticed there is a broken link to an article titled “Testing The World Away”. It was written by Will Watts for QBS Software. November, 2000.
I said “OK, maybe the article was relocated somewhere else in the QBS Software website”; so I tried a custom Google search "Testing the World Away" site:qbssoftware.com. As you can see the article was either banned from Google or removed completely from the QBS Software website.
Once again I said “OK, maybe there’s a copy of the article somewhere else on the Internet” and I tried a second custom Google search "Testing the World Away". At this point I convinced myself that the article was gone for good.
I am a curious guy, so I tried one final thing: I looked up the broken link[1] in the Internet Archive website and wallah!, they came with an archived version of the article.
I have shared below a copy of the article so that we can take a look. As I said, this article is not mine, and if the author(owner) at some point request me to deleted it from my blog, I will do so.
[1] http://www.qbss.com/html/news/news_body.asp?content=ARTICLE&link=368&zone=
Testing the World Away (01 November 2000)
Testing the World Away
Mr Beck has had brushes with those GUI automated tools that record keystrokes and mouse-clicks into some sort of script and then let you play your actions back at the application to be tested and verify its responses. These look like they are going to do the job from the description on the packet but in practice, as Mr Beck correctly observes, they are not very robust. Remove one edit box, or merely nudge it three pixels to the right, or change the screen resolution - suddenly the whole thing falls flat on its face. Testing code, he decided, should be written at the same level and in the same language as the stuff to be tested.
Tests also need structure. One needs to see results presented in a consistent way, to be able to select specific tests to run and so on. To this end, Mr Beck wrote a library of Smalltalk classes - a framework - called ‘SmalltalkUnit’ or ‘SUnit’. Later on he collaborated with no less than Erich Gamma to produce a Java version called ‘JUnit’. The idea ‘took on’, and now there are versions for an impressive range of languages including C++, Eiffel, Objective-C, Perl, Python, Visual Basic and even Visual Objects. You'll find them all listed at http://www.xprogramming.com/software.htm. If you are familiar with my language prejudices, you will be unsurprised to learn that I am going to discuss a Delphi language version called DUnit. Originally ported from the Java version by Juancarlo Añez, this library is now maintained on an Open Source basis by the DUnit group at SourceForge:
https://sourceforge.net/projects/dunit/. This library makes heavy use of function overloading, so you’ll need Delphi 4 or later to play with it.
Who DUnit?
Figure 1 shows a suite of DUnit tests that have been run using the library’s GUI interface. The top pane lists all the tests available. These are organised in a hierarchy: a suites of tests may contain either individual test cases or other suites - a Composite pattern. In the part of the hierarchy visible, I have set up a suite called ‘SFW COM Library tests’ that, in turn, contains suites subdivided by the class being tested. The TTestDoubleChannel
suite operates on a class called TDoubleChannel
, and below TTestDoubleChannel
are tests on individual methods. There are checkboxes to switch individual tests and parts of the hierarchy on and off; these interact with some useful buttons at the bottom of the dialog to allow speedy selection of all or part of the suite.
Each test is colour-coded by the result of the last run. Green, obviously, indicates success; magenta a ‘failure’, that is that an unexpected result was obtained; red, an ‘error’, that the test threw an exception. The lower pane lists all the failures and errors together with descriptive messages. In between the two panes are progress bars indicating progress through the test suite and success rate.
How it works
First look at the Project1TestCases.pas unit. TTestCaseFirst is derived from TTestCase, adding one published method testFirst. Three features of this method are important: that it is a parameterless procedure, that it has public scope, and that its name begins ‘test…’. These features enable DUnit to discover and run the method without the need to call it explicitly in hand-generated code. It is sufficient to declare a method of a TTestCase-derived class that follows these rules to get it run.
The implementation of testFirst is a single line: I ‘assert’ that 1 + 1 = 2. (Old Delphi hands and practitioners of design-by-contract may be raising their eyebrows at this strange use of Assert. Please bear with me, explanations and excuses will follow in due course.)
At the bottom of Project1TestCases.pas, in an initialization section, is the call registerTest('', TTestCaseFirst); which registers TTestCaseFirst with the framework. The first parameter is the ‘path’, it controls where a test case appears in the hierarchy. By supplying an empty string I am placing it below the root node.
The project file Project1Test.dpr references DUnit library units TestFrameWork and GUITestRunner as well as Project1TestCases.pas. A single line replaces the standard Delphi GUI project code: GUITestRunner.runTest(TestFramework.registeredTests);
This creates and displays the GUI interface shown in Figure 1. And that’s it. To add further arithmetic tests, just write extra test… methods, for example:
procedure TTestCaseFirst.testSecond;
begin
Assert(2 + 2 = 5, 'Oops!');
end;
In reality one uses DUnit on classes rather than trivial arithmetic. Instances of classes can be placed as member data in the
TTestCase
-derived class, and two virtual methods, SetUp
and
TearDown
, can be overridden to create and destroy them around each test method. Figure 4 sketches how this is done. Note that
SetUp
is called before, and TearDown
after, each test method. This isolation of the test methods from each other is deliberate - you shouldn’t build a sequence of tests where one method is dependant on those called before. I mentioned DUnit’s ability to build up suites from multiple test cases. This is accomplished using the
TTestSuite
class:
Suite := TTestSuite.create('A suite');
Suite.addTests(TTestCaseFirst);
Suite.addTests(TTestCaseMyClass);
registerTest
as before.All About Assert
However, there is a move afoot among the DUnit developers to change the function's name, probably to Check, and also to add a family of useful overloaded methods with names like CheckEqual
, CheckNotEqual
and so on. With luck this will have gone through by the time you read this.
DUnit is very much work-in-progress, and there are a number of interesting additions and enhancements coming into view. Two add-ons have just been released - one standalone, one integrated with the IDE enhancer CodeRush - which will generate skeleton test case code from the declaration of a class that is to be tested. As well as extra facilities for test repetition and set-up that I have not covered here, there are also plans to add special support for databases, multi-threading and GUI testing.
No technique can stop testing from being a fag. But I have found that the accumulation of a permanent test suite, and the improved confidence in my code developed in this way make DUnit’s use worthwhile. Go on: pull it down and have a go!
Will Watts is a programmer and occasional journo who lives in Chiswick. To his pleasure, his Snobol column in Developers Review has not, as far as he knows, been nominated for the Worst IT Journalism 2000 Award.
Books: Extreme Programming Explained by Kent Beck, pub Addison-Wesley, ISBN 0-201-61641-6. Mr Beck’s philosophy of software development.
Refactoring - Improving the Design of Existing Code by Martin Fowler et al, pub Addison-Wesley, ISBN 0-201-48567-2.
Includes good description of JUnit.