First, I create a project directory account.
Next, I create some test code -- not the account code! I start by
testing something very basic, e.g., that a new account
has a zero balance. In CppUnit, the essence of that test is:
Account acct;
CPPUNIT_ASSERT_EQUAL( 0, acct.getBalance() );
This creates a default account object in acct, then
checks that the balance is 0.
I have to put this inside boilerplate code that creates
what is called a test fixture. This boilerplate takes
care of running the tests and printing the results. I use
this simple CppUnit template
as a guide to make this test file:
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/ui/text/TestRunner.h>
class AccountTests : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE( AccountTests );
CPPUNIT_TEST( testConstructor );
CPPUNIT_TEST_SUITE_END();
public:
void testConstructor()
{
Account acct;
CPPUNIT_ASSERT_EQUAL( 0, acct.getBalance() );
}
};
int main( int argc, char **argv)
{
CppUnit::TextUi::TestRunner runner;
runner.addTest( AccountTests::suite() );
runner.run();
return 0;
}
Now to compile and run the tests.
At this point, you may say "Whoops! You forgot
to write the account code!"
No, I didn't. A key part of TDD is to test
before coding.
The only way to know if
a test works is to see it fail first.
If you write the code before running the tests,
and the tests pass, maybe the tests are broken and
always pass. This
happens far more often than you think. Always run the tests before
writing or changing any code to make sure the tests are actually testing
what you think they do.
To run the tests, I need this Makefile:
In this case, the test file doesn't even compile.
So now I write just
enough code to make an empty bank account, and no more.
Here's my Account.h file:
Here's my Account.cpp file:
I add Account.cpp and Account.h
to my Makefile:
I try to build again. Compiles fine, except for the
expected Cygwin warning.
Time to run the tests by typing ./account.exe.
Ooops! They failed.
Ah -- I forgot to initialize the balance. I'll use
a member initializer list because that's best practice.
Try again... Yay! My test passes. Time to write some new tests for
some new functionality.