HxTest Testing Framework
Hexane uses a custom testing framework for testing the backend code. Here is a quick overview on its capabilities, and how to use it.
Benefits
-
does not require registration of test cases
-
test cases can be manually or automatically named
-
Supports aborting the remaining tests if
-
any test fails
-
specific test(s) fail
-
-
no external pre-processing is needed
-
implicit support for fixtures
-
aborting tests still allows cleanup/takedown code to run
-
the only external dependancy is the STL
Available Macros
Macro | Description |
---|---|
TESTCASE | Creates and registers a new, automatically named testcase. |
HxT_TEST(name) | Creates and registers a new, manually named testcase. |
HxT_FAIL(msg) | Fails a test unconditionally. |
HxT_ASSERT(expr) | Asserts that expr is true. |
HxT_ASSERT_EQUALS(v1, v2) | Asserts that v1 == v2. |
HxT_ASSERT_DIFFERS(v1, v2) | Asserts that v1 != v2 |
HxT_ASSERT_DELTA(v1, v2, tol) | Asserts that abs(v1 - v2) < tol |
HxT_ASSERT_LT(v1, v2) | Asserts that v1 < v2 |
HxT_ASSERT_LTE(v1, v2) | Asserts that v1 <= v2 |
HxT_ASSERT_GT(v1, v2) | Asserts that v1 > v2 |
HxT_ASSERT_GTE(v1, v2) | Asserts that v1 >= v2 |
HxT_RUN_TESTS() | Runs all test cases. |
HxT_ABORT_ON_FAIL() | Configures HxTest to abort execution on fail |
HxT_NO_ABORT_ON_FAIL() | Configures HxTest to continue execution on fail |
Examples
#include "hxtest.h" TESTCASE { HxT_ASSERT( 1 + 1 > 1 ); HxT_ASSERT_EQUALS( 1 + 1, 2 ); } TESTCASE { HxT_ASSERT_EQUALS( 2 * 2, 5 ); } int main() { HxT_RUN_TESTS(); return 0; }
produces the following output:
$ ./a.out Running 2 tests. simple.cpp:20: Expected (2 * 2 == 5), found (4 != 5) ****** Summary ****** Failed 1 of 2 tests. Success Rate: 50%.
Although, HxTest also allows for manual naming of test cases, ie, we could have written Example 1 as:
#include "hxtest.h" HxT_TEST(testAddition) { HxT_ASSERT( 1 + 1 > 1 ); HxT_ASSERT_EQUALS( 1 + 1, 2 ); } HxT_TEST(testMultiplication) { HxT_ASSERT_EQUALS( 2 * 2, 5 ); } int main() { HxT_RUN_TESTS(); return 0; }
Aborting Tests if an Assert fails
HxTest can abort the execution of the test driver if an assert fails. The program does not simply exit - the execution continues after the HxT_RUN_TESTS() call. That way, if any clean up, or teardown is needed, such will not be skipped when an assert fails.
#include "hxtest.h" TESTCASE { HxT_ASSERT_DIFFERS(5, 4); } int main() { // abort execution if *ANY* assert fails HxT_ABORT_ON_FAIL(); HxT_RUN_TESTS(); // execution continues here if an assert fails when // when HxT_ABORT_ON_FAIL() is used. return 0; }
It is also possible to abort the execution if a specific assert fails. Such is accomplished by wrapping the assert in HxT_ABORT_ON_FAIL() and HxT_NO_ABORT_ON_FAIL() calls.
#include "hxtest.h" TESTCASE { // abort execution if this, single assert fails HxT_ABORT_ON_FAIL(); HxT_ASSERT_DIFFERS(5, 4); HxT_NO_ABORT_ON_FAIL(); // even if this assert fails, the program will continue HxT_ASSERT_EQUALS(5, 4); HxT_ASSERT_EQUALS(4, 4); } int main() { HxT_RUN_TESTS(); return 0; }
Fixtures
Although HxTest has no explicit support for fixtures, we can achieve the same effect by using a class. The following example illustrates this.
#include "hxtest.h" // implicit fixture class aFixture { public: int x; int y; // setup aFixture() { x = 5; y = 3; } // teardown ~aFixture() { } } fix; TESTCASE { HxT_ASSERT_EQUALS(fix.x, 5); } TESTCASE { HxT_ASSERT_EQUALS(fix.y, 3); } TESTCASE { HxT_ASSERT_LT(fix.x, fix.y); } int main() { HxT_RUN_TESTS(); return 0; }
Misc
Hxtest also has the capability to allow ASSERT statements appear in functions.
#include "hxtest.h" void validate(int a) { HxT_ASSERT_GT(a, 3 + 5); } TESTCASE { validate(14); validate(1); } int main() { HxT_RUN_TESTS(); return 0; }