blob: c539420f397e92bb0fd22c303036a9759e7df200 [file] [log] [blame] [view]
# Unit testing
## Why?
- MUCH faster than integration tests.
- Runs as part of build process.
- Allows testing specific error conditions that are difficult to trigger under
normal operating conditions.
- e.g. out of memory errors etc.
- Allows testing different device compositions without defining multiple
example applications.
- e.g. feature combinations not in example apps.
## Unit testing in the SDK - nlUnitTest
The following example gives a small demonstration of how to use nlUnitTest to
write a unit test
```
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestRegistration.h>
#include <nlunit-test.h>
class YourTestContext : public Test::AppContext {
...
};
static void TestName(nlTestSuite * apSuite, void * apContext) {
// If you register the test suite with a context, cast
// apContext as appropriate
YourTestContext * ctx = static_cast<YourTestContext *>(aContext);
// Do some test things here, then check the results using NL_TEST_ASSERT
NL_TEST_ASSERT(apSuite, <boolean condition>)
}
static const nlTest sTests[] =
{
NL_TEST_DEF("TestName", TestName), // Can have multiple of these
NL_TEST_SENTINEL() // If you forget this, you’re going to have a bad time
};
nlTestSuite sSuite =
{
"TheNameOfYourTestSuite", // Test name
&sTests[0], // The list of tests to run
TestContext::Initialize, // Runs before all the tests (can be nullptr)
TestContext::Finalize // Runs after all the tests (can be nullptr)
};
int YourTestSuiteName()
{
return chip::ExecuteTestsWithContext<YourTestContext>(&sSuite); // or “without”
}
CHIP_REGISTER_TEST_SUITE(YourTestSuiteName)
```
Each test gets an nlTestSuite object (apSuite) that is passed into the test
assertions, and a void\* context (apContext) that is yours to do with as you
require.
The apContext should be derived from
[Test::AppContext](https://github.com/project-chip/connectedhomeip/blob/master/src/app/tests/AppTestContext.h)
See
[TestSpan.cpp](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/tests/TestSpan.cpp)
for a great example of a good unit test.
## nlUnitTest - Compiling and running
- Add to src/some_directory/tests/BUILD.gn
- chip_test_suite_using_nltest("tests")
- See for example
[src/lib/support/tests/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/tests/BUILD.gn)
- [./gn_build.sh](https://github.com/project-chip/connectedhomeip/blob/master/gn_build.sh)
will build and run all tests
- CI runs this, so any unit tests that get added will automatically be
added to the CI
- Test binaries are compiled into:
- out/debug/<host_compiler>/tests
- e.g. out/debug/linux_x64_clang/tests
- Tests are run when ./gn_build.sh runs, but you can run them individually in
a debugger from their location.
## Debugging unit tests
- After running ./gn_build.sh, test binaries are compiled into
- out/debug/<host_compiler>/tests
- e.g. out/debug/linux_x64_clang/tests
- Individual binaries, can be run through regular tools:
- gdb
- valgrind
- Your favorite tool that you tell everyone about.
## Utilities
We have a small number of unit testing utilities that should be used in unit
tests.
Consider adding more utilities for general use if you require them for your
tests.
### Mock clock
The mock clock is located in
[src/system/SystemClock.h](https://github.com/project-chip/connectedhomeip/blob/master/src/system/SystemClock.h)
as `System::Clock::Internal::MockClock`.
To use the mock clock, use the `chip::System::SystemClock()` function as normal.
In the test, instantiate a MockClock and use the `SetSystemClockForTesting` to
inject the clock. The Set and Advance functions in the MockClock can then be
used to set exact times for testing. This allows testing specific edge
conditions in tests, helps reduce test flakiness due to race conditions, and
reduces the time required for testing as tests no long require real-time waits.
### TestPersistentStorageDelegate
The TestPersistentStorageDelegate is an in-memory version of storage that easily
allows removal of keys, presence checks, etc. It is available at
[src/lib/support/TestPersistentStorageDelegate.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/TestPersistentStorageDelegate.h)