Unit tests » History » Version 16

Rogers, Chris, 28 September 2011 17:44

1 1 Rogers, Chris
h1. Unit Tests
The idea behind unit tests is "does this function do what I think it's doing". We want to check that, when we write a function, we haven't put any subtle (or not so subtle) errors in the code. Also we want to check that when we change some other function, it doesn't break existing code. So for each function (or maybe pair of functions) we write a test function. These are known as "unit tests".
5 8 Rogers, Chris
Unit testing is an essential part of the QA process for MAUS, so that
*Code which is not unit tested is not eligible for release in MAUS*. This includes, for example, all code in the ${MAUS_ROOT_DIR}/src directory.
Also note that tests are code that we need to edit, etc, so tests should obey any relevant style guides.
11 13 Rogers, Chris
In general:
12 15 Rogers, Chris
* Code which is in common_cpp should have tests in cpp_unit; tests are written in the gtest framework
* Code which is in common_py should have tests in py_unit; tests are written in the unittest framework
* Code which is in input, map, reduce areas should have tests in the relevant input, map, reduce subdirectories; typically we use the SWIG interface and write tests in python even for C++ code
15 13 Rogers, Chris
16 1 Rogers, Chris
h2. C++ unit tests
18 3 Rogers, Chris
In C++ we use the google testing framework which has some convenience functions for e.g. equality testing in the presence of floating point errors, setting up common test data, etc. The google test framework should have been installed during the third party libraries. The C++ tests are found at <pre>${MAUS_ROOT_DIR}/tests/cpp_unit</pre> Sconstruct builds a unit test application in build/test_cpp_unit that you can just run from the command line.
19 1 Rogers, Chris
Go ahead and edit the tests if you need to. We should have one source file for each header file in the main body of the code. Each directory in ${MAUS_ROOT_DIR}/src/common/* should be a directory in ${MAUS_ROOT_DIR}/tests/cpp_unit. If you want to add an extra test, you need to make sure that it includes gtest <pre>#include "gtest/gtest.h"</pre> It should be automatically added to the test executable by scons.
22 12 Rogers, Chris
To run the tests, either run the full python unit testing suite, or run just the cpp tests by running executable build/test_cpp_unit (after building). If you are just interested in a specific test, you can do e.g. <pre>build/test_cpp_unit --gtest_filter=VirtualPlaneTest.*</pre> to run all tests from VirtualPlaneTest
23 11 Rogers, Chris
24 1 Rogers, Chris
"Google tests documentation":
25 5 Rogers, Chris
26 1 Rogers, Chris
h2. Python unit tests
28 16 Rogers, Chris
In Python we use the internal unittest module for a unit testing framework. Python unit tests are found at <pre>${MAUS_ROOT_DIR}/tests/py_unit</pre> Feel free to edit or add extra unit tests if you need to. We should have one python source file for each python source file in the main body of the code.
29 5 Rogers, Chris
30 10 Rogers, Chris
"unittest documentation ":
32 7 Rogers, Chris
h2. More on the unit test concept
33 5 Rogers, Chris
The idea behind unit tests is to test at the level of the smallest unit that the code does what we think. We test at the smallest unit so that:
* test coverage is high
* tests are quick to run
* we get logically separated functions
Let's consider each of these points individually
* _test coverage is high_ - if we imagine the execution path following some branch structure, then we get many more possible execution paths for longer code snippets. So maintaining high test coverage becomes very difficult, and we need many more tests to have good test coverage.
* _tests are quick to run_ - the execution time goes as the (number_of_tests)*(length_of_each_test). Now, we have many more tests to keep a good test coverage, and each test is longer because they are testing bigger code snippets. This means tests are slowwww. You want to actually run the tests, and an essential part of this is making sure they are quick enough. 
44 1 Rogers, Chris
* _we get logically separated functions_ - functions that do simple, understandable things are less likely to be buggy than functions that do complicated or difficult things. The process of really testing if a function does what you intended forces us to make code simple and understandable - otherwise the test becomes difficult to write.
45 6 Rogers, Chris
46 8 Rogers, Chris
Explicitly, unit tests are not intended to test: that code works together in the desired fashion, code integrates properly with external libraries, the load on hardware is not too big, etc. These issues are dealt with in the Application tests.