Version 12 (modified by 12 years ago) (diff) | ,
---|
LolUnit tutorial
This tutorial is a quick introduction to LolUnit.
LolUnit is still in its early development stage. Feel free to send comments, suggestions or questions to sam@hocevar.net.
Getting started
Only one line is required to start using LolUnit:
#include <lol/unit.h>
No library and no compiler or linker flags are required as long as the <lol/unit.h>
file is copied in a place where the compiler can find it, for instance in /usr/include/lol/unit.h
.
Fixtures and tests
A fixture is a container class for tests that allows optional setup and teardown methods. To declare and automatically register a fixture, use the LOLUNIT_FIXTURE
macro:
LOLUNIT_FIXTURE(MyFirstFixture) { };
A test is a method within a fixture that runs a series of checks. To declare and automatically register a test within a fixture, use the LOLUNIT_TEST
macro:
LOLUNIT_FIXTURE(MyFirstFixture) { LOLUNIT_TEST(MyFirstTest) { } };
Add checks
Several macros are provided to perform various checks:
LOLUNIT_ASSERT(condition)
will cause the current test to fail ifcondition
is not met.LOLUNIT_ASSERT_EQUAL(a, b)
will cause the current test to fail ifa
andb
are not equal.LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, t)
will cause the current test to fail if the floating point valuesa
andb
are not equal, with a tolerance oft
.- all other comparison checks and their negations are available:
LOLUNIT_ASSERT_GREATER
,LOLUNIT_ASSERT_NOT_GREATER
, etc.
This is how to populate our fixture:
LOLUNIT_FIXTURE(MyFirstFixture) { LOLUNIT_TEST(Addition) { LOLUNIT_ASSERT_EQUAL(1 + 1, 2); LOLUNIT_ASSERT_LESS(2 + 2, 5); /* Check that our value for 2 is not too large */ LOLUNIT_ASSERT_NOT_GEQUAL(2 + 2, 5); } LOLUNIT_TEST(Division) { double a = 1.0 / 2; double b = 1.0 / 3; double c = 1.0 / 6; LOLUNIT_ASSERT_DOUBLES_EQUAL(a - b, c, 1e-10); } };
Run the test
Fixtures and their tests are automatically registered in a list global to the program. A TextTestRunner
object can then be used to run all tests:
int main(void) { lol::TextTestRunner runner; return !runner.run(); }
And this is the output:
.. OK (2 tests)
Test failures
Let's add yet another test to MyFirstFixture
:
LOLUNIT_TEST(ExpectedFailure) { double a = 0.1; double b = 0.2; LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, 1e-10); }
And running it:
...F !!!FAILURES!!! Test Results: Run: 3 Failures: 1 Errors: 0 1) test: MyFirstFixture::ExpectedFailure (F) line: 23 tutorial.cpp double equality assertion failed - Expected: a = 0.1 - Actual : b = 0.2 - Delta : 1e-010
The test failure is properly spotted and information is given on where and how it happened.
Comparison with CppUnit
LolUnit is very similar to CppUnit, except it requires significantly less user input. This is what we would have done with CppUnit:
#include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/TestCaller.h> #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> #include <cppunit/TextTestRunner.h> class MyFirstFixture : public CppUnit::TestCase { CPPUNIT_TEST_SUITE(MyFirstFixture); CPPUNIT_TEST(Addition); CPPUNIT_TEST(Division); CPPUNIT_TEST(ExpectedFailure); CPPUNIT_TEST_SUITE_END(); void Addition() { CPPUNIT_ASSERT_EQUAL(1 + 1, 2); CPPUNIT_ASSERT(2 + 2 < 5); /* Check that our value for 2 is not too large */ CPPUNIT_ASSERT(!(2 + 2 >= 5)); } void Division() { double a = 1.0 / 2; double b = 1.0 / 3; double c = 1.0 / 6; CPPUNIT_ASSERT_DOUBLES_EQUAL(a - b, c, 1e-10); } void ExpectedFailure() { double a = 0.1; double b = 0.2; CPPUNIT_ASSERT_DOUBLES_EQUAL(a, b, 1e-10); } }; CPPUNIT_TEST_SUITE_REGISTRATION(MyFirstFixture); int main(void) { CppUnit::TextTestRunner runner; runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); return !runner.run(); }
One major problem I have with this system is that Addition
needs to be declared and defined at two different places. Similarly, MyFirstFixture
needs to be declared, then given as an argument to CPPUNIT_TEST_SUITE
, and finally as an argument to CPPUNIT_TEST_SUITE_REGISTRATION
. There is no reason the user should have to duplicate this information.
And this is the output:
...F !!!FAILURES!!! Test Results: Run: 3 Failures: 1 Errors: 0 1) test: MyFirstFixture::ExpectedFailure (F) line: 34 tutorial.cpp double equality assertion failed - Expected: 0.1 - Actual : 0.2 - Delta : 1e-10
Also, there is no way to compare two values and have them printed in case of failure. The equivalent of LOLUNIT_ASSERT_LESS(a, b)
, which will print the values of a
and b
in case of failure, is the less interesting CPPUNIT_ASSERT(a < b)
, which will only output true
or false
.