Unit testing¶
This document is a user guide for adding unit tests to your C and C++ functions.
Using the gtest EPICS module¶
gtest is an EPICS module that enables you to use GoogleTest as a framework for unit testing and mocking.
The GoogleTest framework is a well-known framework for writing unit tests in C++. You can test C functions using GoogleTest, but the tests definitions must be in C++.
Functions to test are in a library¶
Note
Read this section if your top is an IOC.
If the top you want to test already is a library / a support top, you can skip this section.
To test your C/C++ functions, it’s best to have a library containing all the functions you want to test. This makes it easier to have your functions both in your IOC and in your tests.
For example,
if you have a myFunctions.cpp
,
don’t add it to the sources of your IOC.
Instead,
create a library,
for example myLibrary
,
and add your myFunctions.cpp
to the sources of this library.
Then,
link your IOC to myLibrary
.
If you don’t have a library,
change your src/Makefile
so that it has these lines:
LIBRARY += myLibrary
myLibrary_SRCS += myFunctions
# Libraries needed by 'myLibrary'
myLibrary_LIBS += Com
Then make sure your IOC links with myLibrary
:
# ...
#=============================
# Build the IOC application
PROD_IOC += myIoc
# ...
# Link myIoc with myLibrary
myIoc_LIBS += myLibrary_LIBS
Adding gtest to the top¶
Add gtest to the build environment:
# Add one of the supported modules here:
# ---
support.modules = with pkgs.epnix.support; [
# other support modules...
gtest
];
Writing tests¶
To write your unit tests, create a separate C++ file, and follow the GoogleTest documentation.
Here is an example of a test:
#include <gtest/gtest.h>
#include "myLibrary.hpp"
namespace {
class MyTest : public testing::Test {
protected:
MyTest() { /* Set-up work for each test */ }
~MyTest() { /* Clean up work for each test */ }
};
TEST_F(MyTest, myTest1)
{
// Test something
EXPECT_EQ(2 + 2, 4) << "2 * 2 must be equal to 4";
}
TEST_F(MyTest, myTest2)
{
EXPECT_EQ(6 * 7, 42) << "6 * 7 must be equal to 42";
}
} // namespace
Adding tests to the build¶
To add your tests to the build,
add these lines to your src/Makefile
:
GTESTPROD_HOST += myTest
myTest_SRCS += myTest.cpp
myTest_LIBS += myLibrary
GTESTS += myTest
Running the tests¶
To run the tests in your development shell, run:
make runtests
Running nix build
also runs tests by default.
To turn off tests inside the Nix build, add this to your configuration:
# ...
# checks.imports = [./checks/simple.nix];
buildConfig.attrs.doCheck = false;
Using the epics-base facility¶
epics-base provides the epicsUnitTest.h facility for declaring unit tests, which can be useful if you don’t want to import an external EPICS module.
epicsUnitTest.h is made in C, but tests can be written in either C or C++.
Pre-requisites¶
Examine gtest’s Functions to test are in a library.
Writing tests¶
To write epics-base unit tests, make sure:
You include
epicsUnitTest.h
You include
testMain.h
and use theMAIN
macro to define your main functionYour main function starts with a
testPlan(n)
, with n being the number of checks that your test will runYour main function returns
testDone()
You’re using
testOk
,testPass
, andtestFail
to add checks
Here is an example test:
#include <epicsUnitTest.h>
#include <testMain.h>
#include "myLibrary.hpp"
static void succeed()
{
testPass("No issues succeeding");
}
static void checkAddition(int x)
{
testOk(x + x == 2 * x, "x + x must be equal to 2 * x");
testOk(x + x + x == 3 * x, "x + x + x must be equal to 3 * x");
}
MAIN(myTest)
{
// 1 for succeed,
// 2 for checkAddition which is called 5 times
testPlan(1 + 5 * 2);
succeed();
for(int i = 0; i < 5; ++i) {
checkAddition(i);
}
return testDone();
}
Adding tests to the build¶
To add your tests to the build,
add these lines to your src/Makefile
:
TESTPROD_HOST += myTest
myTest_SRCS += myTest.cpp
myTest_LIBS += myLibrary
TESTSCRIPTS_HOST += myTest.t
Running the tests¶
Examine gtest’s Running the tests.