Skip to content

Commit 5e73a83

Browse files
authored
Merge pull request #10391 from lorjala/unittesting-example
Update the writing example in unit testing README
2 parents 93dc551 + 1d1e78c commit 5e73a83

File tree

1 file changed

+135
-61
lines changed

1 file changed

+135
-61
lines changed

UNITTESTS/README.md

Lines changed: 135 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -104,75 +104,148 @@ You can also set custom compiler flags and other configurations supported by CMa
104104

105105
#### Example
106106

107-
With the following steps, you can write a simple unit test. In this example, `rtos/Semaphore.cpp` is a class under test.
107+
With the following steps, you can write a simple unit test. This example creates dummy classes to be tested, creates and configures unit tests for a class and stubs all external dependencies.
108108

109-
1. Create a directory for unit test files in `UNITTESTS/rtos/Semaphore`.
110-
1. Create a test configuration file `UNITTESTS/rtos/Semaphore/unittest.cmake` with the following content:
109+
1. Create the following dummy classes in `mbed-os/example`:
111110

112-
```
113-
set(unittest-sources
114-
../rtos/Semaphore.cpp
115-
)
116-
117-
set(unittest-test-sources
118-
stubs/mbed_assert_stub.c
119-
stubs/Kernel_stub.cpp
120-
rtos/Semaphore/test_Semaphore.cpp
121-
)
122-
```
123-
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.
124-
1. Update header stubs with any missing type or function declarations.
125-
1. Create a test source file `UNITTESTS/rtos/Semaphore/test_Semaphore.cpp` with the following content:
126-
127-
```
128-
#include "gtest/gtest.h"
129-
#include "rtos/Semaphore.h"
130-
131-
static osStatus_t retval = osOK;
132-
static uint32_t count = 0;
133-
134-
// Test stubs
135-
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
136-
{
137-
return retval;
138-
}
139-
osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
140-
{
141-
return retval;
142-
}
143-
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
144-
{
145-
return retval;
146-
}
147-
uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
148-
{
149-
return count;
150-
}
151-
osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
152-
{
153-
return (void *)&count; // Just a dymmy reference
154-
}
155-
156-
class TestSemaphore : public testing::Test {
157-
protected:
158-
rtos::Semaphore *sem;
159-
160-
virtual void SetUp()
111+
**MyClass.h**
112+
113+
```
114+
#ifndef MYCLASS_H_
115+
#define MYCLASS_H_
116+
117+
namespace example {
118+
119+
class MyClass {
120+
public:
121+
int myFunction();
122+
};
123+
124+
}
125+
126+
#endif
127+
```
128+
129+
**MyClass.cpp**
130+
131+
```
132+
#include "MyClass.h"
133+
#include "OtherClass.h"
134+
135+
namespace example {
136+
137+
int MyClass::myFunction() {
138+
OtherClass o = OtherClass();
139+
return o.otherFunction();
140+
}
141+
142+
}
143+
```
144+
145+
**OtherClass.h**
146+
147+
```
148+
#ifndef OTHERCLASS_H_
149+
#define OTHERCLASS_H_
150+
151+
namespace example {
152+
153+
class OtherClass {
154+
public:
155+
int otherFunction();
156+
};
157+
158+
}
159+
160+
#endif
161+
```
162+
163+
**OtherClass.cpp**
164+
165+
```
166+
#include "OtherClass.h"
167+
168+
namespace example {
169+
170+
int OtherClass::otherFunction() {
171+
return 1;
172+
}
173+
174+
}
175+
```
176+
177+
1. Create a directory for MyClass unit tests in `UNITTESTS/example/MyClass`.
178+
1. Create a configuration file and a source file for MyClass unit tests in `UNITTESTS/example/MyClass`:
179+
180+
**unittest.cmake**
181+
182+
```
183+
# Add here additional test specific include paths
184+
set(unittest-includes ${unittest-includes}
185+
../example
186+
)
187+
188+
# Add here classes under test
189+
set(unittest-sources
190+
../example/MyClass.cpp
191+
)
192+
193+
# Add here test classes and stubs
194+
set(unittest-test-sources
195+
example/MyClass/test_MyClass.cpp
196+
stubs/OtherClass_stub.cpp
197+
)
198+
```
199+
200+
**test_MyClass.cpp**
201+
202+
```
203+
#include "gtest/gtest.h"
204+
#include "example/MyClass.h"
205+
206+
class TestMyClass : public testing::Test {
207+
protected:
208+
example::MyClass *obj;
209+
210+
virtual void SetUp()
211+
{
212+
obj = new example::MyClass();
213+
}
214+
215+
virtual void TearDown()
216+
{
217+
delete obj;
218+
}
219+
};
220+
221+
TEST_F(TestMyClass, constructor)
161222
{
162-
sem = new rtos::Semaphore();
223+
EXPECT_TRUE(obj);
163224
}
164225
165-
virtual void TearDown()
226+
TEST_F(TestMyClass, myfunction)
166227
{
167-
delete sem;
228+
EXPECT_EQ(obj->myFunction(), 0);
229+
}
230+
```
231+
232+
1. Stub all external dependencies. Create the following stub in `UNITTESTS/stubs`:
233+
234+
**OtherClass_stub.cpp**
235+
236+
```
237+
#include "example/OtherClass.h"
238+
239+
namespace example {
240+
241+
int OtherClass::otherFunction() {
242+
return 0;
243+
}
244+
168245
}
169-
};
246+
```
170247
171-
TEST_F(TestSemaphore, constructor)
172-
{
173-
EXPECT_TRUE(sem);
174-
}
175-
```
248+
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.
176249
177250
### Building and running unit tests
178251
@@ -187,6 +260,7 @@ Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake an
187260
* Add `-DCMAKE_MAKE_PROGRAM=<value>`, `-DCMAKE_CXX_COMPILER=<value>` and `-DCMAKE_C_COMPILER=<value>` to use a specific Make program and compilers.
188261
* Add `-DCMAKE_BUILD_TYPE=Debug` for a debug build.
189262
* Add `-DCOVERAGE=True` to add coverage compiler flags.
263+
* Add `-Dgtest_disable_pthreads=ON` to run in a single thread.
190264
* See the [CMake manual](https://cmake.org/cmake/help/v3.0/manual/cmake.1.html) for more information.
191265
1. Run a Make program to build tests.
192266

0 commit comments

Comments
 (0)