From a4308426da1d5dba4115ccf5a48a7d7dde89b521 Mon Sep 17 00:00:00 2001 From: Lari-Matias Orjala Date: Fri, 12 Apr 2019 15:13:08 +0300 Subject: [PATCH] add a code independent unit test writing example --- UNITTESTS/README.md | 194 ++++++++++++++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 60 deletions(-) diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md index e250a1b8da..d7ff57facc 100644 --- a/UNITTESTS/README.md +++ b/UNITTESTS/README.md @@ -104,75 +104,148 @@ You can also set custom compiler flags and other configurations supported by CMa #### Example -With the following steps, you can write a simple unit test. In this example, `rtos/Semaphore.cpp` is a class under test. +With the following steps, you can write a simple unit test. In this example we will create dummy classes to be tested. Then we will create and configure unit tests for a class. Finally we will stub all external dependencies. -1. Create a directory for unit test files in `UNITTESTS/rtos/Semaphore`. -1. Create a test configuration file `UNITTESTS/rtos/Semaphore/unittest.cmake` with the following content: +1. Create the following dummy classes in `mbed-os/example`: - ``` - set(unittest-sources - ../rtos/Semaphore.cpp - ) - - set(unittest-test-sources - stubs/mbed_assert_stub.c - stubs/Kernel_stub.cpp - rtos/Semaphore/test_Semaphore.cpp - ) - ``` -1. Stub all external dependencies. Create stubs `UNITTESTS/stubs/mbed_assert_stub.c` and `UNITTESTS/stubs/Kernel_stub.cpp` if they don't already exist. -1. Update header stubs with any missing type or function declarations. -1. Create a test source file `UNITTESTS/rtos/Semaphore/test_Semaphore.cpp` with the following content: + **MyClass.h** -``` -#include "gtest/gtest.h" -#include "rtos/Semaphore.h" + ``` + #ifndef MYCLASS_H_ + #define MYCLASS_H_ -static osStatus_t retval = osOK; -static uint32_t count = 0; + namespace example { -// Test stubs -osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) -{ - return retval; -} -osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) -{ - return retval; -} -osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) -{ - return retval; -} -uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) -{ - return count; -} -osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) -{ - return (void *)&count; // Just a dymmy reference -} + class MyClass { + public: + int myFunction(); + }; -class TestSemaphore : public testing::Test { -protected: - rtos::Semaphore *sem; - - virtual void SetUp() - { - sem = new rtos::Semaphore(); } - virtual void TearDown() - { - delete sem; - } -}; + #endif + ``` -TEST_F(TestSemaphore, constructor) -{ - EXPECT_TRUE(sem); -} -``` + **MyClass.cpp** + + ``` + #include "MyClass.h" + #include "OtherClass.h" + + namespace example { + + int MyClass::myFunction() { + OtherClass o = OtherClass(); + return o.otherFunction(); + } + + } + ``` + + **OtherClass.h** + + ``` + #ifndef OTHERCLASS_H_ + #define OTHERCLASS_H_ + + namespace example { + + class OtherClass { + public: + int otherFunction(); + }; + + } + + #endif + ``` + + **OtherClass.cpp** + + ``` + #include "OtherClass.h" + + namespace example { + + int OtherClass::otherFunction() { + return 1; + } + + } + ``` + +1. Create a directory for MyClass unit tests in `UNITTESTS/example/MyClass`. +1. Create a configuration file and a source file for MyClass unit tests in `UNITTESTS/example/MyClass`: + + **unittest.cmake** + + ``` + # Add here additional test specific include paths + set(unittest-includes ${unittest-includes} + ../example + ) + + # Add here classes under test + set(unittest-sources + ../example/MyClass.cpp + ) + + # Add here test classes and stubs + set(unittest-test-sources + example/MyClass/test_MyClass.cpp + stubs/OtherClass_stub.cpp + ) + ``` + + **test_MyClass.cpp** + + ``` + #include "gtest/gtest.h" + #include "example/MyClass.h" + + class TestMyClass : public testing::Test { + protected: + example::MyClass *obj; + + virtual void SetUp() + { + obj = new example::MyClass(); + } + + virtual void TearDown() + { + delete obj; + } + }; + + TEST_F(TestMyClass, constructor) + { + EXPECT_TRUE(obj); + } + + TEST_F(TestMyClass, myfunction) + { + EXPECT_EQ(obj->myFunction(), 0); + } + ``` + +1. Stub all external dependencies. Create the following stub in `UNITTESTS/stubs`: + + **OtherClass_stub.cpp** + + ``` + #include "example/OtherClass.h" + + namespace example { + + int OtherClass::otherFunction() { + return 0; + } + + } + ``` + +This example does not use any Mbed OS code, but if your unit tests do then remember to update header stubs in `UNITTESTS/target_h` and source stubs in `UNITTESTS/stubs` with any missing type or function declarations. ### Building and running unit tests @@ -187,6 +260,7 @@ Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake an * Add `-DCMAKE_MAKE_PROGRAM=`, `-DCMAKE_CXX_COMPILER=` and `-DCMAKE_C_COMPILER=` to use a specific Make program and compilers. * Add `-DCMAKE_BUILD_TYPE=Debug` for a debug build. * Add `-DCOVERAGE=True` to add coverage compiler flags. + * Add `-Dgtest_disable_pthreads=ON` to run in a single thread. * See the [CMake manual](https://cmake.org/cmake/help/v3.0/manual/cmake.1.html) for more information. 1. Run a Make program to build tests.