We use the [http://cxxtest.com/ CxxTest] framework for tests. See the [http://cxxtest.com/cxxtest/doc/guide.html CxxTest user guide] for an introduction and general reference. Tests are highly recommended for new code, and for bug fixes to old code, because they provide some assurances of quality and help detect regressions and portability issues. Sometimes code might need to be redesigned a bit so that it's more easily testable, which is fine. See also http://svn.wildfiregames.com/docs/writing-components.html#testing for additionnal information. There are a few issues specific to our game: == Test locations == The tests for file `foo/bar/Baz.{cpp,h}` usually go into `foo/bar/tests/test_Baz.h`, and have the following form: {{{ /* Copyright (C) 2009 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #include "lib/self_test.h" #include "foo/bar/Baz.h" class TestBaz : public CxxTest::TestSuite { public: void test_whatever() { ... } }; }}} After adding a new test file, you have to run the `update-workspaces` script to integrate the new file into the build system. == New assertion macros == `TS_ASSERT_OK(expr)` -- assert `expr == INFO::OK`. `TS_ASSERT_STR_EQUALS(str1, str2)` -- assert `std::string(str1) == std::string(str2)`. `TS_ASSERT_WSTR_EQUALS(str1, str2)` -- assert `std::wstring(str1) == std::wstring(str2)`. `TS_ASSERT_STR_CONTAINS(str1, str2)` -- assert `str2` is contained somewhere within `str1`. `TS_ASSERT_VECTOR_EQUALS_ARRAY(vec1, array)` -- assert a `std::vector` is equal to a constant-sized array. == Mocks == Particularly for testing code that relies on global system functions (`time`, `getcwd`, etc), it can be useful to replace the functions with mock objects that return special values or do special checks on their arguments. The !CxxTest guide describes how to do that. We use the following specifics: * To mock functions from `foo.h`, create the file `mocks/foo.h` saying: {{{ #include #include CXXTEST_MOCK_GLOBAL(...) CXXTEST_MOCK_GLOBAL(... etc, as in the CxxTest guide ...) }}} * Update `mocks/mocks_real.cpp` to add the line `#include "mocks/foo.h"` * Update `mocks/mocks_test.cpp` to add the line `#include "mocks/foo.h"` and, if you want to default to calling the real function (instead of an empty dummy function) in tests that don't override it then add `DEFAULT(foo);` * In any source file that should use the mocks, do a `#include "mocks/foo.h"` (instead of the original `#include `), and use `T::func()` instead of `func()`. == Running tests == On Windows: Run the "test" project in the VS debugger. Or, use "set as startup project" on the "test" project and then use F5 to run it. On Linux and OS X: Run `make` or `make test` to build the test executable. Then run `./test_dbg` from `binaries/system`. To run a single test suite instead of all tests, add the command-line argument `-test TestSuitename`. To run a single test, add `-test TestSuitename::test_case_name` (using the class/method names from the test code).