Introduction to testing
|
Testing is the standard approach to software quality assurance
Testing helps to ensure that code performs its intended function: well-tested code is likely to be more reliable, correct and flexible
Good tests thoroughly exercise critical code
Code without any tests should arouse suspicion, but it is entirely possible to write a comprehensive but practically worthless test suite
Testing can contribute to performance, security and long-term stability as the size of the codebase and its network of contributors grows
Testing can ensure that software has been installed correctly, is portable to new platforms, and is compatible with new versions of its dependencies
In the context of research software, testing can be used to validate code i.e. ensure that it faithfully implements scientific theory
Unit (e.g. a function); Functional (e.g. a library); and Regression, (e.g. a bug) are three commonly used types of tests
Test coverage can provide a coarse- or fine-grained metric of comprehensiveness, which often provides a signal of code quality
Automated testing is another such signal: it lowers friction; ensures that breakage is identified sooner and isn’t released; and implies that machine-readable instructions exist for building and code and running the tests
Testing ultimately contributes to sustainability i.e. that software is (and remains) fit for purpose as its functionality and/or contributor-base grows, and its dependencies and/or runtime environments change
|
Introduction to Unit Testing using GoogleTest
|
Amongst the various libraries available for testing in C++, GoogleTest is one of the most popular and easy to use library.
GoogleTest offers various macros such as equality assertions, boolean assertions, exception assertions etc. to write your unit tests.
A unit test typically follows a three step structure: Setup, Execution and Verification also widely termed as Arrange, Act and Assert (AAA) technique.
GoogleTest allows you to write your tests with and without your own main function. In case you do not want to write your own main function, you can link against the one provided in the libgtest_main.a library.
|
Introduction to Test Fixtures using GoogleTest
|
A test fixture is a useful tool while writing unit tests because it reduces the code duplication, maintains test independence and takes care of the common setup and teardown operations.
Test fixture ensures that different tests do not interfere with each other by creating a new instance of its fixture class for every test.
GoogleTest allows us to run a subset of tests which can be quite useful if our full test suite takes a long time to run or if we want to develop and check the functionality of a particular test.
|
Parameterised Tests using GoogleTest
|
Parameterised tests can be used to repeat a specific test with different inputs, reducing code duplication.
Parameterised tests are individual tests, so they are more concise and easy to maintain than using a loop for testing multiple conditions
Fixtures can be combined with parameterised tests for maximum flexibility.
|
Tests doubles and dependency injection
|
Test doubles let you write unit tests in isolation from other bits of code
Test doubles require dependency injection to be able to replace real parts of your code with fake ones
Stubs provide canned, simple values as indirect inputs to the function under test.
Mocks let you check indirect outputs (i.e. intermediate results) and also can provide stubs.
Google Mock provides the tools to implement mocks
|
General unit testing best practice
|
Unit tests should be isolated
Unit tests should be repeatable
Unit tests should be readable
Unit tests should have one assertion per test
|