Skip to content

Commit ca0c6d9

Browse files
authored
Merge pull request #42 from bxparks/develop
1.2 - overloaded 2-argument versions of test() and testing(); new gtest.h macros
2 parents e56fd89 + f8e2e44 commit ca0c6d9

File tree

122 files changed

+1536
-562
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+1536
-562
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@
3030
*.exe
3131
*.out
3232
*.app
33+
34+
# Microsoft Visual Studio
35+
/.vs

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
* 1.2 (2018-12-01)
4+
* Add overloaded 2-argument versions of test() and testing() macros to match
5+
the TEST() macro in Google Test which takes 2 arguments.
6+
* Merge 4 new Google Test adapter macros into gtest.h.
7+
* Add documentation of gtest.h to README.md.
38
* 1.1.1 (2018-10-18)
49
* Work around compiler crash on Arduino Core >= 1.6.22 (IDE >= 1.8.6)
510
due to

README.md

Lines changed: 210 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ AVR, ESP8266, ESP32 and Teensy platforms. The sister AUniter project provides
99
command line tools to verify, upload and validate the unit tests. The AUniter
1010
tools can be used in a continuous integration system like Jenkins.
1111

12-
Version: 1.1.1 (2018-10-18)
12+
Version: 1.2 (2018-12-01)
1313

1414
[![AUniter Jenkins Badge](https://us-central1-xparks2018.cloudfunctions.net/badge?project=AUnit)](https://github.com/bxparks/AUniter)
1515

@@ -99,6 +99,9 @@ Here are the features in AUnit which are not available in ArduinoUnit 2.2:
9999
* Approximate comparisons:
100100
* `assertNear()`
101101
* `asssertNotNear()`
102+
* `test()` and `testing()` macros support both 1 and 2 arguments
103+
* `test(testName)` and `test(suiteName, testName)`
104+
* `testing(testName)` and `testing(suiteName, testName)`
102105
* Test fixtures using the "F" variations of existing macros:
103106
* `testF()`
104107
* `testingF()`
@@ -117,8 +120,8 @@ Here are the features in AUnit which are not available in ArduinoUnit 2.2:
117120
* `TestRunner::include(testClass, name)`
118121
* `TestRunner::exclude(testClass, name)`
119122
* Terse and verbose modes:
120-
* `#include <AUnit.h>` - terse messages uses less flash memory
121-
* `#include <AUnitVerbose.h>` - verbose messages uses more flash memory
123+
* `#include <AUnit.h>` - terse messages use less flash memory
124+
* `#include <AUnitVerbose.h>` - verbose messages use more flash memory
122125
* Tested on the following Arduino platforms:
123126
* AVR (8-bit)
124127
* Teensy ARM (32-bit)
@@ -239,21 +242,23 @@ macros are used to create a test:
239242

240243
* `test(name) {...}` - creates a subclass of `TestOnce`
241244
* `testing(name) {...}` - creates a subclass of `TestAgain`
245+
* `test(suiteName, name) {...}` - creates a subclass of `TestOnce`
246+
* `testing(suiteName, name) {...}` - creates a subclass of `TestAgain`
242247
* `testF(classname, name) {...}` - creates a subclass of `classname`
243248
* `testingF(classname, name) {...}` - creates a subclass of `classname`
244249

245250
The code in `{ }` following these macros becomes the body of a method in a
246251
subclass derived from the base class indicated above. The `test()` and `testF()`
247252
macros place the code body into the `TestOnce::once()` method. The `testing()`
248253
and `testingF()` macros place the code body into the `TestAgain::again()`
249-
method. The name of the subclass is a concatenation of the string `"test_"` and
250-
the `name` for `test()` and `testing()`, or the concatenation of
251-
`classname` + `"_"` + `name` for `testF()` and `testing()`.
254+
method.
252255

253-
The argument to these macros are the name of the test case, and is used to
254-
generate a name for the subclass. (The name is available within the test code
255-
using the `Test::getName()` method). The macros also generate code to create an
256-
global instance of the subclass, which are static initialized by C++.
256+
The `test()` and `testing()` macros support 1 or 2 arguments. The one-argument
257+
version is inherited from ArduinoUnit. The two-argument version is
258+
analogous to the `TEST()` macro in GoogleTest, where the `suiteName` can
259+
be used to organize multiple tests into a collection of similar tests. The
260+
grouping is purely in the naming scheme of the generated code, there is no
261+
functional relationship between these tests.
257262

258263
During static initialization, the constructor of the object adds itself to an
259264
internal list. The root of that list is given by `Test::getRoot()`. The
@@ -268,11 +273,17 @@ Here is a rough outline of an AUnit unit test sketch:
268273
#include <AUnit.h>
269274
using namespace aunit;
270275

271-
test(example_test) {
272-
...assertXxx()...
276+
test(example) {
277+
...
278+
assertXxx(...)
279+
...
280+
}
281+
282+
test(ExampleTest, example) {
283+
...
273284
}
274285

275-
testing(looping_test) {
286+
testing(looping) {
276287
...code...
277288
if (...) {
278289
pass();
@@ -283,6 +294,10 @@ testing(looping_test) {
283294
}
284295
}
285296

297+
testing(LoopingTest, looping) {
298+
...
299+
}
300+
286301
class CustomTestOnce: public TestOnce {
287302
protected:
288303
// optional
@@ -348,10 +363,39 @@ void loop() {
348363
```
349364
350365
***ArduinoUnit Compatibility***: _The basic structure of the unit test is
351-
identical to ArduinoUnit. AUnit adds the `testF()` and `testingF`() macros which
366+
identical to ArduinoUnit. AUnit adds the `testF()` and `testingF`() macros,
367+
and the two-argument versions of `test()` and `testing()` which
352368
are not available in ArduinoUnit. The `Test` class in ArduinoUnit has been
353369
replaced with the `TestAgain` class in AUnit._
354370
371+
### Generated Class and Instance Names
372+
373+
The arguments to the various `test*()` macros are used to generate the name for
374+
the subclasses of `TestOnce` or `TestAgain`, and generate the names of the
375+
instances of those classes. For reference, here are the rules:
376+
377+
* `test(name)`
378+
* class: `"test_"` + name
379+
* instance: `"test_"` + name + `"_instance"`
380+
* `testing(name)`
381+
* class: `"test_"` + name
382+
* instance: `"test_"` + name + `"_instance"`
383+
* `test(suiteName, name)`
384+
* class: `suiteName` + `"_"` + name
385+
* instance: `suiteName` + `"_"` + name + `"_instance"`
386+
* `testing(suiteName, name)`
387+
* class: `suiteName` + `"_"` + name
388+
* instance: `suiteName` + `"_"` + name + `"_instance"`
389+
* `testF(className, name)`
390+
* class: `className` + `"_"` + name
391+
* instance: `className` + `"_"` + name + `"_instance"`
392+
* `testingF(className, name)`
393+
* class: `className` + `"_"` + name
394+
* instance: `className` + `"_"` + name + `"_instance"`
395+
396+
The instance name is available within the test code using the `Test::getName()`
397+
method.
398+
355399
### Binary Assertions
356400
357401
Inside the `test()` and `testing()` macros, the following assertions
@@ -1152,6 +1196,41 @@ framework, but let me know if you truly need a timeout of greater than 4m15s).
11521196

11531197
***ArduinoUnit Compatibility***: _Only available in AUnit._
11541198

1199+
## GoogleTest Adapter
1200+
1201+
It may be possible to run simple unit tests written using
1202+
[Google Test](https://github.com/google/googletest/) API on an Arduino platform
1203+
by using the
1204+
[aunit/contrib/gtest.h](src/aunit/contrib/gtest.h) adapter. This
1205+
adapter layer provides a number of macros Google Test macros which map to
1206+
their equivalent macros in AUnit:
1207+
1208+
* `ASSERT_EQ(e, a)` - `assertEqual()`
1209+
* `ASSERT_NE(e, a)` - `assertNotEqual()`
1210+
* `ASSERT_LT(e, a)` - `assertLess()`
1211+
* `ASSERT_GT(e, a)` - `assertMore()`
1212+
* `ASSERT_LE(e, a)` - `assertLessOrEqual()`
1213+
* `ASSERT_GE(e, a)` - `assertMoreOrEqual()`
1214+
* `ASSERT_STREQ(e, a)` - `assertEqual()`
1215+
* `ASSERT_STRNE(e, a)` - `assertNotEqual()`
1216+
* `ASSERT_STRCASEEQ(e, a)` - `assertStringCaseEqual()`
1217+
* `ASSERT_STRCASENE(e, a)` - `assertStringCaseNotEqual()`
1218+
* `ASSERT_TRUE(x)` - `assertTrue()`
1219+
* `ASSERT_FALSE(x)` - `assertFalse()`
1220+
1221+
To use the `gtest.h` adapter, include the following headers:
1222+
```C++
1223+
#include <AUnit.h>
1224+
#include <aunit/contrib/gtest.h>
1225+
```
1226+
1227+
or
1228+
1229+
```C++
1230+
#include <AUnitVerbose.h>
1231+
#include <aunit/contrib/gtest.h>
1232+
```
1233+
11551234
## Commandline Tools and Continuous Integration
11561235

11571236
### AUniter
@@ -1161,29 +1240,33 @@ The command line tools have been moved into the
11611240
The `auniter.sh` script can compile, upload and validate multiple AUnit tests on
11621241
multiple Arduino boards. The script can monitor the serial port and determine if
11631242
the unit test passed or failed, and it will print out a summary of all unit
1164-
tests at the end.
1165-
1166-
Full details are given in the AUniter project, but here are some quick examples
1167-
of these tools using the [AceSegment](https://github.com/bxparks/AceSegment)
1168-
project.
1169-
1170-
The following compiles and verifies the given sketches:
1171-
```
1172-
$ AUniter/auniter.sh --verify \
1173-
--boards nano,leonardo,esp8266,esp32 AceSegment/tests/*Test
1174-
```
1175-
1176-
The following uploads to and runs all the unit tests on an Arduino Nano
1177-
(`/dev/ttyUSB0`), then an Arduion Leonardo (`/dev/ttyACM0`):
1178-
```
1179-
$ AUniter/auniter.sh --test \
1180-
--boards nano:/dev/ttyUSB1,leonardo:/dev/ttyACM0 AceSegment/tests/*Test
1181-
```
1182-
1183-
The list of available ports can be found by:
1184-
```
1185-
$ AUniter/auniter.sh --list_ports
1186-
```
1243+
tests at the end. Full details are given in the AUniter project, but here are
1244+
some quick examples copied from the `AUniter/README.md` file:
1245+
1246+
* `$ auniter envs`
1247+
* list the environments configured in the `auniter.ini` config file
1248+
* `$ auniter ports`
1249+
* list the available serial ports and devices
1250+
* `$ auniter verify nano Blink.ino`
1251+
* verify (compile) `Blink.ino` using the `env:nano` environment
1252+
* `$ auniter verify nano,esp8266,esp32 Blink.ino`
1253+
* verify `Blink.ino` on 3 target environments (`env:nano`, `env:esp8266`,
1254+
`env:esp32`)
1255+
* `$ auniter upload nano:/dev/ttyUSB0 Blink.ino`
1256+
* upload `Blink.ino` to the `env:nano` target environment connected to
1257+
`/dev/ttyUSB0`
1258+
* `$ auniter test nano:USB0 BlinkTest.ino`
1259+
* compile and upload `BlinkTest.ino` using the `env:nano` environment,
1260+
upload it to the board at `/dev/ttyUSB0`, then validate the output of the
1261+
[AUnit](https://github.com/bxparks/AUnit) unit test
1262+
* `$ auniter test nano:USB0,esp8266:USB1,esp32:USB2 BlinkTest/ ClockTest/`
1263+
* upload and verify the 2 unit tests (`BlinkTest/BlinkTest.ino`,
1264+
`ClockTest/ClockTest.ino`) on 3 target environments (`env:nano`,
1265+
`env:esp8266`, `env:esp32`) located at the 3 respective ports
1266+
(`/dev/ttyUSB0`, `/dev/ttyUSB1`, `/dev/ttyUSB2`)
1267+
* `$ auniter upmon nano:USB0 Blink.ino`
1268+
* upload the `Blink.ino` sketch and monitor the serial port using a
1269+
user-configurable terminal program (e.g. `picocom`) on `/dev/ttyUSB0`
11871270

11881271
### Continuous Integration
11891272

@@ -1269,20 +1352,103 @@ TestAgain TestOnce
12691352
::again() ::once()
12701353
```
12711354
1272-
Placing the `Assertion` and `MetaAssertion` classes inside the `Test` hierarchy
1273-
allows those assertion statements to have access to the internal states of the
1274-
`Test` instance, which makes certain functions (like the early return upon
1275-
delayed failure) slightly easier to implement.
1355+
Normally, deep inheritance hierarchies like this should be avoided. However,
1356+
placing the `Assertion` and `MetaAssertion` classes inside the `Test` hierarchy
1357+
allowed those assertion statements to have access to the internal states of the
1358+
`Test` instance. This made certain features (like the early return upon delayed
1359+
failure) slightly easier to implement. For the most part, the end-users can
1360+
ignore the existence of the `Assertion` and `MetaAssertion` classes and think of
1361+
this as a simple 2-level inheritance tree.
12761362
12771363
### Comparing Pointers
12781364
12791365
Currently the `assertEqual()` and other `assertXxx()` methods do not support
1280-
comparing arbitrary pointers (i.e. `(void*)`. This could change if
1366+
comparing arbitrary pointers (i.e. `(void*)`. This could change if
12811367
[Issue #34](https://github.com/bxparks/AUnit/issues/34) is
12821368
resolved. In the meantime, a workaround is to cast the pointer to a `uintptr_t`
12831369
integer type from `#include <stdint.h>` and then calling `assertEqual()` on the
12841370
integer type.
12851371
1372+
### Testing Private Helper Methods
1373+
1374+
There is a school of throught which says that unit tests should test only the
1375+
publically exposed methods of a class or library. I agree mostly with that
1376+
sentiment, but not rigidly. I think it is sometimes useful to write unit tests
1377+
for `protected` or `private` methods. For example, when creating a chain of
1378+
small helper methods, which build up to larger publically exposed methods, it is
1379+
extremely useful to write unit tests for the helper methods in isolation.
1380+
1381+
Normally those helper methods would be `private` because they are used
1382+
only within that class, and we don't want to expose them to the public API. One
1383+
option is to make them `public` but add a comment in the function to say that it
1384+
is exposed only for testing purposes. This does not seem satisfactory because
1385+
users will tend to ignore such comments if the helper functions are useful.
1386+
1387+
I think a better way is to keep the helper functions `private` but make
1388+
the unit tests a `friend class` of the target class. The syntax for doing this
1389+
can be tricky, it took me a number of attempts to get this right, especially if
1390+
you are also using namespaces for your target class:
1391+
1392+
```C++
1393+
//------------------- Target.h -------------
1394+
1395+
// Auto-generated test class names.
1396+
class Test_helper;
1397+
class TargetSuite_helper;
1398+
class TargetTest_helper;
1399+
1400+
namespace mylib {
1401+
1402+
class Target {
1403+
public:
1404+
void publicMethod() {
1405+
...
1406+
int a = helper();
1407+
...
1408+
}
1409+
1410+
private:
1411+
// Must have the global scope operator '::'
1412+
friend class ::Test_helper;
1413+
friend class ::TargetSuite_helper;
1414+
friend class ::TargetTest_helper;
1415+
1416+
static int helper() {...}
1417+
};
1418+
1419+
}
1420+
1421+
//------------------- TargetTest.ino -------------
1422+
1423+
#include <AUnit.h>
1424+
#include "Target.h"
1425+
1426+
using namespace aunit;
1427+
using namespace mylib;
1428+
1429+
test(helper) {
1430+
assertEqual(1, Target::helper(...));
1431+
}
1432+
1433+
test(TargetSuite, helper) {
1434+
assertEqual(1, Target::helper(...));
1435+
}
1436+
1437+
class TargetTest: public TestOnce {
1438+
...
1439+
};
1440+
1441+
testF(TargetTest, helper) {
1442+
assertEqual(1, Target::helper(...));
1443+
}
1444+
1445+
```
1446+
1447+
The tricky part is that in `Target.h` you need a forward declaration of the
1448+
various auto-generated AUnit test classes, and within the `Target` class itsef,
1449+
the `friend` declaration needs to have a global scope `::` specifier before the
1450+
name of the test class.
1451+
12861452
## Benchmarks
12871453

12881454
AUnit consumes as much as 65% less flash memory than ArduinoUnit 2.2 on an AVR
@@ -1365,6 +1531,8 @@ will incorporate everything, but I will give your ideas serious consideration.
13651531
## Authors
13661532

13671533
* Created by Brian T. Park ([email protected]).
1534+
* The Google Test adapter (`gtest.h`) was created by Chris Johnson
1535+
13681536
* The design and syntax of many macros (e.g. `test()`, `assertXxx()`) were
13691537
borrowed from the [ArduinoUnit](https://github.com/mmurdoch/arduinounit)
13701538
project to allow AUnit to be almost a drop-in replacement. Many thanks to

docs/doxygen.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ PROJECT_NAME = "AUnit"
3838
# could be handy for archiving the generated documentation or if some version
3939
# control system is used.
4040

41-
PROJECT_NUMBER = 1.1.1
41+
PROJECT_NUMBER = 1.2
4242

4343
# Using the PROJECT_BRIEF tag one can provide an optional one line description
4444
# for a project that appears at the top of each page and should give viewer a

docs/html/AUnitVerbose_8h.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<tr style="height: 56px;">
2323
<td id="projectalign" style="padding-left: 0.5em;">
2424
<div id="projectname">AUnit
25-
&#160;<span id="projectnumber">1.1.1</span>
25+
&#160;<span id="projectnumber">1.2</span>
2626
</div>
2727
<div id="projectbrief">Unit testing framework for Arduino platforms inspired by ArduinoUnit and Google Test.</div>
2828
</td>
@@ -112,7 +112,7 @@
112112
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
113113
Macros</h2></td></tr>
114114
<tr class="memitem:a87cbb10969eff63f8ae66afc4e9457eb"><td class="memItemLeft" align="right" valign="top"><a id="a87cbb10969eff63f8ae66afc4e9457eb"></a>
115-
#define&#160;</td><td class="memItemRight" valign="bottom"><b>AUNIT_VERSION</b>&#160;&#160;&#160;010100</td></tr>
115+
#define&#160;</td><td class="memItemRight" valign="bottom"><b>AUNIT_VERSION</b>&#160;&#160;&#160;010200</td></tr>
116116
<tr class="separator:a87cbb10969eff63f8ae66afc4e9457eb"><td class="memSeparator" colspan="2">&#160;</td></tr>
117117
</table>
118118
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
-975 Bytes
Loading

0 commit comments

Comments
 (0)