diff options
author | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-04-21 09:57:52 +0000 |
---|---|---|
committer | Baptiste Lepilleur <gaiacrtn@free.fr> | 2002-04-21 09:57:52 +0000 |
commit | ca5f94534beb3fb395a397a2fe991f4c64fb2f84 (patch) | |
tree | 1ab95c541266dc554500d201865f683616a11dbc /doc | |
parent | aa3e46e802dc5139e3e2c32e6a00526697e8a0aa (diff) | |
download | cppunit-ca5f94534beb3fb395a397a2fe991f4c64fb2f84.tar.gz |
Src/DllPlugInTester/makefile.
src/DllPlugInTester/makefile.am: removed ld.so from LDADD flags.
* src/DllPlugInTester/CommandLineParser.h:
* src/DllPlugInTester/CommandLineParser.cpp: rewrote, fixed problem
with double quotes in command line...
* src/DllPlugInTester/CommandLineParserTest.h:
* src/DllPlugInTester/CommandLineParserTest.cpp:
* src/DllPlugInTester/DllPlugInTesterTest.cpp: added, unit tests for
CommandLineParser.
* src/msvc6/TestPlugIn/*: removed.
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Doxyfile.in | 2 | ||||
-rw-r--r-- | doc/Makefile.am | 2 | ||||
-rw-r--r-- | doc/Money.dox | 558 | ||||
-rw-r--r-- | doc/other_documentation.dox | 3 |
4 files changed, 563 insertions, 2 deletions
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index c0e062b..8b73ca3 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -218,7 +218,7 @@ WARN_FORMAT = "$file:$line: $text" # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = @top_srcdir@/include @top_srcdir@/src/cppunit @srcdir@/other_documentation.dox @srcdir@/cookbook.dox +INPUT = @top_srcdir@/include @top_srcdir@/src/cppunit @srcdir@/other_documentation.dox @srcdir@/cookbook.dox @srcdir@/Money.dox # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/doc/Makefile.am b/doc/Makefile.am index 633766e..aca44d3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = $(doxygen_input) $(static_pages) -doxygen_input = cookbook.dox other_documentation.dox header.html footer.html +doxygen_input = cookbook.dox other_documentation.dox header.html footer.html Money.dox static_pages = FAQ diff --git a/doc/Money.dox b/doc/Money.dox new file mode 100644 index 0000000..bf0111e --- /dev/null +++ b/doc/Money.dox @@ -0,0 +1,558 @@ +/*! \page money_example Money, a step by step example + +\section Table of contents + + - \ref sec_setting_vc + - \ref sec_setting_unix + - \ref sec_running_test + - \ref sec_adding_testfixture + - \ref sec_first_tests + - \ref sec_more_tests + - \ref sec_credits + + The example explored in this article can be found in \c examples/Money/. + + + +\section sec_setting_vc Setting up your project (VC++) + +\subsection sec_install Compiling and installing CppUnit libaries + +In the following document, $CPPUNIT is the directory where you unpacked %CppUnit: +$CPPUNIT/: + include/ + lib/ + src/ + cppunit/ + +First, you need to compile %CppUnit libraries: +- Open the $CPPUNIT/src/CppUnitLibraries.dsw workspace in VC++. +- In the 'Build' menu, select 'Batch Build...' +- In the batch build dialog, select all projects and press the build button. +- The resulting libraries can be found in the $CPPUNIT/lib/ directory. + +Once it is done, you need to tell VC++ where are the includes and librairies +to use them in other projects. Open the 'Tools/Options...' dialog, and in the +'Directories' tab, select 'include files' in the combo. Add a new entry that +points to $CPPUNIT/include/. Change to 'libraries files' in the combo and +add a new entry for $CPPUNIT/lib/. Repeat the process with 'source files' +and add $CPPUNIT/src/cppunit/. + +\subsection sec_getting_started Getting started + +Creates a new console application ('a simple application' template will do). +Let's link %CppUnit library to our project. In the project settings: +- In tab 'C++', combo 'Code generation', set the combo to 'Multithreaded DLL' +for the release configuration, and 'Debug Multithreaded DLL' for the debug +configure, +- In tab 'C++', combo 'C++ langage', for All Configurations, check +'enable Run-Time Type Information (RTTI)', +- In tab 'Link', in the 'Object/library modules' field, add cppunitd.lib for +the debug configuration, and cppunit.lib for the release configuration. + +We're done ! + + + + + + + +\section sec_setting_unix Setting up your project (Unix) +We'll use \c autoconf and \c automake to make it simple to +create our build environment. Create a directory somewhere to +hold the code we're going to build. Create \c configure.in and +\c Makefile.am in that directory to get started. + +<tt>configure.in</tt> +\verbatim +dnl Process this file with autoconf to produce a configure script. +AC_INIT(Makefile.am) +AM_INIT_AUTOMAKE(money,0.1) +AM_PATH_CPPUNIT(1.9.6) +AC_PROG_CXX +AC_PROG_CC +AC_PROG_INSTALL +AC_OUTPUT(Makefile)\endverbatim + +<tt>Makefile.am</tt> +\verbatim +# Rules for the test code (use `make check` to execute) +TESTS = MoneyApp +check_PROGRAMS = $(TESTS) +MoneyApp_SOURCES = Money.h MoneyTest.h MoneyTest.cpp MoneyApp.cpp +MoneyApp_CXXFLAGS = $(CPPUNIT_CFLAGS) +MoneyApp_LDFLAGS = $(CPPUNIT_LIBS) +MoneyApp_LDFLAGS = -ldl\endverbatim + + + + + + + + +\section sec_running_test Running our tests + +We have a main that doesn't do anything. Let's start by adding the mecanics +to run our tests (remember, test before you code ;-) ). For this example, +we will use a TextTestRunner with the CompilerOutputter for post-build +testing: + +<tt>MoneyApp.cpp</tt> +\code +#include "stdafx.h" +#include <cppunit/CompilerOutputter.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> + + +int main(int argc, char* argv[]) +{ + // Get the top level suite from the registry + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + // Adds the test to the list of test to run + CppUnit::TextUi::TestRunner runner; + runner.addTest( suite ); + + // Change the default outputter to a compiler error format outputter + runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), + std::cerr ) ); + // Run the tests. + bool wasSucessful = runner.run(); + + // Return error code 1 if the one of test failed. + return wasSucessful ? 0 : 1; +}\endcode + + VC++: Compile and run (Ctrl+F5). + + Unix: First build. Since we don't have all the file yet, let's create them + and build our application for the first time: +\verbatim +touch Money.h MoneyTest.h MoneyTest.cpp +aclocal -I /usr/local/share/aclocal +autoconf +automake -a +touch NEWS README AUTHORS ChangeLog # To make automake happy +./configure +make check\endverbatim + + Our application will report that everything +is fine and no test were run. So let's add some tests... + + + +\subsection sec_post_build Setting up automated post-build testing (VC++) + +What does post-build testing means? It means that each time you compile, +the test are automatically run when the build finish. This is very +useful, if you compile often you can know that you just 'broke' something, +or that everything is still working fine. + +Let's adds that to our project, In the project settings, in the +'post-build step' tab: +- Select 'All configurations' (upper left combo) +- In the 'Post-build description', enter 'Unit testing...' +- In 'post-build command(s)', add a new line: <tt>\$(TargetPath)$</tt> + +<tt>\$(TargetPath)</tt> expands into the name of your application: +Debug\MoneyApp.exe in debug configuration and Release\MoneyApp.exe in release +configuration. + +What we are doing is say to VC++ to run our application for each build. +Notices the last line of \c main(), it returns a different error code, +depending on weither or not a test failed. If the code returned by +an application is not 0 in post-build step, it tell VC++ that the build +step failed. + +Compile. Notices that the application's output is now in the build window. +How convenient! + + (Unix: tips to integrate make check into various IDE?) + + + + + + + +\section sec_adding_testfixture Adding the TestFixture + +For this example, we are going to write a simple money class. Money +has an amount and a currency. Let's begin by creating a fixture where +we can put our tests, and add single test to test Money constructor: + +<tt>MoneyTest.h:</tt> +\code +#ifndef MONEYTEST_H +#define MONEYTEST_H + +#include <cppunit/extensions/HelperMacros.h> + +class MoneyTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( MoneyTest ); + CPPUNIT_TEST( testConstructor ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testConstructor(); +}; + +#endif // MONEYTEST_H\endcode + +- CPPUNIT_TEST_SUITE declares that our Fixture's test suite. +- CPPUNIT_TEST adds a test to our test suite. The test is implemented +by a method named testConstructor(). +- setUp() and tearDown() are use to setUp/tearDown some fixtures. We are +not using any for now. + +<tt>MoneyTest.cpp</tt> +\code +#include "stdafx.h" +#include "MoneyTest.h" + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION( MoneyTest ); + + +void +MoneyTest::setUp() +{ +} + + +void +MoneyTest::tearDown() +{ +} + + +void +MoneyTest::testConstructor() +{ + CPPUNIT_FAIL( "not implemented" ); +} +\endcode + +Compile. As expected, it reports that a test failed. Press the \c F4 key +(Go to next Error). VC++ jump right to our failed assertion CPPUNIT_FAIL. +We can not ask better in term of integration! +\verbatim +Compiling... +MoneyTest.cpp +Linking... +Unit testing... +.F +G:\prg\vc\Lib\cppunit\examples\money\MoneyTest.cpp(26):Assertion +Test name: MoneyTest.testConstructor +not implemented +Failures !!! +Run: 1 Failure total: 1 Failures: 1 Errors: 0 +Error executing d:\winnt\system32\cmd.exe. + +moneyappd.exe - 1 error(s), 0 warning(s) +\endverbatim + +Well, we have everything set up, let's start doing some real testing. + + + + + + + +\section sec_first_tests Our first tests + +Let's write our first real test. A test is usually decomposed in three parts: +- setting up datas used by the test +- doing some processing based on those datas +- checking the result of the processing + +\code +void +MoneyTest::testConstructor() +{ + // Set up + const std::string currencyFF( "FF" ); + const double longNumber = 12345678.90123; + + // Process + Money money( longNumber, currencyFF ); + + // Check + CPPUNIT_ASSERT_EQUAL( longNumber, money.getAmount() ); + CPPUNIT_ASSERT_EQUAL( currencyFF, money.getCurrency() ); +}\endcode + +Well, we finally have a good start of what our Money class will +look likes. Let's start implementing... + +<tt>Money.h</tt> +\code +#ifndef MONEY_H +#define MONEY_H + +#include <string> + +class Money +{ +public: + Money( double amount, std::string currency ) + : m_amount( amount ) + , m_currency( m_currency ) + { + } + + double getAmount() const + { + return m_amount; + } + + std::string getCurrency() const + { + return m_currency; + } + +private: + double m_amount; + std::string m_currency; +}; + +#endif\endcode + +Include <tt>Money.h</tt> in MoneyTest.cpp and compile. + +Hum, an assertion failed! Press F4, and we jump to the assertion +that checks the currency of the constructed money object. The report +indicates that string is not equal to expected value. There is only +two ways for this to happen: the member was badly initialized or we +returned the wrong value. After a quick check, we fin out it is the former. +Let's fix that: + +<tt>Money.h</tt> +\code + Money( double amount, std::string currency ) + : m_amount( amount ) + , m_currency( currency ) + { + }\endcode + +Compile. Our test finally pass! +Let's add some functionnalities to our Money class. + + + + + + + + +\section sec_more_tests Adding more tests + +\subsection sec_equal Testing for equality + + We want to check if to Money object are equal. Let's start by adding +a new test to the suite, then add our method: + +<tt>MoneyTest.h</tt> +\code + CPPUNIT_TEST_SUITE( MoneyTest ); + CPPUNIT_TEST( testConstructor ); + CPPUNIT_TEST( testEqual ); + CPPUNIT_TEST_SUITE_END(); +public: + ... + void testEqual(); +\endcode + +<tt>MoneyTest.cpp</tt> +\code +void +MoneyTest::testEqual() +{ + // Set up + const Money money123FF( 123, "FF" ); + const Money money123USD( 123, "USD" ); + const Money money12FF( 12, "FF" ); + const Money money12USD( 12, "USD" ); + + // Process & Check + CPPUNIT_ASSERT( money123FF == money123FF ); // == + CPPUNIT_ASSERT( money12FF != money123FF ); // != amount + CPPUNIT_ASSERT( money123USD != money123FF ); // != currency + CPPUNIT_ASSERT( money12USD != money123FF ); // != currency and != amount +}\endcode + + Let's implements \c operator \c == and \c operator \c != in Money.h: + +<tt>Money.h</tt> +\code +class Money +{ +public: +... + bool operator ==( const Money &other ) const + { + return m_amount == other.m_amount && + m_currency == other.m_currency; + } + + bool operator !=( const Money &other ) const + { + return (*this == other); + } +}; +\endcode + + Compile, run... Ooops... Press F4, it seems we're having trouble +with \c operator \c !=. Let's fix that: +\code + bool operator !=( const Money &other ) const + { + return !(*this == other); + }\endcode + +Compile, run. Finaly got it working! + + + +\subsection sec_opadd Adding moneys + + Let's add our test 'testAdd' to MoneyTest. You know the routine... + +<tt>MoneyTest.cpp</tt> +\code +void +MoneyTest::testAdd() +{ + // Set up + const Money money12FF( 12, "FF" ); + const Money expectedMoney( 135, "FF" ); + + // Process + Money money( 123, "FF" ); + money += money12FF; + + // Check + CPPUNIT_ASSERT_EQUAL( expectedMoney == money.getAmount() ); // += works + CPPUNIT_ASSERT( &money == &(money += money12FF) ); // += returns ref. on 'this'. +}\endcode + + While writing that test case, you ask yourself, what is the result of +adding money of currencies. Obviously this is an error and it should be +reported, say let throw an exception, say \c IncompatibleMoneyError, +when the currencies are not equal. We will write another test case +for this later. For now let get our testAdd() case working: + +<tt>Money.h</tt> +\code +class Money +{ +public: +... + Money &operator +=( const Money &other ) + { + m_amount += other.m_amount; + return *this; + } +}; \endcode + +Compile, run. Miracle, everything is fine! Just to be sure the test is indeed +working, in the above code, change \c m_amount \c += to \c -=. Build and +check that it fails (always be suspicious of test that work the first +time: you may have forgotten to add it to the suite for example)! +Change the code back so that all the tests are working. + + Let's the incompatible money test case before we forget about it... +That test case expect an \c IncompatibleMoneyError exception to be thrown. +%CppUnit can test that for us, you need to specify that the test case +expect an exception when you add it to the suite: + +<tt>MoneyTest.h</tt> +\code +class MoneyTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( MoneyTest ); + CPPUNIT_TEST( testConstructor ); + CPPUNIT_TEST( testEqual ); + CPPUNIT_TEST( testAdd ); + CPPUNIT_TEST_EXCEPTION( testAddThrow, IncompatibleMoneyError ); + CPPUNIT_TEST_SUITE_END(); +public: + ... + void testAddThrow(); +};\endcode + +By convention, you ends the name of such tests with \c 'Throw', that way, you +know that the test expect an exception to be thrown. Let's write our test case: + +<tt>MoneyTest.cpp</tt> +\code +void +MoneyTest::testAddThrow() +{ + // Set up + const Money money123FF( 123, "FF" ); + + // Process + Money money( 123, "USD" ); + money += money123FF; // should throw an exception +} +\endcode + + Compile... Ooops, forgot to declare the exception class. Let's do that: + +<tt>Money.h</tt> +\code +#include <string> +#include <stdexcept> + +class IncompatibleMoneyError : public std::runtime_error +{ +public: + IncompatibleMoneyError() : runtime_error( "Incompatible moneys" ) + { + } +}; +\endcode + + Compile. As expected testAddThrow() fail... Let's fix that: + +<tt>Money.h</tt> +\code + Money &operator +=( const Money &other ) + { + if ( m_currency != other.m_currency ) + throw IncompatibleMoneyError(); + + m_amount += other.m_amount; + return *this; + }\endcode + + Compile. Our test finaly pass! + + TODO: +- Copy constructor/Assigment operator +- Introducing fixtures +- ? + + + + + + +\section sec_credits Credits +This article was written by Baptiste Lepilleur. Unix configuration & set up +by Phil Verghese. Inspired from many others (JUnit, Phil's cookbook...), +and all the newbies around that keep asking me for the +'Hello world' example ;-) + + + +*/
\ No newline at end of file diff --git a/doc/other_documentation.dox b/doc/other_documentation.dox index 5b6f3df..78cfe7b 100644 --- a/doc/other_documentation.dox +++ b/doc/other_documentation.dox @@ -17,6 +17,9 @@ testing framework. <a href="modules.html">Modules</a> give you a organized view of %CppUnit classes. + (Notes to newbies, you may want to check out \ref money_example, + a work in progress, but the project is provided with %CppUnit). + For a discussion on %CppUnit, check <a href="http://c2.com/cgi/wiki?CppUnit"> the WikiWiki Pages on CppUnit</a>. There you can also |