150 likes | 267 Views
1 + 1 becomes 11. what does our software promise?. child’s addition. 1 + 1 => 11. define the test. #include <fructose/test_base.h> // test framework /** * define the tests. */ struct math_test : public fructose::test_base< math_test > {
E N D
1 + 1 becomes 11 what does our software promise?
child’s addition 1 + 1 => 11
define the test #include <fructose/test_base.h> // test framework /** * define the tests. */ struct math_test : public fructose::test_base< math_test > { void one_plus_one_is_eleven( const std::string& test_name ) { fructose_assert( 11 == 1 + 1 ); } }; example 1 2 3 4
put test into a program /** * run the tests. */ int main( int argc, char* argv[] ) { math_test t; t.add_test( "1 + 1 => 11", &math_test::one_plus_one_is_eleven ); return t.run( argc, argv ); } example 1 2 3 4
run the test prompt>example1.exe Error: 1 + 1 => 11 in example1.cpp(13): 11 == 1 + 1 failed. Test driver failed: 1 error example 1 2 3 4
implement child’s addition /* Note: we cannot redefine int's behaviour for addition, like: * const int operator+( int const a, int const b ); // no no no */ // child's addition const Integer operator+( Integer const a, Integer const b ) { return 11; // solution! } // equality const bool operator==( Integer const a, Integer const b ) { return a.to_int() == b.to_int(); } example 1 2 3 4
Integer user defined type /** * create from int, obtain as int. */ class Integer { public: // this converting constructor allows to say: Integer a = 1; Integer( int const i ) : m_value( i ) { ; } // provide the implementation value for other operations const int to_int() const { return m_value; } private: int m_value; // the implementation }; example 1 2 3 4
adapt test to use Integer void one_plus_one_is_eleven( const std::string& test_name ) { Integer one = 1; fructose_assert( 11 == one + 1 ); } example 1 2 3 4
run the test return 11; // solution! fructose_assert( 11 == one + 1 ); prompt>example2.exe prompt> example 1 2 3 4
oh, you also want 12 == 1 + 2 ?! /** * add another test. */ struct math_test : public fructose::test_base< math_test > { void one_plus_one_is_eleven( const std::string& test_name ) ... void one_plus_two_is_twelve( const std::string& test_name ) { Integer two = 2; fructose_assert( 12 == 1 + two ); } }; t.add_test( "1 + 2 => 12", &math_test::one_plus_two_is_twelve ); example 1 2 3 4
run the test return 11; // solution? fructose_assert( 12 == 1 + two ); prompt>example3.exe Error: 1 + 2 => 12 in example3.cpp(49): 12 == 1 + two failed. Test driver failed: 1 error prompt> example 1 2 3 4
correct verb child’s addition // child's addition const Integer operator+( Integer const a, Integer const b ) { return 10 * a.to_int() + b.to_int(); } example 1 2 3 4
run the test return 10 * a.to_int() + b.to_int(); prompt>example4.exe prompt> 11 == one + 1; 12 == 1 + two; example 1 2 3 4
what did we learn? • decide on behaviour • specify, document behaviour: the tests • ensure the specified behaviour is present • ensure the specified behaviour stays present its name: • Test Driven Development (TDD)
further information on WikiPedia • agile manifesto • extreme programming • test-driven development • unit test, list of unit testing frameworks • Matlab unit testing: http://mlunit.dohmke.de/