Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1702 - 1
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
2
//
3
// This is free software; you can redistribute it and/or modify it under
4
// the terms of the GNU Lesser General Public License as published by the
5
// Free Software Foundation; either version 2.1 of the License, or (at
6
// your option) any later version.
7
//
8
 
9
/// @file   AP_Test.h
10
/// @brief  A simple unit test framework.
11
///
12
/// AP_Test provides the usual test start, condition validation and reporting
13
/// functions in a compact form.
14
///
15
/// Each test must be contained within a block; either a standalone function or
16
/// a block within a function.  The TEST macro is used to start a test; it creates
17
/// the local object which will track the results of the test and saves the name
18
/// for later reporting.  Only one test may be performed within each block.
19
///
20
/// Within the test, use the REQUIRE macro to describe a condition that must be
21
/// met for the test to pass.  If the condition within the macro is not met,
22
/// the condition will be output as a diagnostic and the test will be considered
23
/// to have failed.
24
///
25
/// The test ends at the end of the block, and the result of the test will be
26
/// output as a diagnostic.
27
///
28
/// Optionally at the end of the test suite, the Test::report method may be used
29
/// to summarize the results of all of the tests that were performed.
30
///
31
 
32
/// Unit test state and methods.
33
///
34
class Test
35
{
36
public:
37
    /// Constructor - creates a new test.
38
    ///
39
    /// Normally called by the TEST macro.
40
    ///
41
    /// @param  name    The name of the test being started.
42
    ///
43
    Test(const char *name);
44
 
45
    /// Destructor - ends the test.
46
    ///
47
    ~Test();
48
 
49
    /// Perform a success check.
50
    ///
51
    /// @param  expr    If false, the test has failed.
52
    /// @param  source  The expression source; emitted in the diagnostic
53
    ///                 indicating test failure.
54
    ///
55
    void        require(bool expr, const char *source);
56
 
57
    /// Report the overall number of tests/pass/fails.
58
    ///
59
    static void report();
60
 
61
private:
62
    const char  *_name;         ///< name of the current test
63
    bool        _fail;          ///< set if any ::require calls indicate the test failed
64
    static int  _passed;        ///< global pass count
65
    static int  _failed;        ///< global fail count
66
};
67
 
68
/// Constructor
69
///
70
Test::Test(const char *name) :
71
    _name(name),
72
    _fail(false)
73
{
74
}
75
 
76
/// Destructor
77
///
78
Test::~Test()
79
{
80
    Serial.printf("%s: %s\n", _fail ? "FAILED" : "passed", _name);
81
    if (_fail) {
82
        _failed++;
83
    } else {
84
        _passed++;
85
    }
86
}
87
 
88
/// Success check
89
///
90
void
91
Test::require(bool expr, const char *source)
92
{
93
    if (!expr) {
94
        _fail = true;
95
        Serial.printf("%s: fail: %s\n", _name, source);
96
    }
97
}
98
 
99
/// Summary report
100
///
101
void
102
Test::report()
103
{
104
    Serial.printf("\n%d passed  %d failed\n", _passed, _failed);
105
}
106
 
107
int Test::_passed = 0;
108
int Test::_failed = 0;
109
 
110
/// Start a new test.
111
///
112
/// This should be invoked at the beginning of a block, before any REQUIRE
113
/// statements.  A new test called name is started, and subsequent REQUIRE
114
/// statements will be applied to the test.  The test will continue until
115
/// the end of the block (or until the _test object that is created otherwise
116
/// goes out of scope).
117
///
118
#define TEST(name)      Test _test(#name)
119
 
120
/// Attach an expression to the test's success criteria.
121
///
122
/// The expression expr must evaluate true for the test to pass.  If
123
/// it does not, the text of the expression is output as a diagnostic
124
/// and the test is marked as a failure.
125
///
126
#define REQUIRE(expr)   _test.require(expr, #expr)
127