mirror of
https://github.com/boostorg/test.git
synced 2026-01-26 07:02:12 +00:00
97 lines
5.2 KiB
Plaintext
97 lines
5.2 KiB
Plaintext
[/
|
|
/ Copyright (c) 2003-2014 Gennadiy Rozental
|
|
/
|
|
/ 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 Boost.Test driven development]
|
|
|
|
|
|
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 preallocated 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] |