    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Developing a C++ Unit Testing Framework</title>
        <link>https://members.accu.org/index.php/articles/368</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #52 - Dec 2002</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c191/">52</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-191/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+191/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Developing a C++ Unit Testing Framework</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 02 August 2002 22:57:50 +01:00 or Fri, 02 August 2002 22:57:50 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id=
"d0e18"></a>Introduction</h2>
</div>
<p>Testing is an important part of all software development, yet a
part that is so often overlooked or skimped on. Why is this?
Perhaps it's because testing software is not considered exciting,
or perhaps it's because it's not trivial, and if we're honest with
ourselves it's impossible to write a set of tests that's perfect,
the only way of knowing a test works is if it shows that the
software doesn't. Passing all the tests does not mean the software
is perfect, it may mean your tests just aren't good enough.</p>
<p>As the title suggests I'm going to look solely at unit testing,
as it's currently something I'm focused on, having adopted Extreme
Programming (XP) [<a href="#XP">XP</a>]. So what is unit testing?
To us it's testing individual software units to prove that they
work as specified. In our case, tests may well form part of that
specification, as XP is pro Test First programming, whereby we
write our tests before writing the code, and we stop writing the
code when all the tests pass. As such tests are both a way of
ensuring quality and a way of measuring the status of our
development. It's always worth remembering (and reminding the boss)
that the sooner problems are found, the cheaper they are to fix.
Tests formalise the testing process, they move it from just running
the debugger and seeing what happens, to a structured, repeatable
process. To encourage regular running of the tests, they should be
quick and easy to use, in other words, fully automated. This will
help you to get unit testing accepted as part of your personal and
company development culture.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e28" id=
"d0e28"></a>Prerequisites</h2>
</div>
<p>Ok, so you see a benefit to unit testing, or at least I assume
you do otherwise you'd probably have stopped reading by now. What
do we need to begin developing effective unit tests? Happily not
much, consider the following example:</p>
<pre class="programlisting">
  bool isZero(long value) {
    return value == 0;
  }
</pre>
<p>Which we can test with the following code:</p>
<pre class="programlisting">
  #include &lt;iostream&gt;
  int main() {
    if ((isZero(0)) &amp;&amp; (!isZero(1))) {
      std::cout &lt;&lt; &quot;Passed.&quot; &lt;&lt; std::endl;
    }
    else {
      std::cout &lt;&lt; &quot;Failed.&quot; &lt;&lt; std::endl;
    }
  }
</pre>
<p>However not all code is as simple to test, nor do we want to
have to repeat the basic features that all tests share. The ability
to report the success or failure of the test is the most obvious
feature that we'll be requiring again. We'll also probably want to
test the function with more than two inputs, and a massive
conditional statement is not clean, maintainable and readable. It
would be very nice to know which part of the test failed, and which
resulted in an error. It would be useful if we were able to run the
tests on application start-up, choosing to run all the tests or a
specified subset. Finally, unlike many C++ testing frameworks, we
won't assume that the user will only ever test classes.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e41" id="d0e41"></a>Building our
Framework</h2>
</div>
<p>Let's start by changing the code to allow for our first
prerequisite, which is to easily allow testing with multiple
inputs. Firstly we'll add a function to determine if the test
succeeded, and record the result:</p>
<pre class="programlisting">
  void Test(bool eval, bool&amp; result) {
    if (result) {
      result = eval;
    }
  }
</pre>
<p>I've chosen to implement it this way so a pass after a failure
will not overwrite the failure, in other words if <i class=
"parameter"><tt>result</tt></i> is already false we don't lose the
failure when the next test passes. We can then change main to the
following:</p>
<pre class="programlisting">
  int main() {
    long const max_test = 100;
    bool result = false;
    Test(isZero(0), result);
    for (int i = 1; i &lt; max_test; ++i) {
      Test(!isZero(i), result);
    }
    if (result) {
      std::cout &lt;&lt; &quot;Passed.&quot; &lt;&lt; std::endl;
    }
    else {
      std::cout &lt;&lt; &quot;Failed.&quot; &lt;&lt; std::endl;
    }
  }
</pre>
<p>Which allows us to test the function for potentially all
possible positive values of a long (if we changed <tt class=
"varname">max_test</tt> to be <tt class=
"literal">std::numeric_limits&lt;long&gt;::max()</tt>). Ok, so
we're now able to run multiple tests, but should it fail, it would
be very helpful to know which part failed. So how could we do that?
Well, we could stop on the first failure, but we probably don't
want to stop the entire unit test, so it's time to break our test
down a little and practice some of our procedural/object-oriented
design. We can start by changing the result to a structure as
follows:</p>
<pre class="programlisting">
  struct test_result {
    bool passed;
    unsigned long line;
    std::string file;
  };
</pre>
<p>We will then change the test function to set these additional
values:</p>
<pre class="programlisting">
  void Test(bool eval,
            const char* file,
            unsigned long line,
            test_result&amp; result) {
    result.passed = eval;
    if (!result.passed) {
      result.file = file;
      result.line = line;
    }
  }
</pre>
<p>We'll also need to call the function differently (I've changed
it to only print out failures, to reduce the clutter, and
introduced a failed test) so our final program becomes:</p>
<pre class="programlisting">
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  
  // . . . code . . .

  int main() {
    long const max_test = 100;
    test_result results[max_test];
    Test(!isZero(0), __FILE__, __LINE__, results[0]); // fails 0 is zero!

    for (int i = 1; i &lt; max_test; ++i) {
      Test(!isZero(i), __FILE__, __LINE__,results[i]);
    }

    for (int i = 0; i &lt; max_test; ++i) {
      if (!results[i].passed) {
        std::cout &lt;&lt; &quot;Test failed in file &quot;
                  &lt;&lt; results[i].file &lt;&lt; &quot; on line &quot;
                  &lt;&lt; results[i].line &lt;&lt; std::endl;
      }
    }
  }
</pre>
<p>Ok, so far so good, however it's rather tedious to have to add
<tt class="literal">__FILE__, __LINE__</tt> to each call, and not
terribly pretty either, so I'm going to pull them out, and use a
macro (don't look so horrified) to save us the effort. We'll call
the macro <tt class="literal">ASSERT_TEST()</tt>, just because
that's a common naming style in testing frameworks. We'll define it
as so:</p>
<pre class="programlisting">
  #define ASSERT_TEST(condition, result) Test(condition, __FILE__, __LINE__, result)
</pre>
<p>However, having decided to use a macro we can now use a bit of
magic to get the actual code that failed and print that as part of
our diagnostics, so here's the new macro, with the <span class=
"returnvalue">test_result</span> structure changed to accommodate
the new information and the <tt class="function">Test()</tt>
function renamed to <tt class="function">assertImpl()</tt>:</p>
<pre class="programlisting">
  #include &lt;iostream&gt;
  #include &lt;string&gt;

  struct test_result {
    bool passed;
    unsigned long line;
    std::string file;
    std::string code;
  };

  bool isZero(long value) {
    return value == 0;
  }

  void assertImpl(bool eval, char* code,
                  char* file, unsigned long line,
                  test_result&amp; result) {
    result.passed = eval;
    if (!result.passed) {
      result.file = file;
      result.line = line;
      result.code = code;
    }
  }

  #define ASSERT_TEST(condition, result) \
  assertImpl(condition, #condition, __FILE__, __LINE__, result)

  int main() {
    long const max_test = 100;
    test_result results[max_test];
    ASSERT_TEST(!isZero(0), results[0]);
    // fails 0 is zero!
    for (int i = 1; i &lt; max_test; ++i) {
      ASSERT_TEST(!isZero(i), results[i]);
    }
    for (int i = 0; i &lt; max_test; ++i) {
      if (!results[i].passed) {
        std::cout &lt;&lt; &quot;Test &quot;
                  &lt;&lt; results[i].code
                  &lt;&lt; &quot; failed in file &quot;
                  &lt;&lt; results[i].file
                  &lt;&lt; &quot; on line &quot;
                  &lt;&lt; results[i].line
                  &lt;&lt; std::endl;
      }
    }
  }
</pre>
<p>Having used our little bit of macro magic (for those that feel
it's voodoo read [<a href="#KandR88">KandR88</a>] page 90), it's
time to start thinking about how we can scale this up.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e101" id="d0e101"></a>Refactoring
into Classes</h2>
</div>
<p>At this stage it is worth reviewing our requirements for a C++
testing framework:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>We need to know if a test failed.</p>
</li>
<li>
<p>If a test failed we want the code for the test, the name of the
file it is in, and the line it is on.</p>
</li>
<li>
<p>We want to be able to test multiple conditions in each test,
failure of any single condition is a failure for the test.</p>
</li>
<li>
<p>Failed test(s) should not stop the rest of the test running.</p>
</li>
<li>
<p>We want a report on the test results, after all tests have
run.</p>
</li>
<li>
<p>We may need to be able to set up some data before a test, and
destroy it afterwards.</p>
</li>
<li>
<p>We should cope with exceptions.</p>
</li>
<li>
<p>The testing framework must be easy to use, as part of which we
will implement our code in the <tt class="literal">test</tt>
namespace.</p>
</li>
</ul>
</div>
<p>We might also want the following information at some stage in
the future:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>Duration of each test.</p>
</li>
<li>
<p>Free/Used memory before and after the test.</p>
</li>
<li>
<p>Log results to file.</p>
</li>
</ul>
</div>
<p>Ok, lets take these one at a time starting with the easiest, the
test result. We've already solved this the easy way with our
<tt class="literal">test_result</tt> structure. So we'll dive right
in and do the whole lot:</p>
<pre class="programlisting">
  class TestResultCollection {
 
  public:
    void error(const std::string&amp; err);
    void fail(const std::string&amp; code,
    const char* file, size_t line);
    unsigned long failedCount() const;
    void reportError(std::ostream&amp; out) const;
    void reportFailures(std::ostream&amp; out) const;
  
  private:

    class TestResult {
    public:
      explicit TestResult(const std::string&amp; code, const char* file, size_t line);
      void report(std::ostream&amp; out) const;
    private:
      std::string code_;
      std::string file_;
      unsigned long line_;
    };

    typedef std::list&lt;TestResult&gt; results_collection;
    typedef results_collection::iterator iterator;
    typedef results_collection::const_iterator const_iterator;
    results_collection results_;
    std::string error_;
  };
</pre>
<p>To save space I'm not going to detail each function here, as a
full description is available in the code [<a href=
"#CppUTF">CppUTF</a>].</p>
<p>As each test class may evaluate multiple expressions we're going
to need to store more than one result for each test, as such we're
going to use the class <tt class=
"classname">TestResultCollection</tt> to provide the interface for
a test's results. It in turn will store a <tt class=
"classname">TestResult</tt> class for each failure, or error (we
don't record passes; they are determined by the absence of a
failure).</p>
<p>An error is defined as an exception that escapes the test code,
or a failure of the <tt class="methodname">setUp()</tt> or
<tt class="methodname">tearDown()</tt> methods, which are explained
later. A failure is an expression that evaluates to false inside an
<tt class="literal"><tt class="function">IS_TRUE()</tt></tt>, or an
expression that evaluates to true within an <tt class=
"function">IS_FALSE()</tt>. <tt class="function">IS_TRUE</tt> and
<tt class="function">IS_FALSE</tt> are explained later.</p>
<p>Next we need a base class for tests, which will define our
common interface to each test:</p>
<pre class="programlisting">
  class Testable {
  public:
    Testable(const std::string&amp; name);
    virtual ~Testable() = 0;
    virtual bool setUp();
    virtual void run();
    virtual bool tearDown();
    virtual std::string name();
  };
</pre>
<p>The constructor requires a name argument, this name will be
returned by the member function <tt class="methodname">name()</tt>
and should be a human friendly name for this test class, as it is
only used for reporting.</p>
<p>The four member functions have been designed to allow overriding
in order to allow the client to perform appropriate action for each
class. <tt class="methodname">setUp()</tt> should be used to
prepare any data required for the test, the body of the tests
should be in <tt class="methodname">run()</tt>, and <tt class=
"methodname">tearDown()</tt> should tidy up any resources allocated
in <tt class="methodname">setUp()</tt>. The function <tt class=
"methodname">name()</tt> returns the name provided to the
constructor. Each function has a default implementation
provided.</p>
<p>The class also contains the protected member <span class=
"property">test_out_</span>, intended to allow tests to write out a
stream of data during the test. Note however that it is implemented
via a <tt class="classname">std::ostringstream</tt>, and as such is
not printed to the screen immediately.</p>
<p>As we can only ever have one instance of the <tt class=
"classname">TestCollection</tt>, it is implemented as a Singleton
[<a href="#Singleton">Singleton</a>]. This has the additional
benefit of allowing us to be able to register each test with the
collection through the public static method <tt class=
"methodname">TestCollection::Instance()</tt>. The <tt class=
"classname">Testable</tt> class's default constructor is
implemented as so:</p>
<pre class="programlisting">
  Testable::Testable(const std::string&amp; name)
    : name_(name) {
    TestCollection::Instance().addTest(this);
  }
</pre>
<p>Now any class deriving from <tt class="literal">Testable</tt> is
automatically registered with the testing framework. The great
benefit of this is that it allows us to add a test without changing
any of the code already in the test build; all we need to do is add
the new test's implementation file to our build list (or makefile).
I believe this is important as I've several times seen code go
untested as someone has forgotten to add the call to the test suite
to the test driver code.</p>
<p>The header testable.h also contains the following macros:</p>
<pre class="programlisting">
  #define IS_TRUE(exp) test::isTrue(exp, #exp, __FILE__, __LINE__)
  #define IS_FALSE(exp) test::isFalse(exp, #exp, __FILE__, __LINE__)
</pre>
<p>which call the following helper functions, ensuring we capture
the line of code being tested, and the details of the file and line
where the test can be found:</p>
<pre class="programlisting">
  void isTrue(bool val, const char* code, const char* file, size_t line);
  void isFalse(bool val, const char* code, const char* file, size_t line);
</pre>
<p>These functions evaluate the result of the test, and ask the
test collection to log a failure if they are not true or false,
respectively.</p>
<p>Our tests are then gathered up into the main body of the
framework; the class <tt class="classname">TestCollection</tt>. The
main body of the testing framework is contained in the function
<tt class="methodname">TestCollection::run()</tt> which looks like
this:</p>
<pre class="programlisting">
  void TestCollection::run() {
    const iterator end = tests_.end();
    run_number_ = 0;
    for (iterator current = tests_.begin();
         current != end; ++current, ++run_number_) {
      try {
        test::Testable&amp; test = *current-&gt;first;
        test::TestResultCollection&amp; test_result = *current-&gt;second;
        if (test.setUp()) {
          try {
            test.run();
          }
          catch(...) {
            error(&quot;Error occurred while running test&quot;);
            test.tearDown();
            continue;
          }
          if (test_result.failedCount() == 0) {
            ++pass_count_;
          }
          else {
            ++fail_count_;
          }
          if (!test.tearDown()) {
            error(&quot;Error occurred while tearing down the test&quot;);
          }
        }
        else {
          error(&quot;Setup failed&quot;);
        }
      }
      catch (std::exception&amp; e) {
        error(e.what());
      }
      catch (...) {
        error(&quot;Unexpected error&quot;);
      }
    }
  }
</pre>
<p>The main purpose of the function is to iterate through the list
of tests, calling <tt class="methodname">setUp()</tt>, <tt class=
"methodname">run()</tt> and <tt class="methodname">tearDown()</tt>,
for each test in turn, catching any exceptions thrown, and checking
that we only run tests that have been successfully set up, or
recording tests that have failed to properly tear themselves
down.</p>
<p>The final thing the test framework does is call <tt class=
"methodname">TestCollection::report()</tt> which iterates through
the <tt class="classname">TestResultCollection</tt>, reporting any
passed tests, or failed tests along with any associated failures or
errors.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e281" id="d0e281"></a>Reading the
Code</h2>
</div>
<p>The actual code supplied on my website contains a few more
comments than are displayed in this article, and is documented with
Doxygen [<a href="#Doxy">Doxy</a>], so you can generate HTML, RTF,
Latex, or man pages from it.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e289" id="d0e289"></a>Using the
Testing Framework</h2>
</div>
<p>To demonstrate the use of the unit testing framework, I've
chosen to use a modified version of the calculator Bjarne
Stroustrup presents in The C++ Programming Language. I've modified
it slightly, changing it into a class, and making it perhaps a
little more reusable and testable.</p>
<p>The <tt class="classname">Calculator</tt> is intended to compute
the result of simple formulae, possibly reusing the result of an
earlier expression to calculate a more complex one such as:
<tt class="literal">(a + b) * (c - 0.147) + d</tt>;</p>
<p><tt class="classname">Calculator</tt> is a simple class defined
as follows:</p>
<pre class="programlisting">
  class Calculator {
  public:
    Calculator();
    double evaluate(const std::string expression);
    // ... private members ...
  };
</pre>
<p>A nice simple interface for us to test! So we'll create a
<tt class="filename">CalculatorTest.cpp</tt> file and we can begin
writing our test:</p>
<pre class="programlisting">
  #include &quot;Testable.h&quot;
  #include &quot;Calculator.h&quot;
</pre>
<p>We need the definition of <tt class="classname">Testable</tt>,
as we're going to inherit from it, and we need the definition of
<tt class="classname">Calculator</tt>, as that's what we're going
to test. Next we need to define our unit test class:</p>
<pre class="programlisting">
  class CalculatorTest
    : public test::Testable {
  public:
    explicit CalculatorTest(const std::string&amp; name) : Testable(name) {}
    // ... rest of class follows ...
</pre>
<p>Remember that we need to pass the human readable form of our
test name down to the base class. Next we'll want to provide the
code to set up and tear down any classes or data we'll need for the
test, in this case I've decided to dynamically allocate the
<tt class="classname">Calculator</tt> here:</p>
<pre class="programlisting">
  virtual bool setUp() {
    try {
      calc_ = new Calculator;
    }
    catch(std::bad_alloc&amp; e) {
      std::cerr &lt;&lt; &quot;Error setting up test: &quot;
                &lt;&lt; e.what() &lt;&lt; std::endl;
      return false;
    }
    return true;
  }

  virtual bool tearDown() {
    delete calc_;
    return true;
  }
</pre>
<p>The <tt class="methodname">teardown()</tt> method assumes
<tt class="literal">delete calc_</tt>; will always succeed. Last
but not least we need to implement the <tt class=
"methodname">run()</tt> method:</p>
<pre class="programlisting">
  virtual void run() {
    testBasics();
    testVariables();
    testCompound();
  }
</pre>
<p>in which I've chose to break my tests down into related groups
and run each group in turn. So let's look at the simple tests in
<tt class="methodname">testBasics()</tt>:</p>
<pre class="programlisting">
  void testBasics() {
    double result = calc_-&gt;evaluate(&quot;1 + 1&quot;);
    IS_TRUE(equal_double(2.0, result));
    result = calc_-&gt;evaluate(&quot;1 + 1&quot;);
    IS_TRUE(equal_double(2.0, result));
    result = calc_-&gt;evaluate(&quot;3 - 1&quot;);
    IS_TRUE(equal_double(2.0, result));
    result = calc_-&gt;evaluate(&quot;1 * 2&quot;);
    IS_TRUE(equal_double(2.0, result));
    result = calc_-&gt;evaluate(&quot;6 / 3&quot;);
    IS_TRUE(equal_double(2.0, result));
  }
</pre>
<p>Now we've gotten to the meat of it. We know <tt class=
"varname">calc_</tt> must be valid for the framework to have called
<tt class="methodname">run()</tt> on our test class, so we can
start using it, and what simpler test for a calculator than 1 + 1,
so we create a double called result to store the result of the
<tt class="methodname">evaluate()</tt> call:</p>
<pre class="programlisting">
  double result = calc_-&gt;evaluate(&quot;1 + 1&quot;);
</pre>
<p>Then we use the <tt class="function">IS_TRUE()</tt> macro to
compare the result to 2, our expected answer:</p>
<pre class="programlisting">
  IS_TRUE(equal_double(2.0, result));
</pre>
<p>Finally after our class declaration we need to create a single
instance of the class, we can do this as so:</p>
<pre class="programlisting">
  static CalculatorTest the_test(&quot;Calculator Test&quot;);
</pre>
<p>You may prefer to place it in an anonymous namespace, as well as
or instead of the static. We can then run the testing framework and
hopefully we'll see something that looks like this:</p>
<pre class="programlisting">
  C++ Testing Framework v1.0 Copyright 2001
  Crickett Software Limited
  The latest version can be downloaded from
  http://www.crickett.co.uk
  - - - - - - - - - - - - - - - - - - - - - - -
  Ran 1 test(s)
  Passes: 1
  Failures: 0
  Errors: 0
  - - - - - - - - - - - - - - - - - - - - - - -
  Test: Calculator Test
  Output:
  No failures.
  No errors.
  - - - - - - - - - - - - - - - - - - - - - - -
</pre>
<p>If we deliberately introduce a failure, say:</p>
<pre class="programlisting">
IS_TRUE(equal_double(7.0, calc_-&gt;evaluate(&quot;1 + 1&quot;)));
</pre>
<p>Then the framework will produce the following results:</p>
<pre class="programlisting">
  C++ Testing Framework v1.0 Copyright 2001
  Crickett Software Limited
  The latest version can be downloaded from
  http://www.crickett.co.uk
  - - - - - - - - - - - - - - - - - - - - - - -
  Ran 1 test(s)
  Passes: 0
  Failures: 1
  Errors: 0
  - - - - - - - - - - - - - - - - - - - - - - -
  Test: Calculator Test
  Output:
  Failures:
    Failed IS_TRUE(equal_double(7.0,
    calc_-&gt;evaluate(&quot;1+1&quot;))) at line 68 in file
    d:\dev\c++\testingframework\calculatortest.cpp
  No errors.
  - - - - - - - - - - - - - - - - - - - - - - -
</pre>
<p>Which gives us the location (file and line number) of the failed
test, and the actual code for the test that failed. I suggest that
you, dear reader, experiment with the supplied examples, perhaps
undertaking the following exercises:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>Extend the tests; there is scope for more comprehensive
testing.</p>
</li>
<li>
<p>Extend <tt class="classname">Calculator</tt> to support function
calls, for example sin, cos, and tan. Also write suitable tests for
each.</p>
</li>
<li>
<p>Add another class to the project, and a suitable test class.</p>
</li>
</ol>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e403" id="d0e403"></a>Logging</h2>
</div>
<p>Sometimes it's just not that easy to test results directly, or
we really might just want to log some text during the test, so the
framework allows the test to log data. This is provided by the
protected member variable <span class="property">test_out_</span>,
and all you need to do to record text during the test is treat it
exactly as you would <tt class="classname">std::cout</tt>. The text
is then reported in the Output section of the tests report.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e414" id="d0e414"></a>Taking It
Further</h2>
</div>
<p>This article has introduced the design and development of the
C++ unit testing framework we use at Crickett Software. It's
continually evolving as we need it to, and the latest version will
normally be available from our website.</p>
<p>In a future article we will look at how to use unit testing to
improve the quality of your code, by catching tests earlier, and
automating as much testing as possible. I'll also look at test
first design. Any questions on the article are most welcome to
<tt class="email">&lt;<a href=
"mailto:john@crickett.co.uk">john@crickett.co.uk</a>&gt;</tt>.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e424" id="d0e424"></a>Thanks
To</h2>
</div>
<p>Jon Jagger (<a href=
"/cgi-bin/olink?sysid=">http://www.jaggersoft.com</a>) for feedback
on an earlier testing framework and some suggestions that got me
started on this incarnation of a C++ unit testing framework. Mark
Radford (<a href=
"/cgi-bin/olink?sysid=">http://www.twonine.co.uk</a>) for comments
on both the framework and this article. Paul Grenyer (<a href=
"/cgi-bin/olink?sysid=">http://www.paulgrenyer.co.uk</a>) for
comments on several drafts.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e438" id="d0e438"></a>Other
Interest</h2>
</div>
<p>JUnit - a Java unit testing framework - <a href=
"http://www.junit.org" target="_top">http://www.junit.org</a>,
covered recently in CVu by Alan Griffiths</p>
<p>XP Unit Testing Frameworks - <a href=
"/cgi-bin/olink?sysid=">http://www.xprogramming.com/software.htm</a></p>
<p>XP Unit Testing - <a href=
"/cgi-bin/olink?sysid=">http://www.xprogramming.com/xpmag/expUniTestsat100.htm</a></p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e454" id="d0e454"></a>References</h2>
</div>
<div class="bibliomixed"><a name="XP" id="XP"></a>
<p class="bibliomixed">[XP] Extreme Programming - <span class=
"bibliomisc"><a href="http://www.xprogramming.com" target=
"_top">http://www.xprogramming.com</a></span></p>
</div>
<div class="bibliomixed"><a name="KandR88" id="KandR88"></a>
<p class="bibliomixed">[KandR88] The C Programming Language by
Kernigan &amp; Richie, 1988.</p>
</div>
<div class="bibliomixed"><a name="CppUTF" id="CppUTF"></a>
<p class="bibliomixed">[CppUTF] C++ Unit Testing Framework -
available from <span class="bibliomisc"><a href=
"http://www.crickett.co.uk" target=
"_top">http://www.crickett.co.uk</a></span></p>
</div>
<div class="bibliomixed"><a name="Singleton" id="Singleton"></a>
<p class="bibliomixed">[Singleton] Singleton - <span class=
"bibliomisc"><a href=
"http://rampages.onramp.net/~huston/dp/singleton.html" target=
"_top">http://rampages.onramp.net/~huston/dp/singleton.html</a></span></p>
</div>
<div class="bibliomixed"><a name="Doxy" id="Doxy"></a>
<p class="bibliomixed">[Doxy] Doxygen, an open source C++
documenting tool, similar to JavaDoc - <span class=
"bibliomisc"><a href="http://www.doxygen.org" target=
"_top">http://www.doxygen.org</a></span></p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
