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