[Cppunit-devel] class overview I: defining tests
Brought to you by:
blep
From: Steve M. R. <ste...@vi...> - 2001-07-08 03:53:08
|
In response to Baptiste's message about reorganizing include/, I expressed a desire to understand the overall structure of CppUnit. I have gleaned some information from Baptiste's response and from poring over the code. With this summary (in two parts) of what I've learned so far, I'm hoping to provoke some more discussion. I'm ignoring the assertions and helper macros, for now. Suppose I want to incorporate testing into my software. There are two fundamental operations that need to be supported by the CppUnit testing framework. First, I need to define the tests. Second, I need to execute them and report results. This message deals with classes of the first category. A companion message deals with classes for reporting results. class Test ---------- CppUnit has a small hierarchy of classes rooted at class Test. Test is a pure virtual class with no implementation code. I will assume it is intended to be an interface class. By this I mean it exists only to define the interface that a "test-like" classes must implement. If we were writing Java, it would be an interface. The Test interface has one principal method: void run( TestResult* res ) - run the test and collect the results in res class TestCase -------------- The concrete class that represents a test should be TestCase. In fact, however, TestCase is a framework to define one OR MORE tests. The detailed description of TestCase says it defines the "fixture to run multiple tests". The term "fixture" is bothering me. The documentation suggests that a TestCase _is_ a fixture. If so, why have two terms? Does the word "fixture" have a standardized meaning? TestCase is a subclass of Test, and implements run() as setUp() runTest() tearDown() According to the "cookbook", a TestCase object is intended as the basic mechanism for defining a test. One should subclass TestCase overriding runTest() appropriately. The code in runTest() would typically make a number of assertions. class TestSuite --------------- Straightforward collection of Test objects. The run() method calls run() on each member of the collection in turn. class TestCaller ---------------- Here is where I really start getting muddled. A TestCaller is a subclass of TestCase that "provides access to a test case method". Although nowhere clarified in the docs, "a test case method" appears to refer to any member function of a TestCase that takes no parameters and returns void. All through the TestCaller documentation, the term "fixture" is used to mean "a TestCase instance". As near as I can tell, a TestCaller exists so that one can subclass a TestCase, define a number of "void foo(void)" methods in it, and then use a TestCaller to make an individual test case out of each such method. I'm confused now as to whether an object of type TestCase should be a single test case or a set of related test cases. The name suggests it is a single test case. However, the TestCaller class appears to promote the practice of defining a set of related tests in a TestCase, and then generating a test case (TestCaller) for each. In addition, the TestCaller class is able to ignore an "expected" exception in its runTest() method. This is a useful facility! Why is it not available in the base TestCase class? classes TestDecorator, RepeatedTest, TestSetUp ---------------------------------------------- TestDecorator and RepeatedTest are straightforward. TestSetUp is a mystery, though. It appears very similar to the TestCase class in that it wraps the Test::run() method with virtual setUp() and tearDown() methods. But it doesn't do any catching of exceptions like TestCase does. What is the purpose of this class? -Steve -- by Rocket to the Moon, by Airplane to the Rocket, by Taxi to the Airport, by Frontdoor to the Taxi, by throwing back the blanket and laying down the legs ... - They Might Be Giants |