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 |