Skip to content

Commit ec2438e

Browse files
committed
Add support for unittest_setup and unittest_teardown functions
1 parent f0b54cf commit ec2438e

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
class LcdInterface {
5+
public:
6+
virtual void print(const char *) = 0;
7+
};
8+
9+
class MockLcd : public LcdInterface {
10+
public:
11+
void print(const char *) {}
12+
};
13+
14+
LcdInterface *Lcd_p;
15+
16+
class Calculator {
17+
public:
18+
int add(int a, int b) {
19+
int result = a + b;
20+
char buf[40];
21+
sprintf(buf, "%d + %d = %d", a, b, result);
22+
Lcd_p->print(buf);
23+
return result;
24+
}
25+
};
26+
27+
unittest_setup()
28+
{
29+
Lcd_p = new MockLcd();
30+
}
31+
32+
unittest_teardown()
33+
{
34+
delete Lcd_p;
35+
}
36+
37+
// This is a typical test where using setup (and teardown) would be useful
38+
// to set up the "external" lcd dependency that the calculator uses indirectly
39+
// but it is not something that is related to the functionality that is tested.
40+
41+
// When you want to test that the calculator actually prints the calculations,
42+
// then that should be done in the arrange part of the actual test (by setting
43+
// up an mock lcd class that keeps a list of all messages printed).
44+
45+
unittest(add)
46+
{
47+
// Arrange
48+
Calculator c;
49+
50+
// Act
51+
int result = c.add(11, 22);
52+
53+
// Assert
54+
assertEqual(33, result);
55+
}
56+
57+
unittest_main()

cpp/unittest/ArduinoUnitTests.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
#include "ArduinoUnitTests.h"
22

3+
Test* Test::sSetup = 0;
4+
Test* Test::sTeardown = 0;
35
Test* Test::sRoot = 0;

cpp/unittest/ArduinoUnitTests.h

+36-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class Test
8181
const char* mName;
8282

8383
// linked list structure for active tests
84+
static Test* sSetup;
85+
static Test* sTeardown;
8486
static Test* sRoot;
8587
Test* mNext;
8688

@@ -119,7 +121,13 @@ class Test
119121
Test(const char* _name) : mName(_name) {
120122
mResult = RESULT_NONE;
121123
mReporter = 0;
122-
append();
124+
if (_name == "s e t u p") {
125+
sSetup = this;
126+
} else if (_name == "t e a r d o w n") {
127+
sTeardown = this;
128+
} else {
129+
append();
130+
}
123131
}
124132

125133
inline void fail() { mResult = RESULT_FAIL; }
@@ -152,7 +160,9 @@ class Test
152160
static int run_and_report(int argc, char *argv[]) {
153161
// TODO: pick a reporter based on args
154162
ReporterTAP rep;
163+
if (sSetup) sSetup->task();
155164
Results results = run(&rep);
165+
if (sTeardown) sTeardown->task();
156166
return results.failed + results.skipped;
157167
}
158168

@@ -217,6 +227,31 @@ class Test
217227
} test_##name##_instance; \
218228
void test_##name ::task()
219229

230+
/**
231+
* The unittest_setup and unittest_teardown functions are intended to be used
232+
* to set up "external" dependencies that needs to present but are not directly
233+
* related to the functionality that you are testing, for instance a LCD.
234+
*/
235+
#define unittest_setup() \
236+
struct xtest_unittest_setup : Test \
237+
{ \
238+
xtest_unittest_setup() : Test("s e t u p"){}; \
239+
void task(); \
240+
} xtest_unittest_setup_instance; \
241+
void xtest_unittest_setup::task()
242+
243+
#define unittest_teardown() \
244+
struct xtest_unittest_teardown : Test \
245+
{ \
246+
xtest_unittest_teardown() : Test("t e a r d o w n"){}; \
247+
void task(); \
248+
} xtest_unittest_teardown_instance; \
249+
void xtest_unittest_teardown::task()
250+
251+
// To avoid potentionally breaking existing code by re-using the Test class for
252+
// setup and teardown, add a "x" prefix in front of names so that it will be
253+
// different from code generated by the unittest macro. Also using _name
254+
// arguments to Test that cannot be used in the unittest macro.
220255

221256
#define unittest_main() \
222257
int main(int argc, char *argv[]) { \

0 commit comments

Comments
 (0)