{"id":13832748,"url":"https://github.com/bxparks/AUnit","last_synced_at":"2025-07-09T19:31:13.978Z","repository":{"id":44637433,"uuid":"124992843","full_name":"bxparks/AUnit","owner":"bxparks","description":"Unit testing framework for Arduino platforms inspired by ArduinoUnit and Google Test. Used with EpoxyDuino for continuous builds.","archived":false,"fork":false,"pushed_at":"2023-10-31T21:46:31.000Z","size":7359,"stargazers_count":178,"open_issues_count":3,"forks_count":16,"subscribers_count":9,"default_branch":"develop","last_synced_at":"2024-11-10T01:23:15.202Z","etag":null,"topics":["arduino","arduino-library","esp32","esp8266","teensyduino","unit-testing","unit-testing-framework"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bxparks.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-03-13T04:36:09.000Z","updated_at":"2024-10-24T17:57:37.000Z","dependencies_parsed_at":"2023-02-09T21:15:33.201Z","dependency_job_id":"805cc6b2-350d-47ce-b97b-c03d400e667d","html_url":"https://github.com/bxparks/AUnit","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bxparks%2FAUnit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bxparks%2FAUnit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bxparks%2FAUnit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bxparks%2FAUnit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bxparks","download_url":"https://codeload.github.com/bxparks/AUnit/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225581832,"owners_count":17491794,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","arduino-library","esp32","esp8266","teensyduino","unit-testing","unit-testing-framework"],"created_at":"2024-08-04T11:00:29.603Z","updated_at":"2024-11-20T15:31:03.289Z","avatar_url":"https://github.com/bxparks.png","language":"C++","funding_links":[],"categories":["**SOFTWARE**"],"sub_categories":["***MICROCONTROLERS AND SENSORS***"],"readme":"# AUnit\n\n[![AUnit Tests](https://github.com/bxparks/AUnit/actions/workflows/aunit_tests.yml/badge.svg)](https://github.com/bxparks/AUnit/actions/workflows/aunit_tests.yml)\n\nA unit testing framework for Arduino platforms inspired by by\n[ArduinoUnit](https://github.com/mmurdoch/arduinounit) and [Google\nTest](https://github.com/google/googletest/). AUnit is almost a drop-in\nreplacement of ArduinoUnit (v2.2) with some advantages. AUnit supports timeouts\nand test fixtures. It sometimes consumes 50% less flash memory on the AVR\nplatform, and it has been tested to work on the AVR, SAMD21, STM32, ESP8266,\nESP32 and Teensy platforms. The assertion error messages were updated in v1.7 to\nprovide seamless integration with Unix tools like `vim`.\n\nOriginally, the AUnit tests were designed to run on the embedded controller\nitself which allows detection of architecture-specific problems. But the\nuploading, flashing, and execution process is often slow and flaky, causing the\niteration cycle to take too much time. It is often more effective to execute the\nAUnit tests natively on a host machine (running Linux, MacOS, or FreeBSD) using\nthe [EpoxyDuino](https://github.com/bxparks/EpoxyDuino) companion project. Once\nthe unit tests are running on the Linux or MacOS host machine, they can be\nincorporated into a continuous integration system like\n[Jenkins](https://www.jenkins.io/) system or a cloud-based system like [GitHub\nActions](https://github.com/features/actions).\n\n**Version**: 1.7.1 (2023-06-15)\n\n**Changelog**: [CHANGELOG.md](CHANGELOG.md)\n\n## Table of Contents\n\n* [Summary](#Summary)\n    * [ArduinoUnit Compatible Features](#ArduinoUnitCompatible)\n    * [Missing Features](#MissingFeatures)\n    * [Added Features](#AddedFeatures)\n* [Installation](#Installation)\n    * [Source Code](#SourceCode)\n* [Documentation](#Documentation)\n    * [Examples](#Examples)\n* [Usage](#Usage)\n    * [Header and Namespace](#HeaderAndNamespace)\n    * [Verbose Mode](#VerboseMode)\n    * [Defining the Tests](#DefiningTests)\n    * [Generated Class and Instance Names](#GeneratedClass)\n    * [Binary Assertions](#BinaryAssertions)\n        * [Assertion Message Format](#AssertionMessageFormat)\n        * [Supported Parameter Types](#SupportedParameterTypes)\n        * [Parameter Types Must Match](#ParameterTypesMustMatch)\n        * [Pointer Comparisons](#PointerComparisons)\n        * [Case Insensitive String Comparisons](#CaseInsensitiveStrings)\n    * [Approximate Comparisons](#ApproximateComparisons)\n    * [Boolean Assertions](#BooleanAssertions)\n    * [Test Fixtures](#TestFixtures)\n    * [Early Return and Delayed Assertions](#EarlyReturnDelayedAssertions)\n    * [Meta Assertions](#MetaAssertions)\n    * [Unconditional Termination](#UnconditionalTermination)\n    * [Overridable Methods](#OverridableMethods)\n    * [Running the Tests](#RunningTests)\n    * [Filtering Test Cases](#FilteringTestCases)\n    * [Output Printer](#OutputPrinter)\n    * [Controlling Verbosity](#ControllingVerbosity)\n    * [Line Number Mismatch](#LineNumberMismatch)\n    * [Test Framework Messages](#TestFrameworkMessages)\n        * [Assertion Message](#AssertionMessage)\n        * [Verbose Mode Message](#VerboseModeMessage)\n        * [Test Case Summary](#TestCaseSummary)\n        * [Test Runner Summary](#TestRunnerSummary)\n    * [Test Timeout](#TestTimeout)\n* [GoogleTest Adapter](#GoogleTestAdapter)\n* [Command Line Tools](#CommandLineTools)\n    * [AUniter](#AUniter)\n    * [EpoxyDuino](#EpoxyDuino)\n    * [Command Line Flags and Arguments](#CommandLineFlagsAndArguments)\n* [Continuous Integration](#ContinuousIntegration)\n    * [Arduino IDE/CLI + Cloud](#IdePlusCloud)\n    * [Arduino IDE/CLI + Jenkins](#IdePlusJenkins)\n    * [EpoxyDuino + Jenkins](#EpoxyDuinoPlusJenkins)\n    * [EpoxyDuino + Cloud (Recommended)](#EpoxyDuinoPlusCloud)\n* [Tips](#Tips)\n    * [Debugging Assertions in Fixtures](#DebuggingFixtures)\n    * [Class Hierarchy](#ClassHierarchy)\n    * [Testing Private Helper Methods](#PrivateHelperMethods)\n* [Benchmarks](#Benchmarks)\n    * [Memory Benchmark](#MemoryBenchmark)\n    * [Compared with ArduinoUnit](#CompareArduinoUnit)\n* [System Requirements](#SystemRequirements)\n    * [Hardware](#Hardware)\n    * [Toolchains](#Toolchains)\n    * [Operating System](#OperatingSystem)\n* [License](#License)\n* [Feedback and Support](#FeedbackAndSupport)\n* [Authors](#Authors)\n\n\u003ca name=\"Summary\"\u003e\u003c/a\u003e\n## Summary\n\nAUnit was created to solve 3 problems with ArduinoUnit 2.2:\n* ArduinoUnit consumes too much flash memory on an AVR platform (e.g.\n  Arduino UNO, Nano) as explained in\n  [ArduinoUnit#70](https://github.com/mmurdoch/arduinounit/issues/70).\n* ArduinoUnit does not compile on the ESP8266 platform (see\n  [ArduinoUnit#68](https://github.com/mmurdoch/arduinounit/issues/68),\n  [ArduinoUnit#55](https://github.com/mmurdoch/arduinounit/issues/55),\n  [ArduinoUnit#54](https://github.com/mmurdoch/arduinounit/issues/54)).\n* ArduinoUnit does not provide an easy way to create tests using fixtures,\n  equivalent to the `TEST_F()` macro in Google Test.\n\nIn contrast:\n* AUnit consumes as much as 65% *less* flash memory than ArduinoUnit 2.2 on the\n  AVR platform. On Teensy-ARM, the savings can be as much as 30%.\n* AUnit has been tested on AVR, Teensy-ARM and ESP8266.\n* AUnit implements the `testF()` and `testingF()` macros to use fixtures.\n\nThe [AUniter](https://github.com/bxparks/AUniter) command line tools can compile\nthe unit tests, upload them to Arduino boards attached to the serial ports of\nthe local machine, and validate the output of the AUnit test runner. In\naddition, the AUniter script can be integrated into a\n[Jenkins](https://jenkins.io) continuous integration service running on the\nlocal machine, and the unit tests can be monitored automatically.\n\nUnit tests written using AUnit can often be compiled and executed natively on\nLinux or MacOS using the\n[EpoxyDuino](https://github.com/bxparks/EpoxyDuino) library. The output on\nthe `Serial` object is redirected to the `stdout` of the Unix host. This\nprovides another avenue for implementing continuous builds or integration.\n\n\u003ca name=\"ArduinoUnitCompatible\"\u003e\u003c/a\u003e\n### ArduinoUnit Compatible Features\n\nFor basic unit tests written using ArduinoUnit 2.2, only two changes are\nrequired to convert to AUnit:\n* `#include \u003cArduinoUnit.h\u003e` -\u003e `#include \u003cAUnit.h\u003e`\n* `Test::run()` -\u003e `aunit::TestRunner::run()`\n\nMost of the core macros are compatible between ArduinoUnit and AUnit:\n* `test()`\n* `testing()`\n* `assertXxx()`\n* Meta Assertions\n    * `checkTestXxx()`\n    * `assertTestXxx()`\n* `externTest()`\n* `externTesting()`\n\nAUnit also supports exclude and include filters:\n* `TestRunner::exclude()`\n* `TestRunner::include()`\n\nFilters can be accessed through\n[Command Line Flags](##CommandLineFlagsAndArguments) on desktop machines using\nEpoxyDuino\n\nThe various assertion and test status messages can be enabled or disabled using\nthe `Verbosity` flags on per test basis:\n* `enableVerbosity()`\n* `disableVerbosity()`\n\n\u003ca name=\"MissingFeatures\"\u003e\u003c/a\u003e\n### Missing Features\n\nHere are the features which have *not* been ported over from ArduinoUnit 2.2:\n\n* ArduinoUnit supports multiple `*` wildcards in its `exclude()` and `include()`\n  methods. AUnit supports only a single `*` wildcard and it must occur at the\n  end if present.\n\n\u003ca name=\"AddedFeatures\"\u003e\u003c/a\u003e\n### Added Features\n\nHere are the features in AUnit which are not available in ArduinoUnit 2.2:\n\n* Configurable timeout parameter to prevent `testing()` test cases from\n  running forever:\n    * `TestRunner::setTimeout(seconds)`\n    * `Test::expire()`\n    * `assertTestExpire()`\n    * `assertTestNotExpire()`\n    * `checkTestExpire()`\n    * `checkTestNotExpire()`\n* Case-insensitive string comparisons:\n    * `assertStringCaseEqual()`\n    * `assertStringCaseNotEqual()`\n* Approximate comparisons:\n    * `assertNear()`\n    * `asssertNotNear()`\n* Supports 64-bit integer\n    * `assertXxx()` support both `long long` and `unsigned long long`\n* `test()` and `testing()` macros support both 1 and 2 arguments\n    * `test(testName)` and `test(suiteName, testName)`\n    * `testing(testName)` and `testing(suiteName, testName)`\n* Test fixtures using the \"F\" variations of existing macros:\n    * `testF()`\n    * `testingF()`\n    * `assertTestXxxF()`\n    * `checkTestXxxF()`\n    * `externTestF()`\n    * `externTestingF()`\n* Unconditional termination:\n    * `passTestNow()`\n    * `failTestNow()`\n    * `skipTestNow()`\n    * `expireTestNow()`\n* `teardown()` method which mirrors the `setup()` method:\n    * `teardown()`\n* Test filters support 2-arguments, matching `testF()` and `testingF()`:\n    * `TestRunner::include(testClass, name)`\n    * `TestRunner::exclude(testClass, name)`\n* No dynamic allocation of heap memory:\n    * The library does not create a `String` object.\n    * It reads from a `String` if the calling code provides it.\n* Terse and verbose modes:\n    * `#include \u003cAUnit.h\u003e` - terse messages use less flash memory\n    * `#include \u003cAUnitVerbose.h\u003e` - verbose messages use more flash memory\n\nEvery feature of AUnit is unit tested using AUnit itself.\n\n\u003ca name=\"Installation\"\u003e\u003c/a\u003e\n## Installation\n\nThe latest stable release is available in the Arduino IDE Library Manager.\nSearch for \"unit test\" or \"AUnit\", select \"AUnit\", then click the \"Install\"\nbutton.\n\nThe development version can be installed by cloning the\n[GitHub repository](https://github.com/bxparks/AUnit), checking out the\n`develop` branch, then manually copying over the contents to the `./libraries`\ndirectory used by the Arduino IDE. (The result is a directory named\n`./libraries/AUnit`.) See the Preferences menu for the location of the Arduino\nsketch directory. The `master` branch contains the stable release.\n\nUsing either installation method, you may need to restart the Arduino IDE to\npick up the new library.\n\n\u003ca name=\"SourceCode\"\u003e\u003c/a\u003e\n### Source Code\n\nThe source files are organized as follows:\n* `src/AUnit.h` - main header file\n* `src/AUnitVerbose.h` - verbose version of main header file\n* `src/aunit/` - all implementation files\n* `tests/` - unit tests written using AUnit itself\n* `examples/` - example sketches\n\n\u003ca name=\"Documentation\"\u003e\u003c/a\u003e\n## Documentation\n\n* [README.md](README.md) - this file\n* [Doxygen docs](https://bxparks.github.io/AUnit/html) published on GitHub\n  Pages can help navigate the classes and header files\n\n\u003ca name=\"Examples\"\u003e\u003c/a\u003e\n### Examples\n\nThe `examples/` directory has a number of examples:\n\n* Basic\n    * [basic](examples/basic)\n        * using the `test()` macro\n    * [fixture](examples/fixture)\n        * how to use the `testF()` macro with test fixtures\n* Intermediate\n    * [filter](examples/filter)\n        * how to filter tests using `TestRunner::include()` and\n          `TestRunner::exclude()`\n    * [meta_asserts](examples/meta_asserts)\n        * how to use `assertTestXxx()` and `checkTestXxx()`\n* Advanced\n    * [advanced](examples/advanced/)\n        * how to subclass `Test` and `TestOnce` manually\n    * [continuous](examples/continuous)\n        * using the `testing()` macro\n* Benchmarks\n    * These are internal benchmark programs, not meant as examples (they are in\n      the `examples/` directory because of the Arduino IDE).\n    * [MemoryBenchmark](examples/MemoryBenchmark)\n        * Determines the flash and static memory consumption of AUnit for\n          various microcontroller\n\nIn the `tests/` directory, there are unit tests to test the AUnit framework\nitself:\n\n* [AUnitTest](tests/AUnitTest)\n    * the unit test for core `AUnit` functions\n* [AUnitMoreTest](tests/AUnitMoreTest)\n    * more tests\n* [AUnitMetaTest](tests/AUnitMetaTest)\n    * the unit test for meta assertions and `extern*()` macros\n* [CompareTest](tests/CompareTest)\n    * tests for the low-level compare functions\n* [FailingTest](tests/FailingTest)\n    * tests that are expected to fail\n* [FilterTest](tests/FilterTest)\n    * manual tests for `include()` and `exclude()` filters\n* [Print64Test](tests/Print64Test)\n    * manual tests for `include()` and `exclude()` filters\n* [SetupAndTeardownTest](tests/SetupAndTeardownTest)\n    * tests to verify that `setup()` and `teardown()` are called properly by the\n      finite state machine\n* [tests/Makefile](tests/Makefile)\n    * Runs the tests on a Linux or Mac machine using EpoxyDuino\n\nPerhaps the best way to see AUnit in action is through real life examples. All\nmy libraries use AUnit for testing and for continuous integration through\nEpoxyDuino. Here are some of my libraries:\n\n* [AceButton](https://github.com/bxparks/AceButton)\n    * My first Arduino library, which originally used ArduinoUnit 2.2.\n    * I kept many of the original ArduinoUnit tests for backwards compatibility\n      testing. But over time, I started to use more AUnit features so I'm not\n      sure if they work with ArduinoUnit anymore.\n* [AceCRC](https://github.com/bxparks/AceCRC)\n* [AceCommon](https://github.com/bxparks/AceCommon)\n* [AceRoutine](https://github.com/bxparks/AceRoutine)\n* [AceSegment](https://github.com/bxparks/AceSegment)\n* [AceSorting](https://github.com/bxparks/AceSorting)\n* [AceTime](https://github.com/bxparks/AceTime)\n\n\u003ca name=\"Usage\"\u003e\u003c/a\u003e\n## Usage\n\nIn this section, information about differences between AUnit and ArduinoUnit\nwill appear in a note marked by ***ArduinoUnit Compatibility***.\n\n\u003ca name=\"HeaderAndNamespace\"\u003e\u003c/a\u003e\n### Header and Namespace\n\nTo prevent name clashes with other libraries and code, all classes in the AUnit\nlibrary are defined in the `aunit` namespace. The user will mostly interact with\nthe `TestRunner` class. It can be referenced with an explicit namespace\nqualifier (i.e. `aunit::TestRunner`), or we can use a `using` directive like\nthis:\n```C++\n#include \u003cAUnit.h\u003e\nusing aunit::TestRunner;\n```\nor we can import the entire `aunit` namespace:\n```C++\n#include \u003cAUnit.h\u003e\nusing namespace aunit;\n```\n\nSimilar to ArduinoUnit, many of the \"functions\" in this framework (e.g.\n`test()`, `testing()`, `assertXxx()`) are defined as `#define` macros which live\nin the global namespace, so it is usually not necessary to import the entire\n`aunit` namespace.\n\n\u003ca name=\"VerboseMode\"\u003e\u003c/a\u003e\n### Verbose Mode\n\nBy default, AUnit generates terse assertion messages by leaving out\nthe string arguments of the various `assertXxx()` macros. If you would like\nto get the same verbose output as ArduinoUnit, use the following header\ninstead:\n\n```C++\n#include \u003cAUnitVerbose.h\u003e\n```\n\nThe flash memory consumption on an 8-bit AVR may go up by 20-25% for medium to\nlarge tests. On Teensy ARM, ESP8266 or ESP32, the increased memory size probably\ndoes not matter too much because these microcontrollers have far more flash and\nstatic memory.\n\n\u003ca name=\"DefiningTests\"\u003e\u003c/a\u003e\n### Defining the Tests\n\nThe usage of **AUnit** is basically identical to **ArduinoUnit**. The following\nmacros are used to create a test:\n\n* `test(name) {...}` - creates a subclass of `TestOnce`\n* `testing(name) {...}` - creates a subclass of `TestAgain`\n* `test(suiteName, name) {...}` - creates a subclass of `TestOnce`\n* `testing(suiteName, name) {...}` - creates a subclass of `TestAgain`\n* `testF(classname, name) {...}` - creates a subclass of `classname`\n* `testingF(classname, name) {...}` - creates a subclass of `classname`\n\nThe code in `{ }` following these macros becomes the body of a method in a\nsubclass derived from the base class indicated above. The `test()` and `testF()`\nmacros place the code body into the `TestOnce::once()` method. The `testing()`\nand `testingF()` macros place the code body into the `TestAgain::again()`\nmethod.\n\nThe `test()` and `testing()` macros support 1 or 2 arguments. The one-argument\nversion is inherited from ArduinoUnit. The two-argument version is\nanalogous to the `TEST()` macro in GoogleTest, where the `suiteName` can\nbe used to organize multiple tests into a collection of similar tests. The\ngrouping is purely in the naming scheme of the generated code, there is no\nfunctional relationship between these tests.\n\nDuring static initialization, the constructor of the object adds itself to an\ninternal list. The root of that list is given by `Test::getRoot()`. The\n`TestRunner::run()` method traverses the linked list, executing each test case\nuntil it passes, fails or is skipped.\n\nHere is a rough outline of an AUnit unit test sketch:\n\n```C++\n#line 2 \"AUnitTest.ino\"\n\n#include \u003cAUnit.h\u003e\nusing namespace aunit;\n\ntest(example) {\n  ...\n  assertXxx(...)\n  ...\n}\n\ntest(ExampleTest, example) {\n  ...\n}\n\ntesting(looping) {\n  ...code...\n  if (...) {\n    pass();\n  } else if (...) {\n    failTestNow();\n  } else {\n    skipTestNow();\n  }\n}\n\ntesting(LoopingTest, looping) {\n  ...\n}\n\nclass CustomTestOnce: public TestOnce {\n  protected:\n    // optional\n    void setup() override {\n      TestOnce::setup();\n      ...setup code...\n    }\n\n    // optional\n    void teardown() override {\n      ...teardown code...\n      TestOnce::teardown();\n    }\n\n    void assertBigStuff() {\n      ...higher level assertions...\n    }\n};\n\ntestF(CustomTestOnce, example_test) {\n  ...\n  assertBigStuff();\n  ...\n}\n\nclass CustomTestAgain: public TestAgain {\n  protected:\n    // optional\n    void setup() override {\n      TestAgain::setup();\n      ...setup code...\n    }\n\n    // optional\n    void teardown() override {\n      ...teardown code...\n      TestAgain::teardown();\n    }\n\n    void assertBigStuff() {\n      ...various assertions...\n    }\n};\n\ntestingF(CustomTestAgain, example_test) {\n  ...\n  assertBigStuff();\n  ...\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  while (! Serial); // Wait until Serial is ready - Leonardo/Micro\n\n  TestRunner::exclude(\"*\");\n  TestRunner::include(\"looping*\");\n  TestRunner::include(\"CustomTestAgain\", \"example*\");\n}\n\nvoid loop() {\n  TestRunner::run();\n}\n```\n\n***ArduinoUnit Compatibility***: _The basic structure of the unit test is\nidentical to ArduinoUnit. AUnit adds the `testF()` and `testingF`() macros,\nand the two-argument versions of `test()` and `testing()` which\nare not available in ArduinoUnit. The `Test` class in ArduinoUnit has been\nreplaced with the `TestAgain` class in AUnit._\n\n\u003ca name=\"GeneratedClass\"\u003e\u003c/a\u003e\n### Generated Class and Instance Names\n\nThe arguments to the various `test*()` macros are used to generate the name for\nthe subclasses of `TestOnce` or `TestAgain`, and generate the names of the\ninstances of those classes. For reference, here are the rules:\n\n* `test(name)`\n    * class: `\"test_\"` + name\n    * instance: `\"test_\"` + name + `\"_instance\"`\n* `testing(name)`\n    * class: `\"test_\"` + name\n    * instance: `\"test_\"` + name + `\"_instance\"`\n* `test(suiteName, name)`\n    * class: `suiteName` + `\"_\"` + name\n    * instance: `suiteName` + `\"_\"` + name + `\"_instance\"`\n* `testing(suiteName, name)`\n    * class: `suiteName` + `\"_\"` + name\n    * instance: `suiteName` + `\"_\"` + name + `\"_instance\"`\n* `testF(className, name)`\n    * class: `className` + `\"_\"` + name\n    * instance: `className` + `\"_\"` + name + `\"_instance\"`\n* `testingF(className, name)`\n    * class: `className` + `\"_\"` + name\n    * instance: `className` + `\"_\"` + name + `\"_instance\"`\n\nThe instance name is available within the test code using the `Test::getName()`\nmethod.\n\n\u003ca name=\"BinaryAssertions\"\u003e\u003c/a\u003e\n### Binary Assertions\n\nInside the `test()` and `testing()` macros, the following assertions\nare available. These are essentially identical to ArduinoUnit:\n\n* `assertEqual(a, b)`\n* `assertNotEqual(a, b)`\n* `assertLess(a, b)`\n* `assertMore(a, b)`\n* `assertLessOrEqual(a, b)`\n* `assertMoreOrEqual(a, b)`\n\n\u003ca name=\"AssertionMessageFormat\"\u003e\u003c/a\u003e\n#### Assertion Message Format\n\nWhen the assertion passes, nothing is printed by default. This can be controlled\nby the `TestRunner::setVerbosity()` method. See [Controlling\nVerbosity](#ControllingVerbosity).\n\nWhen the assertion fails, an error message of the following format is printed:\n\n```\nSampleTest.ino:10: Assertion failed: (2) == (1)\n```\n\nThe format of the assertion failure messages was changed in v1.7 to the\nfollowing:\n```\n{fileName}:{lineNumber}: Assertion failed: {expression}\n```\n\nThis format is a widely used in many other programs, for example, the C compiler\n`gcc`, the C++ compiler `g++`, the Python 3 interpreter `python3`, `grep`, and\nthe GNU Make program `make`. In particular, the\n[quickfix](https://vimhelp.org/quickfix.txt.html) feature in the `vim` text\neditor can parse this error format and jump directly to the `fileName` and\n`lineNumber` indicated by the error message. See the instructions in\n[EpoxyDuino](https://github.com/bxparks/EpoxyDuino) to see how to run unit tests\non a Linux or MacOS machine inside the `vim` editor so that the editor jumps\ndirectly to the files and line numbers where the assertion failure occurred.\n\n\u003ca name=\"SupportedParameterTypes\"\u003e\u003c/a\u003e\n#### Supported Parameter Types\n\nThe 6 core assert macros (`assertEqual()`, `assertNotEqual()`, `assertLess()`,\n`assertMore()`, `assertLessOrEqual()`, `assertMoreOrEqual()`) support the\nfollowing 18 combinations for their parameter types:\n\n* `(bool, bool)`\n* `(char, char)`\n* `(int, int)`\n* `(unsigned int, unsigned int)`\n* `(long, long)`\n* `(unsigned long, unsigned long)`\n* `(long long, long long)`\n* `(unsigned long long, unsigned long long)`\n* `(double, double)`\n* `(const char *, const char *)`\n* `(const char *, const String\u0026)`\n* `(const char *, const __FlashStringHelper*)`\n* `(const String\u0026, const char*)`\n* `(const String\u0026, const String\u0026)`\n* `(const String\u0026, const __FlashStringHelper*)`\n* `(const __FlashStringHelper*, const char*)`\n* `(const __FlashStringHelper*, const String\u0026)`\n* `(const __FlashStringHelper*, const __FlashStringHelper*)`\n\nThe `assertEqual()` and `assertNotEqual()` support arbitrary pointer types\nthrough implicit casts to `const void*`:\n\n* `(const void*, const void*)` (since v1.4)\n\nAll 9 combinations of the 3 string types (`char*`, `String`, and\n`__FlashStringHelper*`) are supported.\n\nThese macros perform deep comparisons for string types instead of just comparing\ntheir pointer values. This is different than the `ASSERT_EQ()` and `ASSERT_NE()`\nmacros in Google Test which perform only pointer comparisons. In other words,\n`assertEqual()` with string types is equivalent to `ASSERT_STREQ()` in Google\nTest.\n\nAlso for string types, these macros support `nullptr` (unlike the underlying\n`strcmp()` function from the C-library). The `nullptr` string is defined to be\n\"smaller\" than any non-null string, including the empty string. Two `nullptr`\nstrings are considered to be equal however.\n\nAdditionally, the usual C++ implicit type conversion and function overloading\nmatching algorithms apply to support additional argument types.\nFor example, the following type conversions will occur:\n\n* `signed char` -\u003e `int`\n* `unsigned char` -\u003e `int`\n* `short` -\u003e `int`\n* `unsigned short` -\u003e `int` or `unsigned int` (depending on `sizeof(int)`)\n* `char*` -\u003e `const char*`.\n* `char[N]` -\u003e `const char*`\n* `float` -\u003e `double`\n* pointer types -\u003e `const void*`\n\nNote that `char`, `signed char`, and `unsigned char` are 3 distinct types in\nC++, so a `(char, char)` will match exactly to one of the `assertXxx()`\nmethods.\n\n***ArduinoUnit Compatibility***:\n_The names of the macros are identical. However, the\ntype inference logic of two `(a, b)` arguments in the `assertXxx(a, b)` is\nslightly different. ArduinoUnit allows the two parameters to be slightly\ndifferent types, at the expense of a compiler warning. In AUnit, the\nwarning becomes a compiler error. See the \"Parameters Must Match Types\" section\nbelow._\n\n\u003ca name=\"ParameterTypesMustMatch\"\u003e\u003c/a\u003e\n#### Parameter Types Must Match\n\nIn ArduinoUnit, the `assertXxx()` macros could be slightly different types, for\nexample:\n```C++\nunsigned int uintValue = 5;\nassertEqual(5, uintValue);\n```\n\nIf the compiler warnings are enabled in the Preferences box of the\nIDE, a warning from the compiler is printed:\n\n```\n../ArduinoUnit/src/ArduinoUnitUtility/Compare.h:17:28: warning:\n    comparison between signed and unsigned integer expressions [-Wsign-compare]\n    return (!(a\u003cb)) \u0026\u0026 (!(b\u003ca));\n```\n\nIn AUnit, the above code produces a compiler error (not a warning) like this:\n```\n.../AUnit/src/aunit/Assertion.h:29:66: error: call of overloaded\n    'assertion(const char [14], int, int, const char[3], \u003cunresolved overloaded\n    function type\u003e, unsigned int\u0026)' is ambiguous\n    if (!aunit::assertion(__FILE__,__LINE__,(arg1),opName,op,(arg2)))\\\n...\n```\nThe compiler cannot find an appropriate overloaded version of `assertEqual()`.\n\nThe solution is to make the parameters the same type:\n```C++\nassertEqual(5U, uintValue);\n```\n\nOn the AVR platform, both a (short) and (int) are 16-bit types, so the following\nwill produce a compiler error:\n```C++\nunsigned short ushortValue = 5;\nassertEqual(5U, ushortValue);\n```\nBut on Teensy-ARM, ESP8266, and ESP32, a 16-bit (short) can be promoted to a\n32-bit (int) without loss of precision, so the above will compile just fine. For\nportability, the following should be used on all platforms:\n```C++\nunsigned short ushortValue = 5;\nassertEqual((unsigned short) 5, ushortValue);\n```\n\nThe integer type promotion rules and function overload matching rules can be\ndifficult to remember (and sometimes difficult to understand). The best way to\navoid these compiler errors is to make sure that the assertion parameter types\nare identical, potentially using explicit casting.\n\n\u003ca name=\"PointerComparisons\"\u003e\u003c/a\u003e\n#### Pointer Comparisons\n\nVersion 1.4 adds pointer comparison to `assertEqual()` and `assertNotEqual()`.\nArbritary pointers are implicitly cast to a `const void*` and compared to\neach other. If the assertion fails, the pointer is converted to an integer type,\nand the hexadecimal value of the pointer is printed. For example,\n\n```C++\ntest(voidPointer) {\n  const int aa[] = {1, 2};\n  const long bb[] = {1, 2};\n\n  assertEqual(aa, bb);\n}\n```\n\nThis test will fail with the following error message:\n```\nAUnitTest.ino:338: Assertion failed: (aa=0x3FFFFF38) == (bb=0x3FFFFF30).\nTest voidPointer failed.\n```\n\nComparison against the `nullptr` will work:\n\n```C++\ntest(nullPointer) {\n  const int aa[] = {1, 2};\n  assertEqual(aa, nullptr);\n}\n```\n\nThis will print the following:\n\n```\nAUnitTest.ino:348: Assertion failed: (aa=0x3FFFFF58) == (nullptr=0x0).\nTest nullPointer failed.\n```\n\nComparing a string type (i.e. `const char*`, or `const __FlashStringHelper*`)\nto a `nullptr` will cause an error due to ambiguous matches on overloaded\nfunctions. The solution is to explicitly cast the `nullptr` to the corresponding\nstring type:\n\n```C+++\ntest(stringPointer) {\n  const char aa[] = \"abc\";\n\n  // assertEqual(aa, nullptr); // Causes errors\n\n  assertEqual(aa, (const char*) nullptr); // Works.\n}\n```\n\n\u003ca name=\"CaseInsensitiveStrings\"\u003e\u003c/a\u003e\n#### Case Insensitive String Comparisons\n\nTwo macros provide case-insensitive string comparisons (analogous to\n`ASSERT_STRCASEEQ()` and `ASSERT_STRCASENE()` in Google Test):\n\n* `assertStringCaseEqual(a, b)`\n* `assertStringCaseNotEqual(a, b)`\n\nThe supported types for `(a, b)` are all 9 combinations of Arduino string types:\n\n* `(const char *, const char *)`\n* `(const char *, const String\u0026)`\n* `(const char *, const __FlashStringHelper*)`\n* `(const String\u0026, const char*)`\n* `(const String\u0026, const String\u0026)`\n* `(const String\u0026, const __FlashStringHelper*)`\n* `(const __FlashStringHelper*, const char*)`\n* `(const __FlashStringHelper*, const String\u0026)`\n* `(const __FlashStringHelper*, const __FlashStringHelper*)`\n\n***ArduinoUnit Compatibility***: _Not available in ArduinoUnit._\n\n\u003ca name=\"ApproximateComparisons\"\u003e\u003c/a\u003e\n### Approximate Comparisons\n\nFloating point values are difficult to compare because of internal rounding\nerrors. Google Test provides\n[two types of macros to handle floating points](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#floating-point-comparison):\n* `ASSERT_FLOAT_EQ(a, b)`, `ASSERT_DOUBLE_EQ(a, b)` - determine if the\n  floating point numbers are within 4\n  [Units in the Last Place (ULPs)](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)\n* `ASSERT_NEAR(a, b, error)` - determine if the absolute distance between\n  `a` and `b` is within the given `error`\n\nSince floating point operations are relatively rare in Arduino programming,\nAUnit offers only the equivalent of `ASSERT_NEAR()` function:\n\n* `assertNear(a, b, error)`\n* `assertNotNear(a, b, error)`\n\nUpon failure, the error messages will look something like:\n```\nAUnitTest.ino:517: Assertion failed: |(1.00) - (1.10)| \u003e (0.20).\nAUnitTest.ino:527: Assertion failed: |(4.00) - (1.10)| \u003c= (0.20).\n```\n\nUnlike Google Test where `ASSERT_NEAR()` supports only the `double` type, both\n`assertNear()` and `assertNotNear()` support integral types as well. The full\nlist of supported types is:\n\n* `int`\n* `unsigned int`\n* `long`\n* `unsigned long`\n* `double`\n\nOther primitive types (e.g. `char` or `float`) will be automatically converted\nto one of these supported types by the compiler. (64-bit integer types\n`long long` and `unsigned long long` are not supported here.)\n\nNote that the `abs()` of 2 values of a signed integer type can be larger than\nthe maximum value that can be represented by the given signed type. Since signed\ninteger overflow is an\n[undefined behavior](https://stackoverflow.com/questions/16188263/is-signed-integer-overflow-still-undefined-behavior-in-c)\nin C and C++11, I cannot predict what the compiler will do in that case.\nUnsigned types should not have this problem because the distance between two\nvalues of an unsigned type should always fit inside the given unsigned type.\nTechnically, a similar problem exists for the floating point types (which are\nnaturally signed), but it is unlikely that you are dealing with floating point\nvalues so close to the maximum values.\n\n\u003ca name=\"BooleanAssertions\"\u003e\u003c/a\u003e\n### Boolean Assertions\n\nThe following boolean asserts are also available:\n\n* `assertTrue(condition)`\n* `assertFalse(condition)`\n\n***ArduinoUnit Compatibility***: _These are identical to ArduinoUnit._\n\n\u003ca name=\"TestFixtures\"\u003e\u003c/a\u003e\n### Test Fixtures\n\nWhen the unit tests become more complex, using test fixtures will allow you to\nplace common data objects and methods into a class that can be shared among\nmultiple test cases. This concept matches very closely to the test fixtures\nin\n[Google Test](https://github.com/google/googletest/blob/master/googletest/docs/Primer.md).\n\nTo create a test fixture:\n1. Derives a new class from either `TestOnce` (if you want to run the test just\n   once), or `TestAgain` (if you want to run the test repeatedly).\n1. Add any data objects inside the class.\n1. Optionally add a `virtual void setup() {...}` method to perform any common\n   initialization code. Be sure to call the parent's `setup()` method in the\n   *first* line to chain any `setup()` methods defined by the parents. There may\n   be multiple parent classes.\n1. Optionally add a `virtual void teardown() {...}` method to perform any common\n   clean up code. Be sure to call the parent's `teardown()` method in the *last*\n   line to chain any `teardown()` methods defined by the parents. There may be\n   multiple parent classes.\n1. Add any additional shared methods into this new class.\n\nTo define your tests, use the `testF()` macro like this:\n```C++\nclass CustomTestOnce: public TestOnce {\n  protected:\n    // optional\n    void setup() override {\n      TestOnce::setup();\n      ...setup code...\n    }\n\n    // optional\n    void teardown() override {\n      ...teardown code...\n      TestOnce::teardown();\n    }\n\n    void assertCustomStuff() {\n      ...common code...\n    }\n\n    int sharedValue;\n};\n\ntestF(CustomTestOnce, calculate) {\n  ...test code here...\n}\n```\nNo constructor for `CustomTestOnce` needs to be defined.\n\nUnderneath the covers, the `testF()` macro creates a subclass named\n`CustomTestOnce_calculate` which inherits from `TestOnce` class. The test code\nbecomes the body of the `CustomTestOnce_calculate::once()` method. The name of\nthis test has the class name prepended, so it is `CustomTestOnce_calculate`,\nwhich prevents name collision with other `testF()` tests with the same\nname using a different test fixture class.\n\nTo define a continuous test, use the `testingF()` macro like this:\n```C++\nclass CustomTestAgain: public TestAgain {\n  protected:\n    // optional\n    void setup() override {\n      TestAgain::setup();\n      ...setup code...\n    }\n\n    // optional\n    void teardown() override {\n      ...teardown code...\n      TestAgain::teardown();\n    }\n\n    void assertCustomStuff() {\n      ...common code...\n    }\n\n    int sharedValue;\n};\n\ntestingF(CustomTestAgain, calculate) {\n  ...test code here...\n}\n```\n\nSimilarly, the `testingF()` macro creates a subclass named\n`CustomTestAgain_calculate`, and the test code becomes the body of the\n`CustomTestAgain_calculate::again()` method.\n\nSee `examples/fixtures/fixtures.ino` to see a working example of the `testF()`\nmacro.\n\n***ArduinoUnit Compatibility***: _The `testF()` and `testingF()` macros,\nand the `teardown()` virtual method are available only in AUnit (and Google\nTest), not ArduinoUnit._\n\n\u003ca name=\"EarlyReturnDelayedAssertions\"\u003e\u003c/a\u003e\n### Early Return and Delayed Assertions\n\nAUnit (like ArduinoUnit and Google Test) does not use C++ exceptions. Instead,\nthe various `assertXxx()` macros perform an early `return` if the condition\nevaluates to `false`. That means that the assertions can only bail out of the\ncurrent method, not the calling method. If you are using test fixtures, and\ncreate a shared custom assert function, e.g. the `assertCustomStuff()` method\nabove, any `assertXxx()` statements in shared method will bail out of that\nmethod only. The statement after the `assertCustomStuff()` will continue to\nexecute.\n\nIn other words, in the following example, if the `assertCustomStuff()` fails,\nthen `assertMoreStuff()` inside `testF()` will execute:\n\n```C++\nclass CustomTestOnce: public TestOnce {\n  protected:\n    void assertCustomStuff() {\n      assertEqual(sharedValue, 3);\n\n      // This will not execute if the assertEqual() above fails.\n      assertLess(...);\n    }\n\n    void assertMoreStuff() {\n      assertEqual(...);\n    }\n\n    int sharedValue;\n};\n\n// DON'T DO THIS\ntestF(CustomTestOnce, dontDoThis) {\n  assertCustomStuff();\n\n  // This will execute even if assertCustomStuff() fails.\n  assertMoreStuff();\n}\n\n// DO THIS INSTEAD\ntestF(CustomTestOnce, doThis) {\n  assertNoFatalFailure(assertCustomStuff());\n  assertNoFatalFailure(assertMoreStuff());\n}\n```\n\nThe solution is to use the `assertNoFatalFailure(statement)` macro which checks\nwhether the inner `statement` returned with a fatal assertion. If so, then it\nreturns immediately, preventing execution from continuing to the code that\nfollows. This macro is modeled after the\n[ASSERT_NO_FATAL_FAILURE(statement)](https://github.com/google/googletest/blob/master/docs/advanced.md)\nmacro in Google Test that provides the same functionality.\n\n\u003ca name=\"MetaAssertions\"\u003e\u003c/a\u003e\n### Meta Assertions\n\nThe following methods from ArduinoUnit have also been implemented:\n\n* `checkTestDone(name)`\n* `checkTestNotDone(name)`\n* `checkTestPass(name)`\n* `checkTestNotPass(name)`\n* `checkTestFail(name)`\n* `checkTestNotFail(name)`\n* `checkTestSkip(name)`\n* `checkTestNotSkip(name)`\n* `checkTestExpire(name)` [\u0026ast;]\n* `checkTestNotExpire(name)` [\u0026ast;]\n* `assertTestDone(name)`\n* `assertTestNotDone(name)`\n* `assertTestPass(name)`\n* `assertTestNotPass(name)`\n* `assertTestFail(name)`\n* `assertTestNotFail(name)`\n* `assertTestSkip(name)`\n* `assertTestNotSkip(name)`\n* `assertTestExpire(name)` [\u0026ast;]\n* `assertTestNotExpire(name)` [\u0026ast;]\n\nThe `checkTestXxx()` methods check the status of the test named `name`\nand returns a `bool`. The execution continues even if `false`.\n\nThe `assertTestXxx()` methods stops the unit test if the status check\nreturns `false`, and prints assertion messages that look like this:\n```\nAUnitTest.ino:366: Assertion passed: Test slow_pass is done.\nAUnitTest.ino:372: Assertion passed: Test slow_pass is not failed.\nAUnitTest.ino:448: Assertion passed: Test slow_skip is skipped.\nAUnitTest.ino:451: Assertion passed: Test slow_skip is not timed out.\n```\n(The human readable version of being `expired` will always be `timed out` or\n`not timed out` on the `Serial` output.)\n\nThe following macros define `extern` references to test case objects which live\nin other `.cpp` files. These are required for the above meta assertions if the\ntest cases are defined in another file:\n\n* `externTest()`\n* `externTesting()`\n* `externTestF()`\n* `externTestingF()`\n\n***ArduinoUnit Compatibility***: _The methods marked by [\u0026ast;] are only\navailable in AUnit. Also, the assertion messages are different. ArduinoUnit\nreuses the format used by the `assertXxx()` macros, so prints something like\nthe following:_\n```\nAUnitTest.ino:439: Assertion passed: (test_slow_skip_instance.state=2) \u003e= (Test::DONE_SKIP=2).\n```\n\n_AUnit has a separate message handler to print a customized message for the\nassertTestXxx() meta assertion macros._\n\n\u003ca name=\"UnconditionalTermination\"\u003e\u003c/a\u003e\n### Unconditional Termination\n\nThe following macros can be used inside the body of `test()` or `testing()`\nmacro to terminate a test unconditionally. Each macro prints a short message,\nand returns immediately from the test, much like an `assertXxx()` macro that\nfails.\n\n* `passTestNow()`  [\u0026ast;]\n* `failTestNow()` [\u0026ast;]\n* `skipTestNow()` [\u0026ast;]\n* `expireTestNow()` [\u0026ast;]\n\nThe messages look like:\n```\nAUnitTest.ino:360: Status passed.\nAUnitTest.ino:378: Status failed.\nAUnitTest.ino:380: Status skipped.\nAUnitTest.ino:391: Status timed out.\n```\n\nThe following methods on the `Test` class also set the `status` of the test, but\nthese methods do not print any messages (which makes debugging difficult) and\nthey do *not* terminate the test immediately.\n\n* `pass()` - test passed\n* `fail()` - test failed\n* `skip()` - test skipped\n* `expire()`  - test timed out [\u0026ast;]\n\nIn most cases, the `failTestNow()`, `skipTestNow()` and `expireTestNow()` macros\nare more useful than the equivalent methods in the `Test` class. However, in a\n`testing()` loop test, the `pass()` method is probably better than the\n`passTestNow()` macro because we usually don't want to see an error message\nfrom a passing test.\n\n***ArduinoUnit Compatibility***:\n_The method(s) marked by [\u0026ast;] are only available in AUnit._\n\n\u003ca name=\"OverridableMethods\"\u003e\u003c/a\u003e\n### Overridable Methods\n\nThe following methods are defined at the `Test` base class level:\n\n* `setup()`\n* `teardown()`\n\nThe `TestOnce` class defines:\n* `once()`\n\nThe `TestAgain` class defines:\n* `again()`\n\n***ArduinoUnit Compatibility***: _These are functionally the same as ArduinoUnit\nexcept with different class names. Instead of `Test` use `TestAgain`. Instead\nof `Test::loop` use `TestAgain::again()`. ArduinoUnit does not support a\n`teardown()` method._\n\n\u003ca name=\"RunningTests\"\u003e\u003c/a\u003e\n### Running the Tests\n\nWe run the test cases in the global `loop()` method by calling\n`TestRunner::run()`. The tests are sorted according to the name of the test\ngiven in the argument in the `test()` or `testing()` macro.\n\nEach call to the `run()` method causes one test case to run and be resolved. The\nnext call to `run()` executes the next test case. This design allows the\n`loop()` method to perform a small amount of work and return periodically to\nallow the system to perform some actions. On some systems, such as the ESP8266,\nan error is generated if `loop()` takes too much CPU time.\n\n```C++\n...\nvoid loop() {\n  TestRunner::run();\n}\n```\n\n***ArduinoUnit Compatibility***: _This is equivalent to called `Test::run()` in\nArduinoUnit. AUnit sorts the tests in the same way as ArduinoUnit. In\nArduinoUnit, each call to `Test::run()` will process the entire list of\ncurrently active test cases. In AUnit, each call to `TestRunner::run()` performs\nonly a single test case, then returns._\n\n\u003ca name=\"FilteringTestCases\"\u003e\u003c/a\u003e\n### Filtering Test Cases\n\nSix filtering methods are available on the `TestRunner` class:\n* `TestRunner::include(pattern)` - prefix match\n* `TestRunner::include(testClass, pattern)` - prefix match\n* `TestRunner::exclude(pattern)` - prefix match\n* `TestRunner::exclude(testClass, pattern)` - prefix match\n* `TestRunner::includesub(substring)` - substring match (v1.6)\n* `TestRunner::excludesub(substring)` - substring match (v1.6)\n\nThese methods are called from the global `setup()` method, for example:\n\n```C++\nvoid setup() {\n  TestRunner::include(\"looping*\");\n  TestRunner::exclude(\"CustomTestAgain\", \"*\");\n  TestRunner::include(\"CustomTestAgain\", \"test*\");\n  TestRunner::include(\"CustomTestAgain\", \"test*\");\n  TestRunner::includesub(\"net\");\n  TestRunner::excludesub(\"net\");\n  ...\n}\n```\n\nExcluded tests bypass their `Test::setup()` and `Test::teardown()` methods and\nterminate immediately. For the purposes of reporting, excluded tests are counted\nas \"skipped\".\n\nThe 2-argument versions of `include()` and `exclude()` correspond to the\n2 arguments of `testF()` and `testingF()`.\n\nThe filtering methods are also available as command line flags and arguments\n(`--include`, `--exclude`, `--includesub` `--excludesub`) if the test\nprogram is compiled using EpoxyDuino under a Unix-like environment. See\nthe [EpoxyDuino](#EpoxyDuino) section below.\n\n**Implicit Exclude All**: If the *first* filtering request is an \"include\" (i.e.\n`include(pattern)`, `include(testClass, pattern)`, `includesub(substring)`),\nall tests are excluded by default initially, instead of being included by\ndefault. Otherwise, the first \"include\" statement would have no effect.\n\n***ArduinoUnit Compatibility***:\n_The equivalent versions in ArduinoUnit are `Test::exclude()` and\n`Test::include()` The matching algorithm in AUnit is not as powerful as the one\nin ArduinoUnit. AUnit supports only a single wildcard character `*` and that\ncharacter can appear only at the end if it is present. For example, the\nfollowing are accepted:_\n\n* `TestRunner::exclude(\"*\");`\n* `TestRunner::include(\"f*\");`\n* `TestRunner::exclude(\"flash_*\");`\n* `TestRunner::include(\"looping*\");`\n* `TestRunner::include(\"CustomTestOnce\", \"flashTest*\");`\n\n_AUnit provides 2-argument versions of `include()` and `exclude()`_\n\n\u003ca name=\"OutputPrinter\"\u003e\u003c/a\u003e\n### Output Printer\n\nThe default output printer is the `Serial` instance. This can be\nchanged using the `TestRunner::setPrinter()` method:\n\n```C++\n#include \u003cAUnit.h\u003e\nusing aunit::TestRunner;\n...\n\nvoid setup() {\n  Serial1.begin(...);\n\n  TestRunner::setPrinter(\u0026Serial1);\n  ...\n}\n\nvoid loop() {\n  TestRunner::run();\n}\n```\n\n***ArduinoUnit Compatibility***:\n_This is the equivalent of the `Test::out` static member variable in\nArduinoUnit._\n\n\u003ca name=\"ControllingVerbosity\"\u003e\u003c/a\u003e\n### Controlling the Verbosity\n\nThe default verbosity of the test results can be controlled using the\n`TestRunner::setVerbosity()` method:\n```C++\n#include \u003cAUnit.h\u003e\nusing aunit::TestRunner;\nusing aunit::Verbosity;\n...\nvoid setup() {\n  ...\n  TestRunner::setVerbosity(Verbosity::kAll);\n  ...\n}\n```\n\nEvery test is assigned this default verbosity just before its `Test::setup()`\nis called. A unit test can choose to modify the verbosity calling one of the\nfollowing methods:\n\n* `void enableVerbosity(uint8_t verbosity);`\n    * enables the given verbosity, retaining all the others\n* `void disableVerbosity(uint8_t verbosity);`\n    * disables the given verbosity, retaining all the others\n\nat the beginning of the test definition, like this:\n\n```C++\ntest(enable_assertion_passed_messages) {\n  enableVerbosity(Verbosity::kAssertionPassed);\n  ...\n}\n```\n\nThe values of `verbosity` are defined by the static constants of the `Verbosity`\nutility class:\n\n* `Verbosity::kAssertionPassed`\n* `Verbosity::kAssertionFailed`\n* `Verbosity::kTestPassed`\n* `Verbosity::kTestFailed`\n* `Verbosity::kTestSkipped`\n* `Verbosity::kTestExpired`\n* `Verbosity::kTestRunSummary`\n* `Verbosity::kAssertionAll` - enables all assert messages\n* `Verbosity::kTestAll`\n    * same as `(kTestPassed | kTestFailed | kTestSkipped | kTestExpired)`\n* `Verbosity::kDefault`\n    * same as `(kAssertionFailed | kTestAll | kTestRunSummary )`\n* `Verbosity::kAll` - enables all messages\n* `Verbosity::kNone` - disables all messages\n\n***ArduinoUnit Compatibility***:\n_The following ArduinoUnit variables do not exist:_\n* `Test::min_verbosity`\n* `Test::max_verbosity`\n\n_The bit field constants have slightly different names:_\n\n* `TEST_VERBOSITY_TESTS_SUMMARY` -\u003e `Verbosity::kTestRunSummary`\n* `TEST_VERBOSITY_TESTS_FAILED` -\u003e `Verbosity::kTestFailed`\n* `TEST_VERBOSITY_TESTS_PASSED` -\u003e `Verbosity::kTestPassed`\n* `TEST_VERBOSITY_TESTS_SKIPPED` -\u003e `Verbosity::kTestSkipped`\n* `TEST_VERBOSITY_TESTS_ALL` -\u003e `Verbosity::kTestAll`\n* `TEST_VERBOSITY_ASSERTIONS_FAILED` -\u003e `Verbosity::kAssertionFailed`\n* `TEST_VERBOSITY_ASSERTIONS_PASSED` -\u003e `Verbosity::kAssertionPassed`\n* `TEST_VERBOSITY_ASSERTIONS_ALL` -\u003e `Verbosity::kAssertionAll`\n* `TEST_VERBOSITY_ALL` -\u003e `Verbosity::kAll`\n* `TEST_VERBOSITY_NONE` -\u003e `Verbosity::kNone`\n* {no equivalent} \u003c- `Verbosity::kDefault`\n* {no equivalent} \u003c- `Verbosity::kTestExpired`\n\n\u003ca name=\"LineNumberMismatch\"\u003e\u003c/a\u003e\n### Line Number Mismatch\n\nAUnit suffers from the same compiler/preprocessor bug as ArduinoUnit that causes\nthe built-in `__LINE__` macro to be off by one. The solution is to add:\n```C++\n#line 2 \"filename.ino\"\n```\nas the first line of a unit test sketch, where the \"filename.ino\" must appear in\ndouble-quotes.\n\n***ArduinoUnit Compatibility***: _This problem is identical to ArduinoUnit._\n\n\u003ca name=\"TestFrameworkMessages\"\u003e\u003c/a\u003e\n### Test Framework Messages\n\n\u003ca name=\"AssertionMessage\"\u003e\u003c/a\u003e\n#### Assertion Message\n\nThe various `assertXxx()` macros in AUnit print a message upon pass or fail. For\nexample, if the assertion was:\n```C++\nint expected = 3;\nint counter = 4;\nassertEquals(expected, counter);\n```\n\nThe error message (if enabled, which is the default) is:\n```\nAUnitTest.ino:134: Assertion failed: (3) == (4).\n```\n\nAsserts with `bool` values produce customized messages, printing \"true\" or\n\"false\" instead of using the Print class default conversion to `int`:\n```C++\nassertEquals(true, false);\n\nAUnitTest.ino:134: Assertion failed: (true) == (false).\n```\n\nSimilarly, the `assertTrue()` and `assertFalse()` macros provide more customized\nmessages:\n```C++\nbool ok = false;\nassertTrue(ok);\n\nAUnitTest.ino:134: Assertion failed: (false) is true.\n```\n\nand\n```C++\nbool ok = true;\nassertFalse(ok);\n\nAUnitTest.ino:134: Assertion failed: (true) is false.\n```\n\n***ArduinoUnit Compatibility***:\n_ArduinoUnit captures the arguments of the `assertEqual()` macro\nand prints:_\n\n```\nAUnitTest.ino:134: Assertion failed: (expected=3) == (counter=4).\n```\n\n_Each capture of the parameter string consumes flash memory space. If the unit\ntest has numerous `assertXxx()` statements, the flash memory cost is expensive.\nAUnit omits the parameters to reduce flash memory space by about 33%._\n\n_The messages for asserts with bool values are customized for better clarity\n(partially to compensate for the lack of capture of the string of the actual\narguments, and are different from ArduinoUnit._\n\n\u003ca name=\"VerboseModeMessage\"\u003e\u003c/a\u003e\n#### Verbose Mode Message\n\nIf you use the verbose header:\n```C++\n#include \u003cAUnitVerbose.h\u003e\n```\nthe assertion message will contain the string fragments of the arguments\npassed into the `assertXxx()` macros, like this:\n\n```\nAUnitTest.ino:134: Assertion failed: (expected=3) == (counter=4).\nAUnitTest.ino:134: Assertion failed: (ok=false) is true.\n```\n\ninstead of:\n\n```\nAUnitTest.ino:134: Assertion failed: (3) == (4).\nAUnitTest.ino:134: Assertion failed: (false) is true.\n```\n\n***ArduinoUnit Compatibility***:\n_As of v1.7, the assertion message format is compatible with the vim editor\nand other Linux/MacOS/Unix tools, and no longer compatible with ArduinoUnit\n\n\u003ca name=\"TestCaseSummary\"\u003e\u003c/a\u003e\n#### Test Case Summary\n\nAs each test case finishes, the `TestRunner` prints out the summary of the test\ncase like this:\n\n```\nTest bad failed.\nTest looping_pass passed.\nTest looping_skip skipped.\nTest looping_until timed out.\n```\n\n***ArduinoUnit Compatibility***: _These are identifcal to ArduinoUnit,\nexcept that the \"timed out\" status is new to AUnit. See Test Timeout\nsection below._\n\n\u003ca name=\"TestRunnerSummary\"\u003e\u003c/a\u003e\n#### Test Runner Summary\n\nAt the end of the test run, the `TestRunner` prints out the summary\nof all test cases, like this:\n\n```\nTestRunner duration: 0.05 seconds.\nTestRunner summary: 12 passed, 0 failed, 2 skipped, 1 timed out, out of 15 test(s).\n```\n\n***ArduinoUnit Compatibility***: _The message format is slightly different than\nArduinoUnit. I changed \"Test summary\" to \"TestRunner summary\" because the former\nlooks identical to the message that could have been printed by a `test(summary)`\ntest case. AUnit also adds information about tests which timed out. See below._\n\n\u003ca name=\"TestTimeout\"\u003e\u003c/a\u003e\n### Test Timeout\n\n***ArduinoUnit Compatibility***: _Only available in AUnit._\n\nFrom my experience, it seems incredibly easy to write a `testing()` test case\nwhich accidentally runs forever because the code forgets to call an explicit\n`pass()`, `fail()` or `skip()`.\n\nThe `TestRunner` in AUnit applies a timeout value to all the test cases that it\nruns. The **default timeout is 10 seconds**. A timeout value of `0` means an\n**infinite** timeout, which means that the `testing()` test case may run\nforever. The value of the timeout is stored as a `uint16_t` type, so the maximum\ntimeout is 65535 seconds or a bit over 18 hours.\n\nCurrently, the timeout value is global to all test cases. Time out values for\nindividual tests cannot be set independently. If a test does not finish before\nthat time, then the test is marked as `timed out` (internally implemented by the\n`Test::expire()` method) and a message is printed like this:\n```\nTest looping_until timed out.\n```\n\nThe timeout value can be changed by calling the static\n`TestRunner::setTimeout()` method. Here is an example that sets the timeout to\n30 seconds instead:\n```C++\nvoid setup() {\n  ...\n  TestRunner::setTimeout(30);\n  ...\n}\n```\n\n***ArduinoUnit Compatibility***: _Only available in AUnit._\n\n\u003ca name=\"GoogleTestAdapter\"\u003e\u003c/a\u003e\n## GoogleTest Adapter\n\nIt may be possible to run simple unit tests written using\n[Google Test](https://github.com/google/googletest/) API on an Arduino platform\nby using the\n[aunit/contrib/gtest.h](src/aunit/contrib/gtest.h) adapter. This\nadapter layer provides a number of Google Test macros which map to\ntheir equivalent macros in AUnit:\n\n* `ASSERT_EQ(e, a)` - `assertEqual()`\n* `ASSERT_NE(e, a)` - `assertNotEqual()`\n* `ASSERT_LT(e, a)` - `assertLess()`\n* `ASSERT_GT(e, a)` - `assertMore()`\n* `ASSERT_LE(e, a)` - `assertLessOrEqual()`\n* `ASSERT_GE(e, a)` - `assertMoreOrEqual()`\n* `ASSERT_STREQ(e, a)` - `assertEqual()`\n* `ASSERT_STRNE(e, a)` - `assertNotEqual()`\n* `ASSERT_STRCASEEQ(e, a)` - `assertStringCaseEqual()`\n* `ASSERT_STRCASENE(e, a)` - `assertStringCaseNotEqual()`\n* `ASSERT_TRUE(x)` - `assertTrue()`\n* `ASSERT_FALSE(x)` - `assertFalse()`\n* `ASSERT_NEAR(e, a, error)` - `assertNear()`\n\nTo use the `gtest.h` adapter, include the following headers:\n```C++\n#include \u003cAUnit.h\u003e\n#include \u003caunit/contrib/gtest.h\u003e\n```\n\nor\n\n```C++\n#include \u003cAUnitVerbose.h\u003e\n#include \u003caunit/contrib/gtest.h\u003e\n```\n\n\u003ca name=\"CommandLineTools\"\u003e\u003c/a\u003e\n## Command Line Tools\n\nEach unit test is an independent `*.ino` program. You can run it using your\nArduino IDE. But there are 2 command line tools that can be used to run them.\n\n\u003ca name=\"AUniter\"\u003e\u003c/a\u003e\n### AUniter\n\nThe `auniter.sh` script used to be part of this project, but now lives in\nits own AUniter (https://github.com/bxparks/AUniter) project. The `auniter.sh`\nscript is a wrapper around:\n* [Arduino IDE in command line mode](https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc), and\n* [Arduino CLI tool](https://github.com/arduino/arduino-cli)\n\nUsing `auniter.sh`, you can compile, upload and validate multiple AUnit tests on\nmultiple Arduino boards using a single command.\n\nThe script can monitor the serial port and determine if the unit test passed or\nfailed, and it will print out a summary of all unit tests at the end. Full\ndetails are given in the AUniter project, but here are some quick examples\ncopied from the `AUniter/README.md` file:\n\n* `$ auniter envs`\n    * list the environments configured in the `auniter.ini` config file\n* `$ auniter ports`\n    * list the available serial ports and devices\n* `$ auniter verify nano Blink.ino`\n    * verify (compile) `Blink.ino` using the `env:nano` environment\n* `$ auniter upload nano:/dev/ttyUSB0 Blink.ino`\n    * upload `Blink.ino` to the `env:nano` target environment connected to\n    `/dev/ttyUSB0`\n* `$ auniter test nano:USB0 BlinkTest.ino`\n    * compile and upload `BlinkTest.ino` using the `env:nano` environment,\n      upload it to the board at `/dev/ttyUSB0`, then validate the output of the\n      [AUnit](https://github.com/bxparks/AUnit) unit test\n* `$ auniter test nano:USB0 BlinkTest/ ClockTest/`\n    * upload and verify the 2 unit tests (`BlinkTest/BlinkTest.ino`,\n      `ClockTest/ClockTest.ino`) on the target environment (`env:nano`)\n* `$ auniter upmon nano:USB0 Blink.ino`\n    * upload the `Blink.ino` sketch and monitor the serial port using a\n      user-configurable terminal program (e.g. `picocom`) on `/dev/ttyUSB0`\n\n\u003ca name=\"EpoxyDuino\"\u003e\u003c/a\u003e\n### EpoxyDuino\n\nInstead of running the unit tests on the actual microcontrollers themselves, you\ncan compile and execute AUnit unit tests natively on Linux or MacOS machines\nusing the EpoxyDuino (https://github.com/bxparks/EpoxyDuino) project.\nEpoxyDuino provides a minimal Arduino programming environment that is usually\nsufficient to compile and run AUnit test units on the Unix host machine. It\nrelies on the native C++ compiler, GNU Make, and `Makefile` files for each\n`*.ino` unit test like this:\n\n```\nAPP_NAME := SampleTest\nARDUINO_LIBS := AUnit\ninclude ../../../EpoxyDuino/EpoxyDuino.mk\n```\n\nThe unit test is compiled into a binary (`SampleTest.out`) using the `make\ncommand, and the binary can be executed like this:\n```\n$ make\n$ ./SampleTest.out\n```\n\nHere are a few tips when writing unit tests to run under EpoxyDuino:\n\n**Delay(1000)**\n\nFor real Arduino boards, you get more reliable unit tests if you add a\n`delay(1000)` at the start of the program. For EpoxyDuino, this is not\nnecessary, so I recommend calling this only on real Arduino boards, like this:\n```C++\nvoid setup() {\n#if ! defined(EPOXY_DUINO)\n  delay(1000); // Wait for stability on some boards, otherwise garage on Serial\n#endif\n\n  Serial.begin(115200);\n  while (! Serial); // Wait until Serial is ready - Leonardo/Micro\n\n#if defined(EPOXY_DUINO)\n  Serial.setLineModeUnix(); // use Unix line terminator instead of DOS\n#endif\n  ...\n}\n\nvoid loop() {\n  aunit::TestRunner::run();\n}\n```\n\n**Exit() Status Code**\n\nOn real Arduino boards, the unit test (or any program for that matter) never\nterminates. The `loop()` function executes forever. On Linux or MacOS using\nEpoxyDuino, the test program will terminate at the end through the\n`exit()` function. If the tests are successful (i.e. passing or skipped), it\nwill call `exit(0)`. If there are any failing tests (i.e. failed or timed out),\nit will call `exit(1)`.\n\n\u003ca name=\"CommandLineFlagsAndArguments\"\u003e\u003c/a\u003e\n### Command Line Flags and Arguments\n\n(Added in v1.6)\n\nThe standard Arduino environment does not provide command line arguments, since\na microcontroller does not normally provide a command line environment. However,\nif the AUnit test program is compiled under EpoxyDuino, the standard Unix\ncommand line parameters (`argc` and `argv`)  become available through the\n`extern int epoxy_argc` and `extern const char* const* epoxy_argv` global\nvariables. These allow the `TestRunner` class to provide command line flags and\narguments as follows:\n\n```bash\n$ ./test.out --help\nUsage: ./test.out [--help] [--include pattern,...] [--exclude pattern,...]\n   [--includesub substring,...] [--excludesub substring,...]\n   [--] [substring ...]\n```\n\nExample, the following runs all tests with substring \"net\" or \"led\" in its\nname, and skips all others:\n\n```bash\n$ ./test.out net led\n```\n\nFlags:\n\n* `--include pattern,...`\n    * Comma-separated list of patterns to pass to the\n      `TestRunner::include(pattern)` method\n* `--exclude pattern,...`\n    * Comma-separated list of patterns to pass to the\n      `TestRunner::exclude(pattern)` method\n* `--includesub substring,...`\n    * Comma-separated list of substrings to pass to the\n      `TestRunner::includesub(substring)` method\n* `--excludesub substring,...`\n    * Comma-separated list of substrings to pass to the\n      `TestRunner::excludesub(substring)` method\n\nArguments:\n\n* Any **Space**-separated list of words after the optional flags are passed to\n  the `TestRunner::includesub(substring)` method.\n\nThe command line flags and arguments are processed *after* any hardcoded calls\nto `TestRunner::include()` and `TestRunner::exclude()` methods in the global\n`setup()` method.\n\nThe flags and command line arguments are processed *in order* of appearance\non the command line.\n\nSimilar to the hardcoded calls to `TestRunner::include()` and\n`TestRunner::exclude()`, if the first command line flag is an `--include` or\n`--includesub`, then all tests are *excluded* by default initially. Otherwise,\nthe first include flag would have no effect.\n\n\u003ca name=\"ContinuousIntegration\"\u003e\u003c/a\u003e\n## Continuous Integration\n\nThere are several ways to incorporate AUnit into a continuous integration\nsystem. At the infrastructure level, you can use either a system like\n[Jenkins](https://jenkins.io) running on a local machine, or use a cloud-based\ncontinuous integration system like [GitHub\nActions](https://github.com/features/actions). For each of those\ninfrastructures, you can choose to use the Arduino IDE or CLI build tools, or\nyou can use EpoxyDuino to compile and run against a Linux or MacOS\nenvironment.\n\nThe option matrix looks like this:\n\n```\n+----------------+-------------------------+------------------------+\n|\\ CI environment|                         |                        |\n| \\____________  | Local (e.g. Jenkins)    | Cloud (e.g. GitHub)    |\n|              \\ |                         |                        |\n| Build tool    \\|                         |                        |\n+----------------+-------------------------+------------------------+\n|                | * can execute tests     | * verify compile-only  |\n|                |   on microcontroller    | * cannot actually run  |\n| Arduino        | * complex setup and     |   tests on             |\n| IDE/CLI        | * maintenance           |   microcontroller      |\n|                | * can be slow           | * complex installation |\n|                | * (not recommended)     |   and setup            |\n|                |                         | * (unverified)         |\n+----------------+-------------------------+------------------------+\n|                | * verify execution on   | * verify execution on  |\n|                |   Unix environment      |   Unix environment     |\n| EpoxyDuino     | * faster than IDE/CLI   | * simple setup and     |\n|                | * complex setup and     |   maintenance          |\n|                |   and maintenance       | * very fast            |\n|                | * (unnecessary)         | * (recommended)        |\n+----------------+-------------------------+------------------------+\n```\n\n\u003ca name=\"IdePlusCloud\"\u003e\u003c/a\u003e\n### Arduino IDE/CLI + Cloud\n\nThe big advantage of using the Arduino IDE/CLI to run the AUnit unit tests is\nthat you can compile them using the precise compiler and tool chain that will be\nused against the specific microcontroller that you are interested in verifying.\nThere can be subtle compiler differences (e.g. size of `int`) or differences in\nhow the Arduino programming environment was implemented (e.g. availability of\nthe `FPSTR()` macro). If you use a cloud-based CI infrastructure, then you must\ninstall the complete Arduino IDE/CLI environment into your cloud test runner.\nAlthough I think it's theoretically possible, I have never actually verified\nthat this can be done.\n\n\u003ca name=\"IdePlusJenkins\"\u003e\u003c/a\u003e\n### Arduino IDE/CLI + Jenkins\n\nThis setup is described in [Continuous Integration with\nJenkins](https://github.com/bxparks/AUniter/tree/develop/jenkins), and it worked\nreasonably well for small number of unit tests. The problem is that the Arduino\nIDE is far too slow when the number of unit tests become non-trivial. And it\nalso takes too much effort to maintain the local Jenkins infrastructure. The\nJenkins environment seems to be brittle due to its complexity of all of its\nmoving parts. This is the only environment where you can connect a real Arduino\nmicrocontroller to the local machine and have the unit tests run on the actual\nmicrocontroller. Perhaps for certain situations, running the unit tests on\nactual hardware is a requirement. But for most people, I no longer recommend\nthis environment.\n\n\u003ca name=\"EpoxyDuinoPlusJenkins\"\u003e\u003c/a\u003e\n### EpoxyDuino + Jenkins\n\nOnce the Jenkins environment is up and running, I have verified that it is easy\nto run the unit tests using EpoxyDuino, since it needs just a C++ compiler\nand GNU Make. Things will compile and run a lot faster than using the Arduino\nIDE/CLI. However, this combination suffers from the same problem of maintaining\nthe Jenkins environment. If the unit tests are running in an Unix environment\nanyway, it seems far easier to just run them in the cloud. So I don't recommend\nusing this setup. Just use a cloud CI provider as described below.\n\n\u003ca name=\"EpoxyDuinoPlusCloud\"\u003e\u003c/a\u003e\n### EpoxyDuino + Cloud (Recommended)\n\nA cloud-based continuous integration service like [GitHub\nActions](https://github.com/features/actions) is easy to setup for\nEpoxyDuino. Often the C++ compiler and GNU `make` tools are already installed\nin the Docker container used by the CI system. The only additional setup is\nto install EpoxyDuino, AUnit and other dependent Arduino libraries.\n\nHere are some example YAML files for GitHub Actions:\n* https://github.com/bxparks/AceTime/tree/develop/.github/workflows\n* https://github.com/bxparks/AceButton/tree/develop/.github/workflows\n* https://github.com/bxparks/AceRoutine/tree/develop/.github/workflows\n* https://github.com/bxparks/AceCRC/tree/develop/.github/workflows\n\nIn the various `aunit_tests.yml` files, the `Setup` step installs the various\ndependent libraries using the `git clone` command, for example:\n```\ngit clone https://github.com/bxparks/EpoxyDuino\ngit clone https://github.com/bxparks/AUnit\n```\n\nThese commands install the default branch for those repositories, which for most\nof my libraries will be the `develop` branch. This makes sense for me because I\nwant the unit tests to run against the latest commits. However, for many others,\nit is probably better to use the `master` branch because it contains the stable\nreleases:\n```\ngit clone --branch master https://github.com/bxparks/EpoxyDuino\ngit clone --branch master https://github.com/bxparks/AUnit\n```\n\nUsing EpoxyDuino with a cloud CI provider (like GitHub Actions) is my\nrecommended configuration for running AUnit tests because it is easy to setup\nand maintain and the tests run fast.\n\n\u003ca name=\"Tips\"\u003e\u003c/a\u003e\n## Tips\n\nCollection of useful tidbits.\n\n\u003ca name=\"DebuggingFixtures\"\u003e\u003c/a\u003e\n### Debugging Assertions in Fixtures\n\nWhen using test fixtures with the `testF()` and `testingF()` macros, it's often\nuseful to create helper assertions, such as the `assertCustomStuff()` below.\nDebugging such assertion statements can be tricky. I've found that turning on\nmessages for successful assertions (with a\n`enableVerbosity(Verbosity::kAssertionPassed)`) statement can be very helpful:\n\n```C++\nclass CustomTestOnce: public TestOnce {\n  protected:\n    // optional\n    void setup() override {\n      TestOnce::setup();\n      ...setup code...\n    }\n\n    // optional\n    void teardown() override {\n      ...teardown code...\n      TestOnce::teardown();\n    }\n\n    void assertCustomStuff() {\n      assertEqual(...);\n      ...\n      for (...) {\n        ...\n        assertEqual(...);\n        ...\n      }\n    }\n\n    int sharedValue;\n};\n\ntestF(CustomTestOnce, calculate) {\n  enableVerbosity(Verbosity::kAssertionPassed);\n\n  ...test code here...\n  assertCustomStuff();\n}\n```\n\n\u003ca name=\"ClassHierarchy\"\u003e\u003c/a\u003e\n### Class Hierarchy\n\nTo support test fixtures in a more natural way, the class hierarchy\nin AUnit is slightly different than ArduinoUnit. In ArduinoUnit we have a\ntwo level hierarchy:\n```\n  Test ::loop()\n    ^\n    |\n TestOnce ::once()\n ```\n\nIn AUnit, the functionality that supports the `testing()` macro has been\nmigrated to a separate class called `TestAgain`, like this:\n\n```\n       Test ::loop()\n         ^\n         |\n      Assertion\n         ^\n         |\n     MetaAssertion\n        ^  ^\n       /    \\\n      /      \\\nTestAgain  TestOnce\n::again()  ::once()\n```\n\nNormally, deep inheritance hierarchies like this should be avoided. However,\nplacing the `Assertion` and `MetaAssertion` classes inside the `Test` hierarchy\nallowed those assertion statements to have access to the internal states of the\n`Test` instance. This made certain features (like the early return upon delayed\nfailure) slightly easier to implement. For the most part, the end-users can\nignore the existence of the `Assertion` and `MetaAssertion` classes and think of\nthis as a simple 2-level inheritance tree.\n\n\u003ca name=\"PrivateHelperMethods\"\u003e\u003c/a\u003e\n### Testing Private Helper Methods\n\nThere is a school of thought which says that unit tests should test only the\npublically exposed methods of a class or library. I agree mostly with that\nsentiment, but not rigidly. I think it is sometimes useful to write unit tests\nfor `protected` or `private` methods. For example, when creating a chain of\nsmall helper methods, which build up to larger publically exposed methods, it is\nextremely useful to write unit tests for the helper methods in isolation.\n\nNormally those helper methods would be `private` because they are used\nonly within that class, and we don't want to expose them to the public API. One\noption is to make them `public` but add a comment in the function to say that it\nis exposed only for testing purposes. This does not seem satisfactory because\nusers will tend to ignore such comments if the helper functions are useful.\n\nI think a better way is to keep the helper functions `private` but make\nthe unit tests a `friend class` of the target class. The syntax for doing this\ncan be tricky, it took me a number of attempts to get this right, especially if\nwhen using namespaces for the target class:\n\n```C++\n//------------------- Target.h -------------\n\n// Auto-generated test class names.\nclass Test_helper;\nclass TargetSuite_helper;\nclass TargetTest_helper;\n\nnamespace mylib {\n\nclass Target {\n  public:\n    void publicMethod() {\n      ...\n      int a = helper();\n      ...\n    }\n\n  private:\n    // Must have the global scope operator '::'\n    friend class ::Test_helper;\n    friend class ::TargetSuite_helper;\n    friend class ::TargetTest_helper;\n\n    static int helper() {...}\n};\n\n}\n\n//------------------- TargetTest.ino -------------\n\n#include \u003cAUnit.h\u003e\n#include \"Target.h\"\n\nusing namespace aunit;\nusing namespace mylib;\n\ntest(helper) {\n  assertEqual(1, Target::helper(...));\n}\n\ntest(TargetSuite, helper) {\n  assertEqual(1, Target::helper(...));\n}\n\nclass TargetTest: public TestOnce {\n  ...\n};\n\ntestF(TargetTest, helper) {\n  assertEqual(1, Target::helper(...));\n}\n\n```\n\nThe tricky part is that `Target.h` must have forward declarations of the various\nauto-generated AUnit test classes. And within the `Target` class itself, the\n`friend` declarations need to have a global scope `::` specifier before the name\nof the test class.\n\n\u003ca name=\"Benchmarks\"\u003e\u003c/a\u003e\n## Benchmarks\n\n\u003ca name=\"MemoryBenchmark\"\u003e\u003c/a\u003e\n### MemoryBenchmark\n\nThe [MemoryBenchmark](examples/MemoryBenchmark/) directory collects the flash\nand static RAM usage of the AUnit library on various microcontroller boards, and\nrenders the results as tables embedded in the README.md file. Here are 2\nhighlights:\n\n**Arduino Nano (8-bit)**\n\n```\n+---------------------------------------------------------------------+\n| Functionality                          |  flash/  ram |       delta |\n|----------------------------------------+--------------+-------------|\n| Baseline                               |   1586/  185 |     0/    0 |\n|----------------------------------------+--------------+-------------|\n| AUnit Single Test                      |   4456/  366 |  2870/  181 |\n| AUnit Single Test Verbose              |   4500/  366 |  2914/  181 |\n+---------------------------------------------------------------------+\n```\n\n**ESP8266 (32-bit)**\n\n```\n+---------------------------------------------------------------------+\n| Functionality                          |  flash/  ram |       delta |\n|----------------------------------------+--------------+-------------|\n| Baseline                               | 264949/27984 |     0/    0 |\n|----------------------------------------+--------------+-------------|\n| AUnit Single Test                      | 268021/28148 |  3072/  164 |\n| AUnit Single Test Verbose              | 268081/28148 |  3132/  164 |\n+---------------------------------------------------------------------+\n```\n\n\u003ca name=\"CompareArduinoUnit\"\u003e\u003c/a\u003e\n### Compared to ArduinoUnit 2.2\n\nAUnit consumes as much as 65% less flash memory than ArduinoUnit 2.2 on an AVR\nplatform (e.g. Arduino UNO, Nano), and 30% less flash on the Teensy-ARM platform\n(e.g. Teensy LC ). (ArduinoUnit 2.3 reduces the flash memory by 30% or so, which\nmeans that AUnit can still consume significantly less flash memory.)\n\nHere are the resource consumption (flash and static) numbers\nfrom\n[AceButtonTest](https://github.com/bxparks/AceButton/tree/develop/tests/AceButtonTest)\ncontaining 26 test cases using 331 `assertXxx()`\nstatements, compiled using AUnit and ArduinoUnit 2.2 on 5 different\nmicrocontrollers:\n```\n---------------------------+---------+-------------+-------------+\nPlatform (resource)        |     Max | ArduinoUnit |       AUnit |\n---------------------------+---------+-------------+-------------|\nArduino Nano (flash)       |   30720 |       54038 |       18928 |\nArduino Nano (static)      |    2048 |        1061 |         917 |\n---------------------------+---------+-------------+-------------|\nTeensy LC (flash)          |   63488 |       36196 |       26496 |\nTeensy LC (static)         |    8192 |        2980 |        2780 |\n---------------------------+---------+-------------+-------------|\nTeensy 3.2 (flash)         |  262144 |       51236 |       37920 |\nTeensy 3.2 (static)        |   65536 |        5328 |        5236 |\n---------------------------+---------+-------------+-------------|\nESP8266 - ESP-12E (flash)  | 1044464 |    does not |      268236 |\nESP8266 - ESP-12E (static) |   81920 |     compile |       33128 |\n---------------------------+---------+-------------+-------------|\nESP8266 - ESP-01 (flash)   |  499696 |    does not |      268236 |\nESP8266 - ESP-01 (static)  |   47356 |     compile |       33128 |\n---------------------------+---------+-------------+-------------+\n```\n\nNot all unit test sketches will experience a savings of 65% of flash memory with\nAUnit, but a savings of 30-50% seems to be common.\n\n\u003ca name=\"SystemRequirements\"\u003e\u003c/a\u003e\n## System Requirements\n\n\u003ca name=\"Hardware\"\u003e\u003c/a\u003e\n### Hardware\n\n**Tier 1: Fully supported**\n\nThese boards are tested on each release:\n\n* Arduino Nano clone (16 MHz ATmega328P)\n* SparkFun Pro Micro clone (16 MHz ATmega32U4)\n* Seeeduino XIAO M0 (SAMD21, 48 MHz ARM Cortex-M0+)\n* STM32 Blue Pill (STM32F103C8, 72 MHz ARM Cortex-M3)\n* Adafruit ItsyBitsy M4 (SAMD51, 120 MHz ARM Cortext-M4)\n* NodeMCU 1.0 (ESP-12E module, 80 MHz ESP8266)\n* WeMos D1 Mini (ESP-12E module, 80 MHz ESP8266)\n* ESP32 dev board (ESP-WROOM-32 module, 240 MHz dual core Tensilica LX6)\n\n**Tier 2: Should work**\n\nThese boards should work but I don't test them as often:\n\n* Arduino Pro Mini (16 MHz ATmega328P)\n* Mini Mega 2560 (Arduino Mega 2560 compatible, 16 MHz ATmega2560)\n* Teensy LC (48 MHz ARM Cortex-M0+)\n* Teensy 3.2 (96 MHz ARM Cortex-M4)\n\n**Tier 3: May work, but not supported**\n\n* Other 3rd party SAMD21 and SAMD51 boards *may* work if their board software\n  uses the traditional Arduino API, instead of the\n  [ArduinoCore-API](https://github.com/arduino/ArduinoCore-api)\n\n**Tier Blacklisted**\n\nThe following boards are *not* supported and are explicitly blacklisted to allow\nthe compiler to print useful error messages instead of hundreds of lines of\ncompiler errors:\n\n* Any platform using the\n    [ArduinoCore-API](https://github.com/arduino/ArduinoCore-api), such as:\n    * Arduino Nano Every\n    * Arduino Nano 33 IoT\n    * Arduino MKRZero\n    * Arduino UNO R4\n    * Raspberry Pi Pico (RP2040)\n\n\u003ca name=\"Toolchains\"\u003e\u003c/a\u003e\n### Toolchains\n\nThis library was validated using:\n\n* [Arduino IDE 1.8.19](https://www.arduino.cc/en/Main/Software)\n* [Arduino CLI 0.33.0](https://arduino.github.io/arduino-cli)\n* [Arduino AVR Boards 1.8.6](https://github.com/arduino/ArduinoCore-avr)\n* [Arduino SAMD Boards 1.8.9](https://github.com/arduino/ArduinoCore-samd)\n  (versions \u003e= 1.8.10 not supported)\n* [SparkFun AVR Boards 1.1.13](https://github.com/sparkfun/Arduino_Boards)\n* [SparkFun SAMD Boards 1.8.6](https://github.com/sparkfun/Arduino_Boards)\n* [STM32duino 2.5.0](https://github.com/stm32duino/Arduino_Core_STM32)\n* [ESP8266 Arduino 3.0.2](https://github.com/esp8266/Arduino)\n* [ESP32 Arduino 2.0.9](https://github.com/espressif/arduino-esp32)\n* [Teensyduino 1.57](https://www.pjrc.com/teensy/td_download.html)\n\nThis library is *not* compatible with any platform using the\n[ArduinoCore-API](https://github.com/arduino/ArduinoCore-api), such as:\n\n* [ArduinoCore SAMD \u003e=1.8.10](https://github.com/arduino/ArduinoCore-samd)\n* [ArduinoCore megaAVR](https://github.com/arduino/ArduinoCore-megaavr/)\n* [ArduinoCore renesas](https://github.com/arduino/ArduinoCore-renesas)\n* [Arduino-Pico](https://github.com/earlephilhower/arduino-pico)\n* [MegaCoreX](https://github.com/MCUdude/MegaCoreX)\n\n(See [Issue #56](https://github.com/bxparks/AUnit/issues/56)\nand [Issue #66](https://github.com/bxparks/AUnit/issues/66)).\n\nIt should work with [PlatformIO](https://platformio.org/) but I have\nnot tested it extensively.\n\nThe library works under Linux or MacOS (using both g++ and clang++ compilers)\nusing the EpoxyDuino (https://github.com/bxparks/EpoxyDuino) emulation layer.\n\n\u003ca name=\"OperatingSystem\"\u003e\u003c/a\u003e\n### Operating System\n\nI use Ubuntu 20.04 for the vast majority of my development. I expect that the\nlibrary will work fine under MacOS and Windows, but I have not tested them.\n\n\u003ca name=\"License\"\u003e\u003c/a\u003e\n## License\n\n[MIT License](https://opensource.org/licenses/MIT)\n\n\u003ca name=\"FeedbackAndSupport\"\u003e\u003c/a\u003e\n## Feedback and Support\n\nIf you have any questions, comments, or feature requests for this library,\nplease use the [GitHub\nDiscussions](https://github.com/bxparks/AUnit/discussions) for this project. If\nyou have bug reports, please file a ticket in [GitHub\nIssues](https://github.com/bxparks/AUnit/issues). Feature requests should go\ninto Discussions first because they often have alternative solutions which are\nuseful to remain visible, instead of disappearing from the default view of the\nIssue tracker after the ticket is closed.\n\nPlease refrain from emailing me directly unless the content is sensitive. The\nproblem with email is that I cannot reference the email conversation when other\npeople ask similar questions later.\n\n\u003ca name=\"Authors\"\u003e\u003c/a\u003e\n## Authors\n\n* Created by Brian T. Park (brian@xparks.net).\n* The Google Test adapter (`gtest.h`) was created by Chris Johnson\n  (chrisjohnsonmail@gmail.com).\n* @brewmanz increased the maximum allowed value of `TestRunner::setTimeout()`\n  from 255 seconds to 65535 seconds (18.2 hours). (See [Issue\n  #57](https://github.com/bxparks/AUnit/issues/57)).\n* The design and syntax of many macros (e.g. `test()`, `assertXxx()`) were\n  borrowed from the [ArduinoUnit](https://github.com/mmurdoch/arduinounit)\n  project to allow AUnit to be almost a drop-in replacement. Many thanks to\n  the ArduinoUnit team for creating such an easy-to-use API.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbxparks%2FAUnit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbxparks%2FAUnit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbxparks%2FAUnit/lists"}