Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
bxparks committed Apr 6, 2018
2 parents d4d846b + 5dbc72d commit 318bc1b
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 51 deletions.
36 changes: 26 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# AUnit - Unit Testing Framework for Arduino Platforms
# AUnit

A unit testing framework for Arduino platforms inspired by ArduinoUnit and
Google Test.

Version: 0.4.0 (2018-03-30)

Expand Down Expand Up @@ -87,6 +90,8 @@ Here are the features in AUnit which are not available in ArduinoUnit:
* `externTestF()`
* `externTestingF()`
* AUnit works on the ESP8266 platform.
* Test filters (`TestRunner::include()` and `TestRunner::exclude()`) support the
same 2 arguments versions corresponding to `testF()` and `testingF()`

### Beta Status

Expand Down Expand Up @@ -130,6 +135,7 @@ The `examples/` directory has a number of examples:
In the `tests/` directory:

* `AUnitTest` - the unit test for `AUnit` itself has a large number of examples
* `FilterTest` - manual tests for `include()` and `exclude()` filters

### Header and Namespace

Expand Down Expand Up @@ -237,7 +243,7 @@ class CustomTestAgain: public TestAgain {
}
};
testingF(CustomTestAgain, examle_test) {
testingF(CustomTestAgain, example_test) {
...
assertBigStuff();
...
Expand All @@ -249,6 +255,7 @@ void setup() {
TestRunner::exclude("*");
TestRunner::include("looping*");
TestRunner::include("CustomTestAgain", "example*");
}
void loop() {
Expand Down Expand Up @@ -628,36 +635,45 @@ ArduinoUnit, each call to `Test::run()` will process the entire list of
currently active test cases. In AUnit, each call to `TestRunner::run()` performs
only a single test case, then returns._

### Excluding and Including Test Cases
### Filtering Test Cases

We can `exclude()` or `include()` test cases using a pattern match,
just like ArduinoUnit. The names are slightly different:
We can `exclude()` or `include()` test cases using a pattern match:

* `TestRunner::exclude(pattern)`
* `TestRunner::exclude(testClass, pattern)`
* `TestRunner::include(pattern)`
* `TestRunner::include(testClass, pattern)`

* `TestRunner::exclude()`
* `TestRunner::include()`

These methods are called from the global `setup()` method:

```
void setup() {
TestRunner::exclude("*");
TestRunner::include("looping*");
TestRunner::exclude("CustomTestAgain", "*");
TestRunner::include("CustomTestAgain", "test*");
...
}
```

The 2-argument versions of `include()` and `exclude()` correspond to the
2 arguments of `testF()` and `testingF()`.

***ArduinoUnit Compatibility***:
_The equivalent versions in ArduinoUnit are `Test::exclude()` and
`Test::include()` The matching algorithm in AUnit is not as powerful as one in
ArduinoUnit. AUnit supports only a single wildcard character `*` and that
`Test::include()` The matching algorithm in AUnit is not as powerful as the one
in ArduinoUnit. AUnit supports only a single wildcard character `*` and that
character can appear only at the end if it is present. For example, the
following are accepted:_

* `TestRunner::exclude("*");`
* `TestRunner::include("f*");`
* `TestRunner::exclude("flash_*");`
* `TestRunner::include("looping*");`
* `TestRunner::include("flashTest");`
* `TestRunner::include("CustomTestOnce", "flashTest*");`

_AUnit provides 2-argument versions of `include()` and `exclude()`_

### Output Printer

Expand Down
45 changes: 41 additions & 4 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@

Test KEYWORD1
TestOnce KEYWORD1
TestAgain KEYWORD1
Assertion KEYWORD1
MetaAssertion KEYWORD1
test KEYWORD1
testing KEYWORD1
testF KEYWORD1
testingF KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
Expand All @@ -23,11 +28,13 @@ include KEYWORD2
setVerbosity KEYWORD2
isVerbosity KEYWORD2
setPrinter KEYWORD2
setTimeout KEYWORD2

# Public methods from Test.h
getRoot KEYWORD2
setup KEYWORD2
loop KEYWORD2
resolve KEYWORD2
getName KEYWORD2
getStatus KEYWORD2
setStatus KEYWORD2
Expand All @@ -44,12 +51,21 @@ isSkipped KEYWORD2
isNotSkipped KEYWORD2
isExpired KEYWORD2
isNotExpired KEYWORD2
#
# Protected methods from Test.h
skip KEYWORD2
expire KEYWORD2
enableVerbosity KEYWORD2
disableVerbosity KEYWORD2
# Protected methods from Test.h
pass KEYWORD2
fail KEYWORD2
# TestOnce
init KEYWORD2
isVerbosity KEYWORD2
getVerbosity KEYWORD2

# TestOnce.h
once KEYWORD2

# TestAgain.h
once KEYWORD2

# Public macros from Assertion.h
Expand Down Expand Up @@ -82,7 +98,28 @@ assertTestNotFail KEYWORD2
assertTestSkip KEYWORD2
assertTestNotSkip KEYWORD2
assertTestExpire KEYWORD2
assertTestNotExpireDone KEYWORD2
assertTestNotExpire KEYWORD2
# F versions
checkTestDoneF KEYWORD2
checkTestNotDoneF KEYWORD2
checkTestPassF KEYWORD2
checkTestNotPassF KEYWORD2
checkTestFailF KEYWORD2
checkTestNotFailF KEYWORD2
checkTestSkipF KEYWORD2
checkTestNotSkipF KEYWORD2
checkTestExpireF KEYWORD2
checkTestNotExpireDoneF KEYWORD2
assertTestDoneF KEYWORD2
assertTestNotDoneF KEYWORD2
assertTestPassF KEYWORD2
assertTestNotPassF KEYWORD2
assertTestFailF KEYWORD2
assertTestNotFailF KEYWORD2
assertTestSkipF KEYWORD2
assertTestNotSkipF KEYWORD2
assertTestExpireF KEYWORD2
assertTestNotExpireF KEYWORD2

# Overloaded functions from Compare.h
compareString KEYWORD2
Expand Down
9 changes: 9 additions & 0 deletions src/aunit/TestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ void TestRunner::setStatusMatchingPattern(const char* pattern, uint8_t status) {
}
}

void TestRunner::setStatusMatchingPattern(const char* testClass,
const char* pattern, uint8_t status) {
String fullPattern(testClass);
fullPattern.concat('_');
fullPattern.concat(pattern);

setStatusMatchingPattern(fullPattern.c_str(), status);
}

TestRunner::TestRunner():
mCurrent(nullptr),
mIsResolved(false),
Expand Down
29 changes: 29 additions & 0 deletions src/aunit/TestRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ class TestRunner {
getRunner()->setStatusMatchingPattern(pattern, Test::kStatusSkipped);
}

/**
* Exclude the tests which match the pattern given by (testClass + "_" +
* pattern), the same concatenation rule used by the testF() macro.
* Currently supports only a trailing '*'. For example,
* exclude("CustomTest", "flash*").
*/
static void exclude(const char* testClass, const char* pattern) {
getRunner()->setStatusMatchingPattern(testClass, pattern,
Test::kStatusSkipped);
}

/**
* Include the tests which match the pattern.
* Currently supports only a trailing '*'. For example, include("flash*").
Expand All @@ -65,6 +76,17 @@ class TestRunner {
getRunner()->setStatusMatchingPattern(pattern, Test::kStatusNew);
}

/**
* Include the tests which match the pattern given by (testClass + "_" +
* pattern), the same concatenation rule used by the testF() macro.
* Currently supports only a trailing '*'. For example,
* include("CustomTest", "flash*").
*/
static void include(const char* testClass, const char* pattern) {
getRunner()->setStatusMatchingPattern(testClass, pattern,
Test::kStatusNew);
}

/** Set the verbosity flag. */
static void setVerbosity(uint8_t verbosity) {
getRunner()->setVerbosityFlag(verbosity);
Expand Down Expand Up @@ -129,6 +151,13 @@ class TestRunner {
/** Set the status of the tests which match the pattern. */
void setStatusMatchingPattern(const char* pattern, uint8_t status);

/**
* Set the status of the tests which match the pattern formed by (testClass
* + "_" + pattern), the same rule used by testF() and testingF()
*/
void setStatusMatchingPattern(const char* testClass, const char* pattern,
uint8_t status);

/** Set the test runner timeout. */
void setRunnerTimeout(TimeoutType seconds);

Expand Down
70 changes: 39 additions & 31 deletions tests/AUnitTest/AUnitTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -88,51 +88,59 @@ test(type_mismatch) {

#if USE_AUNIT == 1

// We use if-statements instead of assertXxx() because compareXxx() is used by
// the assertXxx() methods. Strictly speaking, it's not necessary because one
// is a string compare and the other is an integer compare, but this feels
// conceptually cleaner.
test(compareString) {
assertEqual(compareString(a, a), 0);
assertEqual(compareString(a, f), 0);
assertEqual(compareString(a, s), 0);
if (!(compareString(a, a) == 0)) { fail(); }
if (!(compareString(a, f) == 0)) { fail(); }
if (!(compareString(a, s) == 0)) { fail(); }

assertEqual(compareString(f, a), 0);
assertEqual(compareString(f, f), 0);
assertEqual(compareString(f, s), 0);
if (!(compareString(f, a) == 0)) { fail(); }
if (!(compareString(f, f) == 0)) { fail(); }
if (!(compareString(f, s) == 0)) { fail(); }

assertEqual(compareString(s, a), 0);
assertEqual(compareString(s, f), 0);
assertEqual(compareString(s, s), 0);
if (!(compareString(s, a) == 0)) { fail(); }
if (!(compareString(s, f) == 0)) { fail(); }
if (!(compareString(s, s) == 0)) { fail(); }

assertLess(compareString(a, b), 0);
assertLess(compareString(a, g), 0);
assertLess(compareString(a, t), 0);
if (!(compareString(a, b) < 0)) { fail(); }
if (!(compareString(a, g) < 0)) { fail(); }
if (!(compareString(a, t) < 0)) { fail(); }

assertLess(compareString(f, b), 0);
assertLess(compareString(f, g), 0);
assertLess(compareString(f, t), 0);
if (!(compareString(f, b) < 0)) { fail(); }
if (!(compareString(f, g) < 0)) { fail(); }
if (!(compareString(f, t) < 0)) { fail(); }

assertLess(compareString(s, b), 0);
assertLess(compareString(s, g), 0);
assertLess(compareString(s, t), 0);
if (!(compareString(s, b) < 0)) { fail(); }
if (!(compareString(s, g) < 0)) { fail(); }
if (!(compareString(s, t) < 0)) { fail(); }
}

// We use if-statements instead of assertXxx() because compareXxx() is used by
// the assertXxx() methods. Strictly speaking, it's not necessary because one
// is a string compare and the other is an integer compare, but this feels
// conceptually cleaner.
test(compareStringN) {
assertEqual(compareStringN(ff, "abcde", 5), 0);
assertEqual(compareStringN("abcde", ff, 5), 0);
if (!(compareStringN(ff, "abcde", 5) == 0)) { fail(); }
if (!(compareStringN("abcde", ff, 5) == 0)) { fail(); }

assertMore(compareStringN(ff, "abcd", 5), 0);
if (!(compareStringN(ff, "abcd", 5) > 0)) { fail(); }
assertLess(compareStringN("abcd", ff, 5), 0);

assertEqual(compareStringN(ff, "abcd", 4), 0);
assertEqual(compareStringN("abcd", ff, 4), 0);
if (!(compareStringN(ff, "abcd", 4) == 0)) { fail(); }
if (!(compareStringN("abcd", ff, 4) == 0)) { fail(); }

assertMore(compareStringN(ff, "", 1), 0);
assertLess(compareStringN("", ff, 1), 0);
if (!(compareStringN(ff, "", 1) > 0)) { fail(); }
if (!(compareStringN("", ff, 1) < 0)) { fail(); }

assertEqual(compareStringN(ff, "", 0), 0);
assertEqual(compareStringN("", ff, 0), 0);
if (!(compareStringN(ff, "", 0) == 0)) { fail(); }
if (!(compareStringN("", ff, 0) == 0)) { fail(); }

assertEqual(compareStringN(gg, ff, 5), 0);
if (!(compareStringN(gg, ff, 5) == 0)) { fail(); }

assertMore(compareStringN(gg, ff, 6), 0);
if (!(compareStringN(gg, ff, 6) > 0)) { fail(); }
}

#endif
Expand Down Expand Up @@ -728,9 +736,9 @@ testing(fixture_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
Serial.begin(115200); // ESP8266 default of 74880 not supported on Linux
while (! Serial); // Wait until Serial is ready - Leonardo/Micro

#if USE_AUNIT == 1
// These are useful for debugging.
Expand Down
31 changes: 25 additions & 6 deletions tests/FilterTest/FilterTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,44 @@ testingF(CustomAgain, display) { pass(); }

void setup() {
delay(1000); // Wait for stability on some boards, otherwise garage on Serial
Serial.begin(74880); // 74880 is the default for some ESP8266 boards
Serial.begin(115200); // ESP8266 default of 74880 not supported on Linux
while (! Serial); // Wait until Serial is ready - Leonardo

// Verify that the names of these tests don't collide and can be
// independently selected. Name of test = "{test_class}_{name}".
// independently selected. Name of test is "{test_class}_{name}", but we can
// use the new 2-argument versions of include(testClass, pattern) and
// exclude(testClass, pattern) instead.

TestRunner::list();

Serial.println("exclude(\"*\")");
TestRunner::exclude("*");
TestRunner::list();

Serial.println("include(\"configure*\")");
TestRunner::include("configure");
TestRunner::list();

Serial.println("include(\"CustomAgain*\")");
TestRunner::include("CustomAgain*");
TestRunner::list();
TestRunner::include("CustomOnce_dis*");

Serial.println("exclude(\"CustomAgain\", \"*\")");
TestRunner::exclude("CustomAgain", "*");
TestRunner::list();
TestRunner::include("configure");

Serial.println("include(\"CustomAgain\", \"display\")");
TestRunner::include("CustomAgain", "display");
TestRunner::list();

Serial.println("include(\"CustomOnce_dis*\")");
TestRunner::include("CustomOnce_dis*");
TestRunner::list();
}

void loop() {
// Should get:
// Should get something like:
// TestRunner summary:
// 4 passed, 0 failed, 2 skipped, 0 timed out, out of 6 test(s).
// 3 passed, 0 failed, 3 skipped, 0 timed out, out of 6 test(s).
TestRunner::run();
}

0 comments on commit 318bc1b

Please sign in to comment.