ae01c8387c
- section about command line argument filtering for template test cases - many typos fixes - remove reference to bjam
90 lines
5.2 KiB
Plaintext
90 lines
5.2 KiB
Plaintext
[/
|
|
/ Copyright (c) 2003 Boost.Test contributors
|
|
/
|
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
/]
|
|
|
|
[section:bt_and_tdd Test driven development with Boost.Test]
|
|
|
|
Today is a momentous day - first day of new year. Today I am going to start a new life. I am going to stop eating a
|
|
greasy food, start attending a fitness club and ... today I am going to test programs I am writing. I can start right
|
|
after the last line of a program is completed or, even better, 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.
|
|
|
|
Let say I want to encapsulate an unchangeable C character buffer with a length into the simple class `const_string`.
|
|
Rationale: a string class that does not allocate a memory and provide a convenient read-only access to the pre-allocated
|
|
character buffer. I will probably want `const_string` 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 `const_string`. It will look like
|
|
this:
|
|
|
|
[import ../snippet/snippet13.cpp] [snippet13]
|
|
|
|
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:
|
|
|
|
``*** No errors detected``
|
|
|
|
|
|
|
|
Well, now it could be a good time to start a work on `const_string`. First thing I imagine would be good to have is a
|
|
constructors and trivial access methods. So my class initial version looks like this:
|
|
|
|
[import ../snippet/snippet14.cpp] [snippet14]
|
|
|
|
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:
|
|
|
|
[import ../snippet/snippet15.cpp] [snippet15]
|
|
|
|
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:
|
|
|
|
``Running 1 test case...
|
|
|
|
*** No errors detected
|
|
``
|
|
|
|
Encouraged I am moving on and adding more access methods:
|
|
|
|
[import ../snippet/snippet16.cpp][snippet16]
|
|
|
|
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:
|
|
|
|
[import ../snippet/snippet17.cpp] [snippet17]
|
|
|
|
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.
|
|
|
|
[import ../snippet/const_string.hpp] [import ../snippet/const_string_test.cpp]
|
|
|
|
Continuing my effort I am able to complete class `const_string` (see [@../snippet/const_string.hpp Listing 1
|
|
=const_string.hpp=]) and testing module for it (see [@../snippet/const_string_test.cpp Listing 2 =const_string_test.cpp=])
|
|
that is checking all features that are presented in the class `const_string` specification.
|
|
|
|
|
|
|
|
Well, I am step closer to fulfilling my new year resolution (we should see about this fitness club sometime next ...).
|
|
What about you? 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 Boost.Test 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 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.
|
|
|
|
|
|
[endsect]
|