File: index.html

package info (click to toggle)
boost 1.33.1-10
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 100,948 kB
  • ctags: 145,103
  • sloc: cpp: 573,492; xml: 49,055; python: 15,626; ansic: 13,588; sh: 2,099; yacc: 858; makefile: 660; perl: 427; lex: 111; csh: 6
file content (209 lines) | stat: -rw-r--r-- 13,674 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<HTML>
<HEAD>
<TITLE>Getting started to use Unit Test Framework</TITLE>
<LINK rel="stylesheet" type="text/css" href="../../../style/btl.css" media="screen">
<LINK rel="stylesheet" type="text/css" href="../../../style/btl-print.css" media="print">
<META http-equiv="Content-Language" content="en-us">
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</HEAD>
<BODY>
<DIV class="header"> <A href="../../../index.html">Boost.Test</A> > <A href="../../index.html">Components</A> 
  > <A href="../index.html">Unit Test Framework</A> > <SPAN class="current_article">Getting started</SPAN> </DIV>
<DIV class="body"> <IMG src='../../../btl1.gif' width='252' height='43' alt="Boost Test logo"> 
  <H1 class="subtitle">Getting started to use the Unit Test Framework</H1>
  <P class="first-line-indented">Today is a momentous day. Today I am going to start 
    a new life. I am going to stop eating a greasy food, start attending a fitness 
    club and ... since today I am going to test programs I am writing. I can start 
    after the last line of a program is completed or, even better idea, I can write 
    tests while I am coding. And maybe next time I will write tests before the coding,
    during the design stage. I have read a lot of literature on how to write the tests, 
    I have the unit test framework in hand and an idea of new class. So let's get 
    started.</P>
  <P class="first-line-indented">Let say I want to encapsulate an unchangeable C character 
    buffer with a length into the simple class <B>const_string</B>. Rationale: a string 
    class that does not allocate a memory and provide a convenient read-only access 
    to the preallocated character buffer. I will probably want <B>const_string</B> 
    to have an interface similar to the class std::string. What will I do first? In 
    my new life I will start with writing a test module for future class <B>const_string</B>. 
    It will look like this:</P>
  <P>const_string_test.cpp:</P>
  <PRE class="code">#<SPAN class="reserv-word">include</SPAN> &lt;boost/test/unit_test.hpp&gt;
<SPAN class="reserv-word">using namespace</SPAN> boost::unit_test;

test_suite*
init_unit_test_suite( <SPAN class="cpp-type">int</SPAN> argc, <SPAN class="cpp-type">char</SPAN>* argv[] )
{
    test_suite* test= BOOST_TEST_SUITE( <SPAN class="literal">"const_string test"</SPAN> );

    <SPAN class="reserv-word">return</SPAN> test;
}

<SPAN class="comment">// EOF</SPAN></PRE>
  <P class="first-line-indented">Now I can compile it and link with the unit test 
    framework. Done! I have a working test program. It is empty, so when I run the 
    program it produces following output:</P>
  <P class="test-output">*** No errors detected</P>
  <P class="first-line-indented">Well, now it could be a good time to start a work 
    on <B>const_string</B>. First thing I imagine would be good to have is a constructors 
    and trivial access methods. So my class initial version looks like this:</P>
  <P>const_string.hpp</P>
  <PRE class="code"><SPAN class="reserv-word">class</SPAN> const_string {
<SPAN class="reserv-word">public</SPAN>:
    // Constructors
    const_string();
    const_string( <SPAN class="cpp-type">std::string</SPAN> <SPAN class="reserv-word">const</SPAN>&amp; s )
    const_string( <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">const</SPAN>* s );
    const_string( <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">const</SPAN>* s, <SPAN class="cpp-type">size_t</SPAN> length );
    const_string( <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">const</SPAN>* begin, <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">const</SPAN>* end );

    // Access methods
    <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">const</SPAN>* data() <SPAN class="reserv-word">const</SPAN>;
    <SPAN class="cpp-type">size_t</SPAN>      length() <SPAN class="reserv-word">const</SPAN>;
    <SPAN class="cpp-type">bool</SPAN>        is_empty() <SPAN class="reserv-word">const</SPAN>;

    ...
};</PRE>
  <P class="first-line-indented">Now I am able to write a first test case - constructors 
    testing - and add it to a test suite. My test program became to look like this:</P>
  <P>const_string_test.cpp:</P>
  <PRE class="code">#include &lt;boost/test/unit_test.hpp&gt;
<SPAN class="reserv-word">using namespace</SPAN> boost::unit_test;

<SPAN class="cpp-type">void</SPAN> constructors_test() {
     const_string cs0( <SPAN class="literal">&quot;&quot;</SPAN> );                                                 <SPAN class="comment">// 1 //</SPAN>
     BOOST_CHECK_EQUAL( cs0.length(), (<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">0</SPAN> );
     BOOST_CHECK( cs0.is_empty() );

     const_string cs01( NULL );                                              <SPAN class="comment">// 2 //</SPAN>
     BOOST_CHECK_EQUAL( cs01.length(), (<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">0</SPAN> );
     BOOST_CHECK( cs01.is_empty() );

     const_string cs1( <SPAN class="literal">&quot;test_string&quot;</SPAN> );                                      <SPAN class="comment">// 3 //</SPAN>
     BOOST_CHECK_EQUAL( std::strcmp( cs1.data(), <SPAN class="literal">&quot;test_string&quot;</SPAN> ), <SPAN class="literal">0</SPAN> );
     BOOST_CHECK_EQUAL( cs1.length(), std::strlen(&quot;test_string&quot;) );

     <SPAN class="cpp-type">std::string</SPAN> s( <SPAN class="literal">&quot;test_string&quot;</SPAN> );                                         <SPAN class="comment">// 4 //</SPAN>
     const_string cs2( s );
     BOOST_CHECK_EQUAL( std::strcmp( cs2.data(), <SPAN class="literal">&quot;test_string&quot;</SPAN> ), <SPAN class="literal">0</SPAN> );

     const_string cs3( cs1 );                                                <SPAN class="comment">// 5 //</SPAN>
     BOOST_CHECK_EQUAL( std::strcmp( cs1.data(), <SPAN class="literal">&quot;test_string&quot;</SPAN> ), <SPAN class="literal">0</SPAN> );

     const_string cs4( <SPAN class="literal">&quot;test_string&quot;</SPAN>, <SPAN class="literal">4</SPAN> );                                   <SPAN class="comment">// 6 //</SPAN>
     BOOST_CHECK_EQUAL( std::strncmp( cs4.data(), <SPAN class="literal">&quot;test&quot;</SPAN>, cs4.length() ), <SPAN class="literal">0</SPAN> );

     const_string cs5( s.data(), s.data() + s.length() );                    <SPAN class="comment">// 7 //</SPAN>
     BOOST_CHECK_EQUAL( std::strncmp( cs5.data(), <SPAN class="literal">&quot;test_string&quot;</SPAN>, cs5.length() ), <SPAN class="literal">0</SPAN> );

     const_string cs_array[] = { <SPAN class="literal">&quot;str1&quot;</SPAN>, <SPAN class="literal">&quot;str2&quot;</SPAN> };                           <SPAN class="comment">// 8 //</SPAN>
     BOOST_CHECK_EQUAL( cs_array[<SPAN class="literal">0</SPAN>], <SPAN class="literal">&quot;str1&quot;</SPAN> );
     BOOST_CHECK_EQUAL( cs_array[<SPAN class="literal">1</SPAN>], <SPAN class="literal">&quot;str2&quot;</SPAN> );
}

test_suite*
init_unit_test_suite( <SPAN class="cpp-type">int</SPAN> argc, <SPAN class="cpp-type">char</SPAN>* argv[] )
{
    test_suite* test= BOOST_TEST_SUITE( <SPAN class="literal">&quot;const_string test&quot;</SPAN> );

    test-&gt;add( BOOST_TEST_CASE( &amp;constructors_test ) );

    <SPAN class="reserv-word">return</SPAN> test;
}

<SPAN class="comment">// EOF</SPAN></PRE>
  <P class="first-line-indented">The constructors_test test case is intended to check 
    a simple feature of the class const_string: an ability to construct itself properly 
    based on different arguments. To test this feature I am using such characteristics 
    of constructed object as a data it contains and a length. The specification of 
    the class const_string does not contain any expected failures, so, though the 
    constructor can fail if I would pass a pointer to an invalid memory, error check 
    control is not performed (can't require what was not promised :-)). But for any 
    valid input it should work. So I am trying to check a construction for an empty 
    string (1), a NULL string (2) a regular C string(3), an STL string(4), a copy 
    construction(5) and so on . Well, after fixing all the errors in the implementation 
    (do you write programs without errors from scratch?) I am able to pass this test 
    case and the unit test framework gives me the following report:</P>
  <P class="test-output">Running 1 test case...<BR>
    *** No errors detected</P>
  <P class="first-line-indented">Encouraged I am moving on and adding more access 
    methods:</P>
  <P>const_string.hpp</P>
  <PRE class="code"><SPAN class="reserv-word">class</SPAN> const_string {
<SPAN class="reserv-word">public</SPAN>:
    <SPAN class="cpp-type">char</SPAN> <SPAN class="reserv-word">operator</SPAN>[]( <SPAN class="cpp-type">size_t</SPAN> index ) <SPAN class="reserv-word">const</SPAN>;
    <SPAN class="cpp-type">char</SPAN> at( <SPAN class="cpp-type">size_t</SPAN> index ) <SPAN class="reserv-word">const</SPAN>;
    ...
};
</PRE>
  <P class="first-line-indented">I added the new feature - I need a new test case 
    to check it. As a result my test suite became to look like this:</P>
  <P>const_string_test.cpp:</P>
  <PRE class="code">#<SPAN class="reserv-word">include</SPAN> &lt;boost/test/unit_test.hpp&gt;
<SPAN class="reserv-word">using namespace</SPAN> boost::unit_test;

<SPAN class="cpp-type">void</SPAN> constructors_test() {
    ...
}

<SPAN class="cpp-type">void</SPAN> data_access_test() {
    const_string cs1( <SPAN class="literal">&quot;test_string&quot;</SPAN> );                                 <SPAN class="comment">// 1 //</SPAN>
    BOOST_CHECK_EQUAL( cs1[(<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">0</SPAN>], <SPAN class="literal">'t'</SPAN> );
    BOOST_CHECK_EQUAL( cs1[(<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">4</SPAN>], <SPAN class="literal">'_'</SPAN> );
    BOOST_CHECK_EQUAL( cs1[cs1.length()-<SPAN class="literal">1</SPAN>], <SPAN class="literal">'g'</SPAN> );

    BOOST_CHECK_EQUAL( cs1[(<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">0</SPAN>], cs1.at( <SPAN class="literal">0</SPAN> ) );                  <SPAN class="comment">// 2 //</SPAN>
    BOOST_CHECK_EQUAL( cs1[(<SPAN class="cpp-type">size_t</SPAN>)<SPAN class="literal">2</SPAN>], cs1.at( <SPAN class="literal">5</SPAN> ) );
    BOOST_CHECK_EQUAL( cs1.at( cs1.length() - <SPAN class="literal">1</SPAN> ), <SPAN class="literal">'g'</SPAN> );

    BOOST_CHECK_THROW( cs1.at( cs1.length() ), std::out_of_range );    <SPAN class="comment">// 3 //</SPAN>
}

test_suite*
init_unit_test_suite( <SPAN class="cpp-type">int</SPAN> argc, <SPAN class="cpp-type">char</SPAN>* argv[] )
{
    test_suite* test= BOOST_TEST_SUITE( <SPAN class="literal">&quot;const_string test&quot;</SPAN> );
    test-&gt;add( BOOST_TEST_CASE( &amp;constructors_test ) );
    test-&gt;add( BOOST_TEST_CASE( &amp;data_access_test ) );

    <SPAN class="reserv-word">return</SPAN> test;
}

<SPAN class="comment">// EOF</SPAN>
</PRE>
  <P class="first-line-indented">In the data_access_test test case I am trying to 
    check the class const_string character access correctness. While tests (1) checks 
    valid access using const_string::operator[] and test (2) checks valid access using 
    method const_string::at(), there is one more thing to test. The specification 
    of the method const_string::at() contains validation for the out of bound access. 
    That was test (3) is intended to do: check that the validation is working. A testing 
    of a validation and error handling code is an important part of a unit testing 
    and should not be left for a production stage. The data_access_test test case 
    passed and I am ready for the next step.</P>
  <P class="first-line-indented">Continuing my effort I am able to complete class 
    const_string (see <A href="const_string.hpp">Listing 1</A>) and 
    testing module for it (see <A href="const_string_test.cpp">Listing 
    2</A>) that is checking all features that are presented in the class const_string 
    specification.</P>
  <P class="first-line-indented">Your testing habits could be a little different. 
    You could start with a class/library development and then at some point start 
    writing test cases on feature basis. Or you can, given a detailed specification 
    for the future product, including expected interfaces, immediately start with 
    writing all test cases (or it could be a different person, while you working on 
    implementation at the same time). In any case you should not have any problems 
    to use facilities provided by the unit test framework and, let me hope, be able 
    to write a stable, bulletproof code. And what is even more important is your confidence 
    in an ability to make a changes of any complexity without involving a lengthy 
    regression testing of your whole product. Your test module and the unit test framework 
    will stay behind your back to help you with any occasional errors.</P>
</DIV>
<DIV class="footer"> 
  <DIV class="footer-body"> 
    <P> &copy <A name="Copyright">Copyright</A> <A href='mailto:boost-test at emailaccount dot com (please unobscure)'>Gennadiy Rozental</A> 2001-2005. <BR>
      Distributed under the Boost Software License, Version 1.0.
      (See accompanying file <A href="../../../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at 
      <A href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</A>)</P>
        <P>Revised:        <!-- #BeginDate format:Sw1 -->6 January, 2004<!-- #EndDate -->     </P>
  </DIV>
</DIV>
</BODY>
</HTML>