|
4 | 4 |
|
5 | 5 | A unit testing framework for Arduino platforms inspired by by |
6 | 6 | [ArduinoUnit](https://github.com/mmurdoch/arduinounit) and [Google |
7 | | -Test](https://github.com/google/googletest/). The unit tests usually run on the |
8 | | -embedded controller which allows detection of architecture-specific problems. |
9 | | -But for faster development, many unit tests can be compiled and executed |
10 | | -natively on Linux or MacOS using the |
11 | | -[EpoxyDuino](https://github.com/bxparks/EpoxyDuino) companion project. |
12 | | - |
13 | | -AUnit is almost a drop-in replacement of ArduinoUnit with some advantages. AUnit |
14 | | -supports timeouts and test fixtures. It sometimes consumes 50% less flash memory |
15 | | -on the AVR platform, and it has been tested to work on the AVR, SAMD21, STM32, |
16 | | -ESP8266, ESP32 and Teensy platforms. Another companion project |
17 | | -[AUniter](https://github.com/bxparks/AUniter) project provides command line |
18 | | -tools to verify, upload and validate the unit tests to the microcontroller, |
19 | | -instead of having to go through the Arduino IDE. Both the AUniter and |
20 | | -EpoxyDuino tools can be used in a continuous integration system like Jenkins, |
21 | | -or with [GitHub Actions](https://github.com/features/actions). |
22 | | - |
23 | | -**Version**: 1.7.0 (2022-12-08) |
| 7 | +Test](https://github.com/google/googletest/). AUnit is almost a drop-in |
| 8 | +replacement of ArduinoUnit (v2.2) with some advantages. AUnit supports timeouts |
| 9 | +and test fixtures. It sometimes consumes 50% less flash memory on the AVR |
| 10 | +platform, and it has been tested to work on the AVR, SAMD21, STM32, ESP8266, |
| 11 | +ESP32 and Teensy platforms. The assertion error messages were updated in v1.7 to |
| 12 | +provide seamless integration with Unix tools like `vim`. |
| 13 | + |
| 14 | +Originally, the AUnit tests were designed to run on the embedded controller |
| 15 | +itself which allows detection of architecture-specific problems. But the |
| 16 | +uploading, flashing, and execution process is often slow and flaky, causing the |
| 17 | +iteration cycle to take too much time. It is often more effective to execute the |
| 18 | +AUnit tests natively on a host machine (running Linux, MacOS, or FreeBSD) using |
| 19 | +the [EpoxyDuino](https://github.com/bxparks/EpoxyDuino) companion project. Once |
| 20 | +the unit tests are running on the Linux or MacOS host machine, they can be |
| 21 | +incorporated into a continuous integration system like |
| 22 | +[Jenkins](https://www.jenkins.io/) system or a cloud-based system like [GitHub |
| 23 | +Actions](https://github.com/features/actions). |
| 24 | + |
| 25 | +**Version**: 1.7.1 (2023-06-15) |
24 | 26 |
|
25 | 27 | **Changelog**: [CHANGELOG.md](CHANGELOG.md) |
26 | 28 |
|
@@ -78,6 +80,8 @@ or with [GitHub Actions](https://github.com/features/actions). |
78 | 80 | * [Class Hierarchy](#ClassHierarchy) |
79 | 81 | * [Testing Private Helper Methods](#PrivateHelperMethods) |
80 | 82 | * [Benchmarks](#Benchmarks) |
| 83 | + * [Memory Benchmark](#MemoryBenchmark) |
| 84 | + * [Compared with ArduinoUnit](#CompareArduinoUnit) |
81 | 85 | * [System Requirements](#SystemRequirements) |
82 | 86 | * [Hardware](#Hardware) |
83 | 87 | * [Tool Chain](#ToolChains) |
@@ -248,36 +252,66 @@ The source files are organized as follows: |
248 | 252 |
|
249 | 253 | The `examples/` directory has a number of examples: |
250 | 254 |
|
251 | | -* `advanced` - how to subclass `Test` and `TestOnce` manually |
252 | | -* `basic` - using the `test()` macro |
253 | | -* `continuous` - using the `testing()` macro |
254 | | -* `filter` - how to filter tests using `TestRunner::include()` and |
255 | | - `TestRunner::exclude()` |
256 | | -* `fixture` - how to use the `testF()` macro with test fixtures |
257 | | -* `meta_asserts` - how to use `assertTestXxx()` and `checkTestXxx()` |
258 | | - |
259 | | -In the `tests/` directory: |
260 | | - |
261 | | -* `AUnitTest` - the unit test for core `AUnit` functions, |
262 | | -* `AUnitMetaTest` - the unit test for meta assertions and `extern*()` macros |
263 | | -* `FilterTest` - manual tests for `include()` and `exclude()` filters |
264 | | -* `SetupAndTeardownTest` - tests to verify that `setup()` and `teardown()` are |
265 | | - called properly by the finite state machine |
266 | | - |
267 | | -Perhaps the best way to see AUnit in action through real life examples. All my |
268 | | -libraries use AUnit for testing and for continuous integration through |
269 | | -EpoxyDuino. Here are some examples: |
| 255 | +* Basic |
| 256 | + * [basic](examples/basic) |
| 257 | + * using the `test()` macro |
| 258 | + * [fixture](examples/fixture) |
| 259 | + * how to use the `testF()` macro with test fixtures |
| 260 | +* Intermediate |
| 261 | + * [filter](examples/filter) |
| 262 | + * how to filter tests using `TestRunner::include()` and |
| 263 | + `TestRunner::exclude()` |
| 264 | + * [meta_asserts](examples/meta_asserts) |
| 265 | + * how to use `assertTestXxx()` and `checkTestXxx()` |
| 266 | +* Advanced |
| 267 | + * [advanced](examples/advanced/) |
| 268 | + * how to subclass `Test` and `TestOnce` manually |
| 269 | + * [continuous](examples/continuous) |
| 270 | + * using the `testing()` macro |
| 271 | +* Benchmarks |
| 272 | + * These are internal benchmark programs, not meant as examples (they are in |
| 273 | + the `examples/` directory because of the Arduino IDE). |
| 274 | + * [MemoryBenchmark](examples/MemoryBenchmark) |
| 275 | + * Determines the flash and static memory consumption of AUnit for |
| 276 | + various microcontroller |
| 277 | + |
| 278 | +In the `tests/` directory, there are unit tests to test the AUnit framework |
| 279 | +itself: |
| 280 | + |
| 281 | +* [AUnitTest](tests/AUnitTest) |
| 282 | + * the unit test for core `AUnit` functions |
| 283 | +* [AUnitMoreTest](tests/AUnitMoreTest) |
| 284 | + * more tests |
| 285 | +* [AUnitMetaTest](tests/AUnitMetaTest) |
| 286 | + * the unit test for meta assertions and `extern*()` macros |
| 287 | +* [CompareTest](tests/CompareTest) |
| 288 | + * tests for the low-level compare functions |
| 289 | +* [FailingTest](tests/FailingTest) |
| 290 | + * tests that are expected to fail |
| 291 | +* [FilterTest](tests/FilterTest) |
| 292 | + * manual tests for `include()` and `exclude()` filters |
| 293 | +* [Print64Test](tests/Print64Test) |
| 294 | + * manual tests for `include()` and `exclude()` filters |
| 295 | +* [SetupAndTeardownTest](tests/SetupAndTeardownTest) |
| 296 | + * tests to verify that `setup()` and `teardown()` are called properly by the |
| 297 | + finite state machine |
| 298 | +* [tests/Makefile](tests/Makefile) |
| 299 | + * Runs the tests on a Linux or Mac machine using EpoxyDuino |
| 300 | + |
| 301 | +Perhaps the best way to see AUnit in action is through real life examples. All |
| 302 | +my libraries use AUnit for testing and for continuous integration through |
| 303 | +EpoxyDuino. Here are some of my libraries: |
270 | 304 |
|
271 | 305 | * [AceButton](https://github.com/bxparks/AceButton) |
272 | 306 | * My first Arduino library, which originally used ArduinoUnit 2.2. |
273 | 307 | * I kept many of the original ArduinoUnit tests for backwards compatibility |
274 | | - testing. But over time, I started to use nore AUnit features. |
| 308 | + testing. But over time, I started to use more AUnit features so I'm not |
| 309 | + sure if they work with ArduinoUnit anymore. |
275 | 310 | * [AceCRC](https://github.com/bxparks/AceCRC) |
276 | 311 | * [AceCommon](https://github.com/bxparks/AceCommon) |
277 | 312 | * [AceRoutine](https://github.com/bxparks/AceRoutine) |
278 | 313 | * [AceSegment](https://github.com/bxparks/AceSegment) |
279 | 314 | * [AceSorting](https://github.com/bxparks/AceSorting) |
280 | | -* [AceTimeClock](https://github.com/bxparks/AceTimeClock) |
281 | 315 | * [AceTime](https://github.com/bxparks/AceTime) |
282 | 316 |
|
283 | 317 | <a name="Usage"></a> |
@@ -518,7 +552,7 @@ SampleTest.ino:10: Assertion failed: (2) == (1) |
518 | 552 | The format of the assertion failure messages was changed in v1.7 to the |
519 | 553 | following: |
520 | 554 | ``` |
521 | | -{filName}:{lineNumber}: Assertion failed: {expression} |
| 555 | +{fileName}:{lineNumber}: Assertion failed: {expression} |
522 | 556 | ``` |
523 | 557 |
|
524 | 558 | This format is a widely used in many other programs, for example, the C compiler |
@@ -1476,21 +1510,16 @@ copied from the `AUniter/README.md` file: |
1476 | 1510 | * list the available serial ports and devices |
1477 | 1511 | * `$ auniter verify nano Blink.ino` |
1478 | 1512 | * verify (compile) `Blink.ino` using the `env:nano` environment |
1479 | | -* `$ auniter verify nano,esp8266,esp32 Blink.ino` |
1480 | | - * verify `Blink.ino` on 3 target environments (`env:nano`, `env:esp8266`, |
1481 | | - `env:esp32`) |
1482 | 1513 | * `$ auniter upload nano:/dev/ttyUSB0 Blink.ino` |
1483 | 1514 | * upload `Blink.ino` to the `env:nano` target environment connected to |
1484 | 1515 | `/dev/ttyUSB0` |
1485 | 1516 | * `$ auniter test nano:USB0 BlinkTest.ino` |
1486 | 1517 | * compile and upload `BlinkTest.ino` using the `env:nano` environment, |
1487 | 1518 | upload it to the board at `/dev/ttyUSB0`, then validate the output of the |
1488 | 1519 | [AUnit](https://github.com/bxparks/AUnit) unit test |
1489 | | -* `$ auniter test nano:USB0,esp8266:USB1,esp32:USB2 BlinkTest/ ClockTest/` |
| 1520 | +* `$ auniter test nano:USB0 BlinkTest/ ClockTest/` |
1490 | 1521 | * upload and verify the 2 unit tests (`BlinkTest/BlinkTest.ino`, |
1491 | | - `ClockTest/ClockTest.ino`) on 3 target environments (`env:nano`, |
1492 | | - `env:esp8266`, `env:esp32`) located at the 3 respective ports |
1493 | | - (`/dev/ttyUSB0`, `/dev/ttyUSB1`, `/dev/ttyUSB2`) |
| 1522 | + `ClockTest/ClockTest.ino`) on the target environment (`env:nano`) |
1494 | 1523 | * `$ auniter upmon nano:USB0 Blink.ino` |
1495 | 1524 | * upload the `Blink.ino` sketch and monitor the serial port using a |
1496 | 1525 | user-configurable terminal program (e.g. `picocom`) on `/dev/ttyUSB0` |
@@ -1528,10 +1557,22 @@ For real Arduino boards, you get more reliable unit tests if you add a |
1528 | 1557 | necessary, so I recommend calling this only on real Arduino boards, like this: |
1529 | 1558 | ```C++ |
1530 | 1559 | void setup() { |
1531 | | -#ifdef ARDUINO |
| 1560 | +#if ! defined(EPOXY_DUINO) |
1532 | 1561 | delay(1000); // Wait for stability on some boards, otherwise garage on Serial |
1533 | 1562 | #endif |
| 1563 | + |
| 1564 | + Serial.begin(115200); |
| 1565 | + while (! Serial); // Wait until Serial is ready - Leonardo/Micro |
| 1566 | + |
| 1567 | +#if defined(EPOXY_DUINO) |
| 1568 | + Serial.setLineModeUnix(); // use Unix line terminator instead of DOS |
| 1569 | +#endif |
1534 | 1570 | ... |
| 1571 | +} |
| 1572 | + |
| 1573 | +void loop() { |
| 1574 | + aunit::TestRunner::run(); |
| 1575 | +} |
1535 | 1576 | ``` |
1536 | 1577 |
|
1537 | 1578 | **Exit() Status Code** |
@@ -1881,13 +1922,50 @@ testF(TargetTest, helper) { |
1881 | 1922 | ``` |
1882 | 1923 |
|
1883 | 1924 | The tricky part is that `Target.h` must have forward declarations of the various |
1884 | | -auto-generated AUnit test classes. And within the `Target` class itsef, the |
| 1925 | +auto-generated AUnit test classes. And within the `Target` class itself, the |
1885 | 1926 | `friend` declarations need to have a global scope `::` specifier before the name |
1886 | 1927 | of the test class. |
1887 | 1928 |
|
1888 | 1929 | <a name="Benchmarks"></a> |
1889 | 1930 | ## Benchmarks |
1890 | 1931 |
|
| 1932 | +<a name="MemoryBenchmark"></a> |
| 1933 | +### MemoryBenchmark |
| 1934 | + |
| 1935 | +The [MemoryBenchmark](examples/MemoryBenchmark/) directory collects the flash |
| 1936 | +and static RAM usage of the AUnit library on various microcontroller boards, and |
| 1937 | +renders the results as tables embedded in the README.md file. Here are 2 |
| 1938 | +highlights: |
| 1939 | + |
| 1940 | +**Arduino Nano (8-bit)** |
| 1941 | + |
| 1942 | +``` |
| 1943 | ++---------------------------------------------------------------------+ |
| 1944 | +| Functionality | flash/ ram | delta | |
| 1945 | +|----------------------------------------+--------------+-------------| |
| 1946 | +| Baseline | 1586/ 185 | 0/ 0 | |
| 1947 | +|----------------------------------------+--------------+-------------| |
| 1948 | +| AUnit Single Test | 4456/ 366 | 2870/ 181 | |
| 1949 | +| AUnit Single Test Verbose | 4500/ 366 | 2914/ 181 | |
| 1950 | ++---------------------------------------------------------------------+ |
| 1951 | +``` |
| 1952 | + |
| 1953 | +**ESP8266 (32-bit)** |
| 1954 | + |
| 1955 | +``` |
| 1956 | ++---------------------------------------------------------------------+ |
| 1957 | +| Functionality | flash/ ram | delta | |
| 1958 | +|----------------------------------------+--------------+-------------| |
| 1959 | +| Baseline | 264949/27984 | 0/ 0 | |
| 1960 | +|----------------------------------------+--------------+-------------| |
| 1961 | +| AUnit Single Test | 268021/28148 | 3072/ 164 | |
| 1962 | +| AUnit Single Test Verbose | 268081/28148 | 3132/ 164 | |
| 1963 | ++---------------------------------------------------------------------+ |
| 1964 | +``` |
| 1965 | + |
| 1966 | +<a name="CompareArduinoUnit"></a> |
| 1967 | +### Compared to ArduinoUnit 2.2 |
| 1968 | + |
1891 | 1969 | AUnit consumes as much as 65% less flash memory than ArduinoUnit 2.2 on an AVR |
1892 | 1970 | platform (e.g. Arduino UNO, Nano), and 30% less flash on the Teensy-ARM platform |
1893 | 1971 | (e.g. Teensy LC ). (ArduinoUnit 2.3 reduces the flash memory by 30% or so, which |
@@ -1929,50 +2007,69 @@ AUnit, but a savings of 30-50% seems to be common. |
1929 | 2007 | <a name="Hardware"></a> |
1930 | 2008 | ### Hardware |
1931 | 2009 |
|
1932 | | -The library is tested on the following boards: |
| 2010 | +**Tier 1: Fully supported** |
| 2011 | + |
| 2012 | +These boards are tested on each release: |
1933 | 2013 |
|
1934 | 2014 | * Arduino Nano clone (16 MHz ATmega328P) |
1935 | 2015 | * SparkFun Pro Micro clone (16 MHz ATmega32U4) |
1936 | | -* SAMD21 M0 Mini board (Arduino Zero compatible, 48 MHz ARM Cortex-M0+) |
| 2016 | +* Seeeduino XIAO M0 (SAMD21, 48 MHz ARM Cortex-M0+) |
1937 | 2017 | * STM32 Blue Pill (STM32F103C8, 72 MHz ARM Cortex-M3) |
| 2018 | +* Adafruit ItsyBitsy M4 (SAMD51, 120 MHz ARM Cortext-M4) |
1938 | 2019 | * NodeMCU 1.0 (ESP-12E module, 80 MHz ESP8266) |
1939 | 2020 | * WeMos D1 Mini (ESP-12E module, 80 MHz ESP8266) |
1940 | 2021 | * ESP32 dev board (ESP-WROOM-32 module, 240 MHz dual core Tensilica LX6) |
1941 | | -* Teensy 3.2 (96 MHz ARM Cortex-M4) |
1942 | 2022 |
|
1943 | | -I will occasionally test on the following hardware as a sanity check: |
| 2023 | +**Tier 2: Should work** |
| 2024 | + |
| 2025 | +These boards should work but I don't test them as often: |
1944 | 2026 |
|
1945 | 2027 | * Arduino Pro Mini (16 MHz ATmega328P) |
1946 | 2028 | * Mini Mega 2560 (Arduino Mega 2560 compatible, 16 MHz ATmega2560) |
1947 | 2029 | * Teensy LC (48 MHz ARM Cortex-M0+) |
| 2030 | +* Teensy 3.2 (96 MHz ARM Cortex-M4) |
| 2031 | + |
| 2032 | +**Tier 3: May work, but not supported** |
1948 | 2033 |
|
1949 | | -The following boards are **not** supported: |
| 2034 | +* Other 3rd party SAMD21 and SAMD51 boards *may* work if their board software |
| 2035 | + uses the traditional Arduino API, instead of the |
| 2036 | + [ArduinoCore-API](https://github.com/arduino/ArduinoCore-api) |
1950 | 2037 |
|
1951 | | -* Any platform using the ArduinoCore-API |
1952 | | - (https://github.com/arduino/ArduinoCore-api), such as: |
1953 | | - * megaAVR (e.g. Nano Every) using ArduinoCore-megaavr |
1954 | | - (https://github.com/arduino/ArduinoCore-megaavr/) |
1955 | | - * SAMD21 boards (e.g. MKRZero) using ArduinoCore-samd |
1956 | | - (https://github.com/arduino/ArduinoCore-samd) starting with |
1957 | | - `arduino:samd` version >= 1.8.10 |
1958 | | - * Raspberry Pi Pico (RP2040) using Arduino-Pico |
1959 | | - (https://github.com/earlephilhower/arduino-pico) |
| 2038 | +**Tier Blacklisted** |
| 2039 | + |
| 2040 | +The following boards are *not* supported and are explicitly blacklisted to allow |
| 2041 | +the compiler to print useful error messages instead of hundreds of lines of |
| 2042 | +compiler errors: |
| 2043 | + |
| 2044 | +* Any platform using the |
| 2045 | + [ArduinoCore-API](https://github.com/arduino/ArduinoCore-api), such as: |
| 2046 | + * Arduino-branded megaAVR using |
| 2047 | + [ArduinoCore-megaavr](https://github.com/arduino/ArduinoCore-megaavr/) |
| 2048 | + * Nano Every |
| 2049 | + * Arduino-branded SAMD21 or SAMD51 boards using |
| 2050 | + [ArduinoCore-samd](https://github.com/arduino/ArduinoCore-samd) after |
| 2051 | + version >= 1.8.10 |
| 2052 | + * MKRZero |
| 2053 | + * Nano 33 IoT |
| 2054 | + * Raspberry Pi Pico (RP2040) using |
| 2055 | + [Arduino-Pico](https://github.com/earlephilhower/arduino-pico) |
1960 | 2056 |
|
1961 | 2057 | <a name="ToolChain"></a> |
1962 | 2058 | ### Tool Chain |
1963 | 2059 |
|
1964 | 2060 | This library was validated using: |
1965 | 2061 |
|
1966 | 2062 | * [Arduino IDE 1.8.19](https://www.arduino.cc/en/Main/Software) |
1967 | | -* [Arduino CLI 0.19.2](https://arduino.github.io/arduino-cli) |
1968 | | -* [Arduino AVR Boards 1.8.4](https://github.com/arduino/ArduinoCore-avr) |
| 2063 | +* [Arduino CLI 0.33.0](https://arduino.github.io/arduino-cli) |
| 2064 | +* [Arduino AVR Boards 1.8.6](https://github.com/arduino/ArduinoCore-avr) |
1969 | 2065 | * [Arduino SAMD Boards 1.8.9](https://github.com/arduino/ArduinoCore-samd) |
| 2066 | + (versions >= 1.8.10 not supported) |
1970 | 2067 | * [SparkFun AVR Boards 1.1.13](https://github.com/sparkfun/Arduino_Boards) |
1971 | 2068 | * [SparkFun SAMD Boards 1.8.6](https://github.com/sparkfun/Arduino_Boards) |
1972 | | -* [STM32duino 2.2.0](https://github.com/stm32duino/Arduino_Core_STM32) |
| 2069 | +* [STM32duino 2.5.0](https://github.com/stm32duino/Arduino_Core_STM32) |
1973 | 2070 | * [ESP8266 Arduino 3.0.2](https://github.com/esp8266/Arduino) |
1974 | | -* [ESP32 Arduino 2.0.2](https://github.com/espressif/arduino-esp32) |
1975 | | -* [Teensyduino 1.56](https://www.pjrc.com/teensy/td_download.html) |
| 2071 | +* [ESP32 Arduino 2.0.9](https://github.com/espressif/arduino-esp32) |
| 2072 | +* [Teensyduino 1.57](https://www.pjrc.com/teensy/td_download.html) |
1976 | 2073 |
|
1977 | 2074 | This library is *not* compatible with: |
1978 | 2075 |
|
|
0 commit comments