How to Unit-Test
wip
What is Fake Function Framework?
The Fake function framework (FFF) is a way to make mocks to test a newly written driver or application. It is meant to mock the supplementary drivers and/or applications using their header files. FFF was integrated into the Controls codebase to give an alternate option to test on software besides Renode. It was also meant to be tested in isolation from other drivers and applications by making them into mocks.
Why are we using FFF?
FFF was used because it is lightweight. Even though it does not have auto-generate mocks, a third party alternative generator was found. It is not integrated, but that is a pending issue.
Other testing frameworks were proposed, such as Google's cmockery and cmock. Google's cmokery is very similar to how FFF is structured. However, it has not been updated in a while and may have deprecated libraries being used. On the other hand, cmock has its advantages; it can auto generate the mocks. However, it uses ruby for the final scripts which make it a bit more convoluted.
Why are we unit testing?
Goals of unit testing (so we know what's important to test)
High-level logic: Does it ultimately do what we want it to?
Requirements and not implementation
You should be able to write it based on header files- don't look at the implementation because we don't want to write tests that are tailored to how the code is already written (undermines the value of testing)
Unit tests and code should be able to be written independently of each other
Logic of a single unit
Not dependencies, thread interactions, scheduling, OS things, etc
What are we unit testing?
The functions/logic in singular driver or application files Controls has written
(Not BSP, though)
When do we unit test?XXX
We can start writing unit tests as soon as we know our task. This can be at any point in time, including in parallel with or even before the development of the actual code.
The unit test won't actually be used until the code is completed
This is the first step in verifying a new piece of code. After the logic has been proven to work in isolation through unit testing, we can proceed to evaluating its behavior when interacting with other tasks through integration tests.
Who is unit testing?
You are, it seems! And this guide will help you do it.
Where are we unit testing?
Within the Controls system, we keep our test files in Controls/Tests/UnitTests/Tests. This is where you'll create your new unit test file. While you shouldn't need to mess with any of the other folders or files, a brief map of the Controls/Tests directory is provided below:
Tests/: Contains all of Controls' test stuff
Other non-unit testing test files
UnitTests/: Unit Test-related files
Makefile: A separate makefile invoked by make unittest
fff.h: Fake Function Framework (for generating mocks)
Tests/: Unit test files
Unity/: The Unity unit testing framework
Objects/: Where compiled unit test code objects go
Mocks/: Files with mocks to replace the real functions that aren't being tested
Mimics the real files with App, Driver, BSP directories
Inc folders: headers that include the normal header plus mock declarations
Src folders: c files that define mock functions
The Mock and Test names must copy the names of real files in order to compile the unit tests correctly. When compiling a unit test, we include mocks for all but the file being named by Test_XXX. Additionally, by using the same name, we allow our real files to use mock headers without changing the original code.
How to unit test
Introduce Unity
Unity Test Project is made to test code and seek validity. The project is a single C file and a pair of headers. Unity Test integrates with FFF in order to give a basic testing structure.
In order to use FFF, an application or driver source and header file need to be written.
Take a note of which files the file you wrote is touching.
After writing the files, the additional header files that are being used need to be mocked.
Start writing the unit test file
Step 0: Mock the supplementary files being used.
include unity.h
include the mock files
include DEFINE_FFF_GLOBALS
the Unity trio
setUp()
setUp() is a special function required by Unity that will run after each test.
tearDown()
Simliar to setUp(), tearDown() is a special function required by Unity that will run after each test.
test functions
One for every function we are trying to test. These are written by you.
main()
will call the tests
special cases - custom fakes, history length, function pointers