diff --git a/CHANGELOG.md b/CHANGELOG.md index 4662471..3084181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +* v0.3.1 (2018-03-20) + * Add support for Verbosity::kTestExpired. + * Clean up code in examples/ directory and add documentation in README.md. * v0.3.0 (2018-03-19) * Implement all remaining macros from ArduinoUnit: assertTestXxx(), checkTestXxx(), externTest(), externTesting(). diff --git a/README.md b/README.md index 1404b7b..b3bb188 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AUnit - Unit Testing Framework for Arduino Platforms -Version: v0.3.0 (2018-03-19) +Version: 0.3.1 (2018-03-20) ## Summary @@ -23,7 +23,7 @@ AUnit was created to solve 2 problems with ArduinoUnit: [ArduinoUni#54](https://github.com/mmurdoch/arduinounit/issues/54)). In contrast: -* AUnit consumes as much as 66% *less* flash memory than ArduinoUnit on the +* AUnit consumes as much as 65% *less* flash memory than ArduinoUnit on the AVR platform. On Teensy-ARM, the savings can be as much as 30%. * AUnit has been tested on AVR, Teensy-ARM and ESP8266. @@ -98,6 +98,21 @@ pick up the new library. In this section, information about differences between AUnit and ArduinoUnit will appear in a note marked by ***ArduinoUnit Compatibility***. +### Examples + +The `examples/` directory has a number of examples: + +* `advanced` - how to subclass `Test` and `TestOnce` manually +* `basic` - using the `test()` macro +* `continuous` - using the `testing()` macro +* `filter` - how to filter tests using `TestRunner::include()` and + `TestRunner::exclude()` +* `meta_asserts` - how to use `assertTestXxx()` and `checkTestXxx` + +In the `tests/` directory: + +* `AUnitTest` - the unit test for `AUnit` itself has a large number of examples + ### Header and Namespace To prevent name clashes with other libraries and code, all classes in the AUnit @@ -121,7 +136,7 @@ in the global namespace, so it is usually not necessary to import the entire `aunit` namespace. ***ArduinoUnit Compatibility***: _I have found that the following macros are -useful during the transition:_ +useful during the transition from ArduinoUnit to AUnit_ ``` #define USE_AUNIT 1 @@ -356,7 +371,10 @@ returns `false`, and prints assertion messages that look like this: Assertion passed: Test slow_pass is done, file AUnitTest.ino, line 366. Assertion passed: Test slow_pass is not failed, file AUnitTest.ino, line 372. Assertion passed: Test slow_skip is skipped, file AUnitTest.ino, line 448. +Assertion passed: Test slow_skip is not timed out, file AUnitTest.ino, line 451. ``` +(The human readable version of being `expired` will always be `timed out` or +`not timed out` on the `Serial` output.) The following macros define `extern` references to test case objects which live in other `.cpp` files. These are required for the above meta assertions if the @@ -509,21 +527,23 @@ The names of the bit field flags are different from ArduinoUnit to avoid name collisions with other `#define` macros which have global scope. AUnit uses static constants of the `Verbosity` utility class: -* `Verbosity::kTestRunSummary` -* `Verbosity::kTestFailed` +* `Verbosity::kAssertionPassed` +* `Verbosity::kAssertionFailed` * `Verbosity::kTestPassed` +* `Verbosity::kTestFailed` * `Verbosity::kTestSkipped` +* `Verbosity::kTestExpired` +* `Verbosity::kTestRunSummary` +* `Verbosity::kAssertionAll` - enables all assert messages * `Verbosity::kTestAll` -* `Verbosity::kAssertionFailed` -* `Verbosity::kAssertionPassed` -* `Verbosity::kAssertionAll` -* `Verbosity::kDefault`, equivalent to setting the following - * `(Verbosity::kAssertionFailed | Verbosity::kTestAll)` + * same as `(kTestPassed | kTestFailed | kTestSkipped | kTestExpired)` +* `Verbosity::kDefault` + * same as `(kAssertionFailed | kTestAll | kTestRunSummary )` * `Verbosity::kAll` - enables all messages * `Verbosity::kNone` - disables all messages ***ArduinoUnit Compatibility***: -_The following ArduinoUnit variables do not exist:_` +_The following ArduinoUnit variables do not exist:_ * `Test::verbosity` * `Test::min_verbosity` * `Test::max_verbosity` @@ -543,6 +563,7 @@ The bit field constants have slightly different names:_ * `TEST_VERBOSITY_ALL` -> `Verbosity::kAll` * `TEST_VERBOSITY_NONE` -> `Verbosity::kNone` * {no equivalent} <- `Verbosity::kDefault` +* {no equivalent} <- `Verbosity::kTestExpired` ### Line Number Mismatch @@ -648,7 +669,7 @@ A timeout value of `0` means an infinite timeout, which means that the ## Benchmarks -AUnit consumes as much as 66% less flash memory than ArduinoUnit on an AVR +AUnit consumes as much as 65% less flash memory than ArduinoUnit on an AVR platform (e.g. Arduino UNO, Nano), and 30% less flash on the Teensy-ARM platform (e.g. Teensy LC ). Here are the resource consumption (flash and static) numbers from an actual unit test sketch containing 26 test cases using 331 `assertXxx()` @@ -657,24 +678,24 @@ microcontrollers: ``` Platform (resource) | Max | ArduinoUnit | AUnit | ---------------------------+---------+-------------+-------------| -Arduino Nano (flash) | 30720 | 54038 | 18666 | +Arduino Nano (flash) | 30720 | 54038 | 18818 | Arduino Nano (static) | 2048 | 1061 | 918 | ---------------------------+---------+-------------+-------------| -Teensy LC (flash) | 63488 | 36196 | 25228 | +Teensy LC (flash) | 63488 | 36196 | 25240 | Teensy LC (static) | 8192 | 2980 | 2780 | ---------------------------+---------+-------------+-------------| -Teensy 3.2 (flash) | 262144 | 51236 | 36300 | +Teensy 3.2 (flash) | 262144 | 51236 | 36236 | Teensy 3.2 (static) | 65536 | 5328 | 5236 | ---------------------------+---------+-------------+-------------| -ESP8266 - ESP-12E (flash) | 1044464 | does not | 266748 | +ESP8266 - ESP-12E (flash) | 1044464 | does not | 266796 | ESP8266 - ESP-12E (static) | 81920 | compile | 33128 | ---------------------------+---------+-------------+-------------| -ESP8266 - ESP-01 (flash) | 499696 | does not | 266748 | +ESP8266 - ESP-01 (flash) | 499696 | does not | 266796 | ESP8266 - ESP-01 (static) | 47356 | compile | 33128 | ---------------------------+---------+-------------+-------------| ``` -Not all unit test sketches will experience a savings of 66% of flash memory with +Not all unit test sketches will experience a savings of 65% of flash memory with AUnit, but a savings of 30-50% seems to be common. ## Changelog diff --git a/examples/advanced/advanced.ino b/examples/advanced/advanced.ino index 97266a3..84aefce 100644 --- a/examples/advanced/advanced.ino +++ b/examples/advanced/advanced.ino @@ -1,6 +1,6 @@ #line 2 "advanced.ino" -// Copied from: +// Adapted from: // https://github.com/mmurdoch/arduinounit/blob/master/examples/advanced/advanced.ino #define USE_AUNIT 1 @@ -12,83 +12,78 @@ using namespace aunit; #include #endif -test(simple1) -{ +test(simple1) { assertTrue(true); } -test(simple2) -{ +test(simple2) { assertTrue(false); } -class MyTestOnce : public TestOnce -{ -public: - // constructor must name test - - MyTestOnce(const char *name) - : TestOnce(name) - { - // lightweight constructor, since - // this test might be skipped. - // you can adjust verbosity here +class MyTestOnce: public TestOnce { + public: + MyTestOnce(const char *name): + TestOnce(name) { #if USE_AUNIT == 0 - verbosity = TEST_VERBOSITY_ALL; + // lightweight constructor, since + // this test might be skipped. + // you can adjust verbosity here + verbosity = TEST_VERBOSITY_ALL; #endif - } - - int n; - - void setup() - { - n = random(6); - if (n == 0) skip(); - } - - void once() - { - for (int i=-n; i<=n; ++i) { - for (int j=-n; j<=n; ++j) { - assertEqual(i+j,j+i); + } + + virtual void setup() override { + n = random(6); + if (n == 0) skip(); + } + + virtual void once() override { + for (int i = -n; i <= n; ++i) { + for (int j = -n; j <= n; ++j) { + assertEqual(i+j, j+i); + } } } - } + + private: + int n; }; MyTestOnce myTestOnce1("myTestOnce1"); MyTestOnce myTestOnce2("myTestOnce2"); MyTestOnce myTestOnce3("myTestOnce3"); -class MyTest : public Test -{ -public: - uint16_t when; - MyTest(const char *name) - : Test(name) - { - when = random(100,200); - } - - void loop() - { - if (millis() >= when) - { - assertLess(random(100),50L); - pass(); // if assertion is ok +class MyTest: public Test { + public: + MyTest(const char *name): + Test(name) { + when = random(100, 200); } - } + + virtual void loop() override { + assertLess(getValue() ,50L); + if (millis() >= when) { + pass(); // if assertion is ok + } + } + + private: + long getValue() { + return 20L; + } + + uint16_t when; }; MyTest myTest1("myTest1"); MyTest myTest2("myTest2"); MyTest myTest3("myTest3"); -void setup() -{ +void setup() { Serial.begin(74880); // 74880 is default for some ESP8266 boards - while(!Serial); // for the Arduino Leonardo/Micro only + while (!Serial); // for the Arduino Leonardo/Micro only + delay(1000); // wait for stability on some boards to prevent garbage Serial #if USE_AUNIT == 1 TestRunner::setVerbosity(Verbosity::kAll); @@ -100,11 +95,15 @@ void setup() #endif } -void loop() -{ +void loop() { #if USE_AUNIT == 1 + // Should get: + // TestRunner summary: + // 5 passed, 1 failed, 2 skipped, 0 timed out, out of 8 test(s). TestRunner::run(); #else + // Should get: + // Test summary: 5 passed, 1 failed, and 2 skipped, out of 8 test(s). Test::run(); #endif } diff --git a/examples/basic/basic.ino b/examples/basic/basic.ino index 839c080..c3a8ab2 100644 --- a/examples/basic/basic.ino +++ b/examples/basic/basic.ino @@ -1,6 +1,6 @@ #line 2 "basic.ino" -// Copied from: +// Adapted from: // https://github.com/mmurdoch/arduinounit/blob/master/examples/basic/basic.ino #define USE_AUNIT 1 @@ -11,29 +11,31 @@ #include #endif -test(correct) -{ - int x=1; - assertEqual(x,1); +test(correct) { + int x = 1; + assertEqual(x, 1); } -test(incorrect) -{ - int x=1; - assertNotEqual(x,1); +test(incorrect) { + int x = 1; + assertNotEqual(x, 1); } -void setup() -{ +void setup() { Serial.begin(74880); // 74880 is default for some ESP8266 boards while(!Serial); // for the Arduino Leonardo/Micro only + delay(1000); // wait for stability on some boards to prevent garbage Serial } -void loop() -{ +void loop() { #if USE_AUNIT == 1 + // Should get: + // TestRunner summary: + // 1 passed, 1 failed, 0 skipped, 0 timed out, out of 2 test(s). aunit::TestRunner::run(); #else + // Should get: + // Test summary: 1 passed, 1 failed, and 0 skipped, out of 2 test(s). Test::run(); #endif } diff --git a/examples/continuous/continuous.ino b/examples/continuous/continuous.ino index f06f9eb..6323463 100644 --- a/examples/continuous/continuous.ino +++ b/examples/continuous/continuous.ino @@ -1,6 +1,6 @@ #line 2 "continuous.ino" -// Copied from: +// Adapted from: // https://github.com/mmurdoch/arduinounit/blob/master/examples/continuous/continuous.ino #define USE_AUNIT 1 @@ -12,31 +12,35 @@ #endif // test-once test named "once" -test(once) -{ +test(once) { int x=1; assertLessOrEqual(x,1); } // test-until-skip-pass-or-fail test named "continuous" -testing(continuous) -{ +testing(continuous) { + static unsigned long startTime = millis(); + unsigned long t = millis(); - assertLessOrEqual(t,100UL); - if (t >= 100) pass(); + assertLessOrEqual(t, startTime + 100UL); + if (t >= 100UL + startTime) pass(); } -void setup() -{ +void setup() { Serial.begin(74880); // 74880 is default for some ESP8266 boards while(!Serial); // for the Arduino Leonardo/Micro only + delay(1000); // wait for stability on some boards to prevent garbage Serial } -void loop() -{ +void loop() { #if USE_AUNIT == 1 + // Should get: + // TestRunner summary: + // 2 passed, 0 failed, 0 skipped, 0 timed out, out of 2 test(s). aunit::TestRunner::run(); #else + // Should get: + // Test summary: 2 passed, 0 failed, and 0 skipped, out of 2 test(s). Test::run(); #endif } diff --git a/examples/filter/filter.ino b/examples/filter/filter.ino index 24c633e..6f07a6c 100644 --- a/examples/filter/filter.ino +++ b/examples/filter/filter.ino @@ -1,6 +1,6 @@ #line 2 "filter.ino" -// Copied from: +// Adapted from: // https://github.com/mmurdoch/arduinounit/blob/master/examples/filter/filter.ino #define USE_AUNIT 1 @@ -20,11 +20,11 @@ test(crypto_aes) { pass(); } testing(crypto_rng) { pass(); } test(crypto_sha256) { pass(); } -void setup() -{ +void setup() { Serial.begin(74880); // 74880 is default for some ESP8266 boards while(!Serial); // for the Arduino Leonardo/Micro only - + delay(1000); // wait for stability on some boards to prevent garbage Serial + // all tests named net_ - something, except net_ftp #if USE_AUNIT == 1 TestRunner::exclude("*"); @@ -37,11 +37,15 @@ void setup() #endif } -void loop() -{ +void loop() { #if USE_AUNIT == 1 + // Should get: + // TestRunner summary: + // 2 passed, 0 failed, 4 skipped, 0 timed out, out of 6 test(s). TestRunner::run(); #else + // Should get: + // Test summary: 2 passed, 0 failed, and 4 skipped, out of 6 test(s). Test::run(); #endif } diff --git a/examples/meta_asserts/meta_asserts.ino b/examples/meta_asserts/meta_asserts.ino index 6047b15..de9c9b7 100644 --- a/examples/meta_asserts/meta_asserts.ino +++ b/examples/meta_asserts/meta_asserts.ino @@ -1,9 +1,9 @@ #line 2 "meta_asserts.ino" -// Originally derived from the README.md in -// https://github.com/mmurdoch/arduinounit/ but is now very different. +// Adapted from code fragment in the README.md in +// https://github.com/mmurdoch/arduinounit/ -#define USE_AUNIT 0 +#define USE_AUNIT 1 #if USE_AUNIT == 1 #include @@ -184,6 +184,7 @@ testing(slow_expire_monitor) { void setup() { Serial.begin(74880); // 74880 is default for some ESP8266 boards while(!Serial); // for the Arduino Leonardo/Micro only + delay(1000); // wait for stability on some boards to prevent garbage Serial } void loop() { diff --git a/keywords.txt b/keywords.txt index 89146b0..281a3ef 100644 --- a/keywords.txt +++ b/keywords.txt @@ -34,6 +34,17 @@ setStatus KEYWORD2 setPassOrFail KEYWORD2 getNext KEYWORD2 # +isDone KEYWORD2 +isNotDone KEYWORD2 +isPassed KEYWORD2 +isNotPassed KEYWORD2 +isFailed KEYWORD2 +isNotFailed KEYWORD2 +isSkipped KEYWORD2 +isNotSkipped KEYWORD2 +isExpired KEYWORD2 +isNotExpired KEYWORD2 +# # Protected methods from Test.h skip KEYWORD2 pass KEYWORD2 @@ -41,7 +52,7 @@ fail KEYWORD2 # TestOnce once KEYWORD2 -# Macros from Assertion.h +# Public macros from Assertion.h assertEqual KEYWORD2 assertNotEqual KEYWORD2 assertLess KEYWORD2 @@ -51,6 +62,28 @@ assertMoreOrEqual KEYWORD2 assertTrue KEYWORD2 assertFalse KEYWORD2 +# Public macros from MetaAssertion.h +checkTestDone KEYWORD2 +checkTestNotDone KEYWORD2 +checkTestPass KEYWORD2 +checkTestNotPass KEYWORD2 +checkTestFail KEYWORD2 +checkTestNotFail KEYWORD2 +checkTestSkip KEYWORD2 +checkTestNotSkip KEYWORD2 +checkTestExpire KEYWORD2 +checkTestNotExpireDone KEYWORD2 +assertTestDone KEYWORD2 +assertTestNotDone KEYWORD2 +assertTestPass KEYWORD2 +assertTestNotPass KEYWORD2 +assertTestFail KEYWORD2 +assertTestNotFail KEYWORD2 +assertTestSkip KEYWORD2 +assertTestNotSkip KEYWORD2 +assertTestExpire KEYWORD2 +assertTestNotExpireDone KEYWORD2 + # Overloaded functions from Compare.h compareString KEYWORD2 compareStringN KEYWORD2 @@ -69,14 +102,15 @@ compareNotEqual KEYWORD2 ####################################### # public constants from Verbosity.h -kTestRunSummary LITERAL1 -kTestFailed LITERAL1 +kAssertionPassed LITERAL1 +kAssertionFailed LITERAL1 kTestPassed LITERAL1 +kTestFailed LITERAL1 kTestSkipped LITERAL1 -kTestAll LITERAL1 -kAssertionFailed LITERAL1 -kAssertionPassed LITERAL1 +kTestExpired LITERAL1 +kTestRunSummary LITERAL1 kAssertionAll LITERAL1 +kTestAll LITERAL1 kDefault LITERAL1 kAll LITERAL1 kNone LITERAL1 diff --git a/library.properties b/library.properties index fbe10bc..c2935a2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AUnit -version=0.3.0 +version=0.3.1 author=Brian T. Park maintainer=Brian T. Park sentence=A unit testing framework for Arduino platforms inspired by ArduinoUnit. diff --git a/src/AUnit.h b/src/AUnit.h index 4c47c4a..0490424 100644 --- a/src/AUnit.h +++ b/src/AUnit.h @@ -34,6 +34,6 @@ SOFTWARE. #include "aunit/MetaAssertion.h" // Version format: 010203 == "1.2.3" -#define AUNIT_VERSION 000300 +#define AUNIT_VERSION 000301 #endif diff --git a/src/aunit/Assertion.cpp b/src/aunit/Assertion.cpp index 13475a7..80ba6ce 100644 --- a/src/aunit/Assertion.cpp +++ b/src/aunit/Assertion.cpp @@ -26,6 +26,43 @@ SOFTWARE. namespace aunit { +// This can be a template function because it is accessed only through the +// various assertXxx() methods. Those assertXxx() methods are explicitly +// overloaded for the various types that we want to support. +// +// Prints something like the following: +// Assertion failed: (5) == (6), file Test.ino, line 820. +// Assertion passed: (6) == (6), file Test.ino, line 820. +template +void printAssertionMessage(bool ok, const char* file, uint16_t line, + const A& lhs, const char *opName, const B& rhs) { + + bool isOutput = + (ok && TestRunner::isVerbosity(Verbosity::kAssertionPassed)) || + (!ok && TestRunner::isVerbosity(Verbosity::kAssertionFailed)); + if (!isOutput) return; + + // Don't use F() strings here because flash memory strings are not deduped by + // the compiler, so each template instantiation of this method causes a + // duplication of all the strings below. See + // https://github.com/mmurdoch/arduinounit/issues/70 + // for more info. + Print* printer = Printer::getPrinter(); + printer->print("Assertion "); + printer->print(ok ? "passed" : "failed"); + printer->print(": ("); + printer->print(lhs); + printer->print(") "); + printer->print(opName); + printer->print(" ("); + printer->print(rhs); + printer->print("), file "); + printer->print(file); + printer->print(", line "); + printer->print(line); + printer->println('.'); +} + bool assertion(const char* file, uint16_t line, bool lhs, const char* opName, bool (*op)(bool lhs, bool rhs), bool rhs) { diff --git a/src/aunit/Assertion.h b/src/aunit/Assertion.h index b46f384..c92ee22 100644 --- a/src/aunit/Assertion.h +++ b/src/aunit/Assertion.h @@ -61,42 +61,6 @@ SOFTWARE. namespace aunit { -// This can be a template function because it is accessed only through the -// various assertXxx() methods. Those assertXxx() methods are explicitly -// overloaded for the various types that we want to support. -// -// Prints something like the following: -// Assertion failed: (5) == (6), file Test.ino, line 820. -// Assertion passed: (6) == (6), file Test.ino, line 820. -template -void printAssertionMessage(bool ok, const char* file, uint16_t line, - const A& lhs, const char *opName, const B& rhs) { - - bool isOutput = - (ok && TestRunner::isVerbosity(Verbosity::kAssertionPassed)) || - (!ok && TestRunner::isVerbosity(Verbosity::kAssertionFailed)); - if (!isOutput) return; - - // Don't use F() strings here because flash memory strings are not deduped by - // the compiler, so each template instantiation of this method causes a - // duplication of all the strings below. See - // https://github.com/mmurdoch/arduinounit/issues/70 - // for more info. - Printer::getPrinter()->print("Assertion "); - Printer::getPrinter()->print(ok ? "passed" : "failed"); - Printer::getPrinter()->print(": ("); - Printer::getPrinter()->print(lhs); - Printer::getPrinter()->print(") "); - Printer::getPrinter()->print(opName); - Printer::getPrinter()->print(" ("); - Printer::getPrinter()->print(rhs); - Printer::getPrinter()->print("), file "); - Printer::getPrinter()->print(file); - Printer::getPrinter()->print(", line "); - Printer::getPrinter()->print(line); - Printer::getPrinter()->println('.'); -} - // For the same reason as the compareXxx() methods, we use explicit overloaded // functions, instead of using template specialization. And just as before, I // was unable to use a template function for primitive integer types, because it diff --git a/src/aunit/MetaAssertion.cpp b/src/aunit/MetaAssertion.cpp index 53a43ab..bfa916d 100644 --- a/src/aunit/MetaAssertion.cpp +++ b/src/aunit/MetaAssertion.cpp @@ -1,5 +1,6 @@ #include "Printer.h" #include "Verbosity.h" +#include "Compare.h" #include "MetaAssertion.h" namespace aunit { @@ -7,11 +8,30 @@ namespace aunit { // Print a human readable string fragment from the method name: // "isDone" -> "is done" // "isNotDone" ->"is not done" +// ... +// "isExpired" ->"is timed out" (*) +// "isNotExpired" ->"is not timed out" (*) // -// If the method names are changed, then this mapping needs to be done in -// another way. +// (*) - The internal "expired" state is consistently known as "timed out" +// externally. Doing a string compare is a bit inefficient in terms of CPU +// cycle, but these are unit tests, we don't need to be super fast. +// +// I can think of 2 alternatives to do this internal to external mapping: +// 1) provide the human-readable mapping in the various assertTestXxx() +// macros, +// 2) maybe use a pointer to member functions and do a switch on that here. +// Either of those seems more complex than this little hack. void printStatusString(const char* statusName) { - for (const char* p = statusName; *p != '\0'; p++) { + const char* p; + if (compareEqual(statusName, F("isExpired"))) { + p = "isTimedOut"; // can't use F() here without a lot of work + } else if (compareEqual(statusName, F("isNotExpired"))) { + p = "isNotTimedOut"; // can't use F() here without a lot of work + } else { + p = statusName; + } + + for (; *p != '\0'; p++) { char c = *p; if (!isupper(c)) { Printer::getPrinter()->print(c); @@ -31,18 +51,20 @@ void printAssertionTestStatusMessage(bool ok, const char* file, uint16_t line, if (!isOutput) return; // TODO: Merge the common strings between this and printAssertionMesssage() - // into PROGMEM strings manually and reused them. - Printer::getPrinter()->print("Assertion "); - Printer::getPrinter()->print(ok ? "passed" : "failed"); - Printer::getPrinter()->print(": Test "); - Printer::getPrinter()->print(testName); - Printer::getPrinter()->print(' '); + // into PROGMEM strings manually and reused them. It's not too bad even with + // these c-strings, because the compiler will dedupe them. + Print* printer = Printer::getPrinter(); + printer->print("Assertion "); + printer->print(ok ? "passed" : "failed"); + printer->print(": Test "); + printer->print(testName); + printer->print(' '); printStatusString(statusName); - Printer::getPrinter()->print(", file "); - Printer::getPrinter()->print(file); - Printer::getPrinter()->print(", line "); - Printer::getPrinter()->print(line); - Printer::getPrinter()->println('.'); + printer->print(", file "); + printer->print(file); + printer->print(", line "); + printer->print(line); + printer->println('.'); } bool assertionTestStatus(const char* file, uint16_t line, diff --git a/src/aunit/TestRunner.cpp b/src/aunit/TestRunner.cpp index 587eb6f..e23be1e 100644 --- a/src/aunit/TestRunner.cpp +++ b/src/aunit/TestRunner.cpp @@ -176,38 +176,37 @@ uint16_t TestRunner::countTests() { } void TestRunner::resolveTest(Test* testCase) { - bool isOutput = isVerbosity( - Verbosity::kTestFailed | Verbosity::kTestSkipped | - Verbosity::kTestPassed); - if (!isOutput) return; + if (!isVerbosity(Verbosity::kTestAll)) return; - Printer::getPrinter()->print(F("Test ")); + Print* printer = Printer::getPrinter(); + printer->print(F("Test ")); Printer::print(testCase->getName()); if (testCase->getStatus() == Test::kStatusSkipped) { - Printer::getPrinter()->println(F(" skipped.")); + printer->println(F(" skipped.")); } else if (testCase->getStatus() == Test::kStatusFailed) { - Printer::getPrinter()->println(F(" failed.")); + printer->println(F(" failed.")); } else if (testCase->getStatus ()== Test::kStatusPassed) { - Printer::getPrinter()->println(F(" passed.")); + printer->println(F(" passed.")); } else if (testCase->getStatus ()== Test::kStatusExpired) { - Printer::getPrinter()->println(F(" timed out.")); + printer->println(F(" timed out.")); } } void TestRunner::resolveRun() { if (!isVerbosity(Verbosity::kTestRunSummary)) return; - Printer::getPrinter()->print(F("TestRunner summary: ")); - Printer::getPrinter()->print(mPassedCount); - Printer::getPrinter()->print(F(" passed, ")); - Printer::getPrinter()->print(mFailedCount); - Printer::getPrinter()->print(F(" failed, ")); - Printer::getPrinter()->print(mSkippedCount); - Printer::getPrinter()->print(F(" skipped, ")); - Printer::getPrinter()->print(mExpiredCount); - Printer::getPrinter()->print(F(" timed out, out of ")); - Printer::getPrinter()->print(mCount); - Printer::getPrinter()->println(F(" test(s).")); + Print* printer = Printer::getPrinter(); + printer->print(F("TestRunner summary: ")); + printer->print(mPassedCount); + printer->print(F(" passed, ")); + printer->print(mFailedCount); + printer->print(F(" failed, ")); + printer->print(mSkippedCount); + printer->print(F(" skipped, ")); + printer->print(mExpiredCount); + printer->print(F(" timed out, out of ")); + printer->print(mCount); + printer->println(F(" test(s).")); mIsResolved = true; } @@ -215,12 +214,13 @@ void TestRunner::resolveRun() { void TestRunner::listTests() { setupRunner(); - Printer::getPrinter()->print("TestRunner test count: "); - Printer::getPrinter()->println(mCount); + Print* printer = Printer::getPrinter(); + printer->print(F("TestRunner test count: ")); + printer->println(mCount); for (Test** p = Test::getRoot(); (*p) != nullptr; p = (*p)->getNext()) { - Printer::getPrinter()->print(F("Test ")); + printer->print(F("Test ")); Printer::print((*p)->getName()); - Printer::getPrinter()->println(F(" found.")); + printer->println(F(" found.")); } } diff --git a/src/aunit/TestRunner.h b/src/aunit/TestRunner.h index c6da95f..6aa2169 100644 --- a/src/aunit/TestRunner.h +++ b/src/aunit/TestRunner.h @@ -67,7 +67,7 @@ class TestRunner { getRunner()->setVerbosityFlag(verbosity); } - /** Determine the current verbosity. */ + /** Returns true if ANY of the bit flags of 'verbosity' is set. */ static bool isVerbosity(uint8_t verbosity) { return getRunner()->isVerbosityFlag(verbosity); } diff --git a/src/aunit/Verbosity.h b/src/aunit/Verbosity.h index 1c06f6b..1858212 100644 --- a/src/aunit/Verbosity.h +++ b/src/aunit/Verbosity.h @@ -36,16 +36,21 @@ namespace aunit { */ class Verbosity { public: - static const uint8_t kTestRunSummary = 0x01; - static const uint8_t kTestFailed = 0x02; + // basic flags + static const uint8_t kAssertionPassed = 0x01; + static const uint8_t kAssertionFailed = 0x02; static const uint8_t kTestPassed = 0x04; - static const uint8_t kTestSkipped = 0x08; - static const uint8_t kTestAll = 0x0F; - static const uint8_t kAssertionFailed = 0x10; - static const uint8_t kAssertionPassed = 0x20; - static const uint8_t kAssertionAll = 0x30; - static const uint8_t kDefault = ( - kAssertionFailed | kTestAll); + static const uint8_t kTestFailed = 0x08; + static const uint8_t kTestSkipped = 0x10; + static const uint8_t kTestExpired = 0x20; + static const uint8_t kTestRunSummary = 0x40; + + // compound flags + static const uint8_t kAssertionAll = (kAssertionPassed | kAssertionFailed); + static const uint8_t kTestAll = + (kTestPassed | kTestFailed | kTestSkipped | kTestExpired); + static const uint8_t kDefault = + (kAssertionFailed | kTestAll | kTestRunSummary); static const uint8_t kAll = 0xFF; static const uint8_t kNone = 0x00; diff --git a/tests/AUnitTest/AUnitTest.ino b/tests/AUnitTest/AUnitTest.ino index 7b1b6dc..b55ee45 100644 --- a/tests/AUnitTest/AUnitTest.ino +++ b/tests/AUnitTest/AUnitTest.ino @@ -493,6 +493,7 @@ testing(slow_expire_monitor) { void setup() { Serial.begin(74880); // 74880 is the default for some ESP8266 boards while (! Serial); // Wait until Serial is ready - Leonardo + delay(1000); // Wait for stability on some boards, otherwise garage on Serial #if USE_AUNIT == 1 //TestRunner::setVerbosity(Verbosity::kAll); @@ -511,6 +512,9 @@ void setup() { void loop() { #if USE_AUNIT == 1 + // Should get something like: + // TestRunner summary: + // 18 passed, 1 failed, 1 skipped, 2 timed out, out of 22 test(s). TestRunner::run(); #else Test::run();