Sophie

Sophie

distrib > Mandriva > 2006.0 > i586 > by-pkgid > 9c646fa862f3ddbc469622b1cf108654 > files > 33

check-0.9.2-1mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML
><HEAD
><TITLE
>Test a little, code a little
   </TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Check Tutorial"
HREF="index.html"><LINK
REL="UP"
TITLE="Tutorial: Basic unit testing
  "
HREF="c57.html"><LINK
REL="PREVIOUS"
TITLE="Setting up the money tests
   "
HREF="x68.html"><LINK
REL="NEXT"
TITLE="Creating a suite
   "
HREF="x108.html"></HEAD
><BODY
CLASS="SECTION"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Check Tutorial</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="x68.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 3. Tutorial: Basic unit testing</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="x108.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECTION"
><H1
CLASS="SECTION"
><A
NAME="AEN80"
>3.3. Test a little, code a little</A
></H1
><P
>The Test Infected article starts out with a Money class, and so will we. Of course, we can't do classes with C, but we don't really need to. The Test Infected approach to writing code says that we should write the unit test <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>before</I
></SPAN
> we write the code, and in this, we will be even more dogmatic and doctrinaire than the authors of Test Infected (who clearly don't really get this stuff, only being some of the originators of the Patterns approach to software development and OO design).
   </P
><P
>Here is our first unit test:
   </P
><PRE
CLASS="PROGRAMLISTING"
>START_TEST (test_create)
{
 Money *m;
 m = money_create(5, "USD");
 fail_unless(money_amount(m) == 5,
             "Amount not set correctly on creation");
 fail_unless(strcmp(money_currency(m), "USD") == 0,
             "Currency not set correctly on creation");
 money_free(m);
}
END_TEST</PRE
><P
>A unit test should just chug along and complete. If it exits early, or is signaled, it will fail with a generic error message. (Note: it is conceivable that you expect an early exit, or a signal. There is currently nothing in Check to specifically assert that we should expect either -- if that is valuable, it may be worth while adding to Check). If we want to get some information about what failed, we need to use the <CODE
CLASS="FUNCTION"
>fail_unless()</CODE
> function. The function (actually a macro) takes a first Boolean argument, and an error message to send if the condition is not true.
  </P
><P
>If the Boolean argument is too complicated to elegantly express within <CODE
CLASS="FUNCTION"
>fail_unless()</CODE
>, there is an alternate function <CODE
CLASS="FUNCTION"
>fail()</CODE
>, that unconditionally fails. The second test above can be rewritten as follows:
   </P
><PRE
CLASS="PROGRAMLISTING"
>if (strcmp(money_currency(m), "USD") != 0) {
  fail("Currency not set correctly on creation");
}</PRE
><P
>There is also a <CODE
CLASS="FUNCTION"
>fail_if()</CODE
> function, which is the inverse of <CODE
CLASS="FUNCTION"
>fail_unless()</CODE
>, the above test then looks like:
   </P
><PRE
CLASS="PROGRAMLISTING"
>fail_if(strcmp(money_currency(m), "USD") != 0,
        "Currency not set correctly on creation");</PRE
><P
>For your convenience all fail functions also accepts NULL as the msg argument and substitutes a suitable message for you. So you could also write a test as follows:
   </P
><PRE
CLASS="PROGRAMLISTING"
>fail_unless(money_amount(m) == 5, NULL);</PRE
><P
>This is equivalent to the line:
   </P
><PRE
CLASS="PROGRAMLISTING"
>fail_unless(money_amount(m) == 5, "Assertion 'money_amount (m) == 5' failed");</PRE
><P
>All fail functions also support varargs and accept printf-style format strings and arguments. This is especially useful while debugging. With printf-style formatting the message could look like this:
   </P
><PRE
CLASS="PROGRAMLISTING"
>fail_unless(money_amount(m) == 5,
            "Amount was %d, instead of 5", money_amount(m));</PRE
><P
>When we try to compile and run the test suite now, we get a whole host of compilation errors. It may seem a bit strange to deliberately write code that won't compile, but notice what we are doing: in creating the unit test, we are also defining requirements for the money interface. Compilation errors are, in a way, unit test failures of their own, telling us that the implementation does not match the specification. If all we do is edit the sources so that the unit test compiles, we are actually making progress, guided by the unit tests, so that's what we will now do.
   </P
><P
>We will add the following to our header money.h:
   </P
><PRE
CLASS="PROGRAMLISTING"
>typedef struct Money Money;
 
Money *money_create(int amount, char *currency); 
int money_amount(Money *m); 
char *money_currency(Money *m); 
void money_free(Money *m);</PRE
><P
>and our code now compiles, but fails to link, since we haven't implemented any of the functions. Let's do that now, creating stubs for all of the functions:
   </P
><PRE
CLASS="PROGRAMLISTING"
>#include &lt;stdlib.h&gt;
#include "money.h"
Money *money_create(int amount, char *currency) 
{ 
  return NULL; 
}
int money_amount(Money *m) 
{ 
  return 0; 
}
char *money_currency(Money *m) 
{ 
  return NULL; 
}
void money_free(Money *m) 
{ 
  return; 
}</PRE
><P
>Now, everything compiles, and we still pass all our tests. How can that be??? Of course -- we haven't run any of our tests yet....
   </P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x68.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x108.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Setting up the money tests</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c57.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Creating a suite</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>