Welcome back to the world of C++ game engine infrastructure! Today, we will be exploring the fascinating realm of test automation in the context of game programming and game engine development.
In the previous video, we set up our namespace and file system, incorporating the IOC (Inversion of Control) infrastructure we built in previous videos. However, there is a key difference in this video: we will separate Singletons from the container and delve into the interface by writing unit tests.
Tests are not only a means of testing code; they also serve as valuable documentation. Open source projects often lack comprehensive documentation, but by examining the tests, you can gain insights into how different parts of the code are used. So, let’s dive into test automation!
![Test Automation: Enhancing Game Engine Programming with Unit Tests](https://img.youtube.com/vi/d2jYB7NcT_k/hq720.jpg)
Contents
Setting Up Unit Tests
To begin, let’s add a new project for our unit tests. We have several options, and while Google Test is a popular choice, we will use the Microsoft test framework to minimize friction. We can ignore the pre-compiled headers for now and focus on what matters.
Next, we need to add a reference to the core project, as it is the project we are testing. This ensures that the required dependencies are included, allowing for successful builds.
Running the Tests
To run the tests efficiently, we’ll use the test runner provided by the test framework. By navigating to the Test Explorer window, we can easily run and organize our tests. Running the tests from here will aggregate the results and allow us to track their status.
Writing Unit Tests
Now comes the exciting part—writing unit tests! In this video, we’ll demonstrate how to use the IOC container in our tests. We’ll create a fresh IOC container before each test runs to ensure independence and avoid interfering with the test data. We’ll also explore the use of assertions to check if the tests meet our expectations.
TEST_METHOD_INITIALIZE(Setup) {
p_ioc = std::make_unique<IOCContainer>();
}
TEST_METHOD_CLEANUP(TearDown) {
p_ioc.reset();
}
TEST_METHOD(SimpleResolveSuccess) {
const auto expected = 69.0;
const auto actual = p_ioc->Resolve();
Assert::AreEqual(expected, actual);
}
TEST_METHOD(SimpleResolveFailure) {
Assert::ExpectException<std::runtime_error>([] {
p_ioc->ResolveBase();
});
}
These are just a couple of examples of the tests we can write using the IOC container. Writing unit tests for our code can be initially time-consuming, but it pays off in terms of bug detection and future code refactoring.
Enhancing Test Development
To streamline our test development process, we can create a wrapper header file that disables specific warnings. By including this header file before the test framework header, we can maintain static analysis checks for our code while avoiding warnings from the test framework.
#pragma warning(push)
#pragma warning(disable : 26433)
#include "CppUnitTest.h"
#pragma warning(pop)
This allows us to focus on the warnings that matter for our code while ignoring warnings from external sources.
Conclusion
In this video, we explored the fundamentals of test automation and unit testing within the context of game engine programming. We learned how to set up unit tests, run them efficiently, and write tests for our IOC container.
Writing unit tests is an essential part of the software development process. It helps us catch bugs early, document our code, and ensure that changes to the codebase do not introduce unexpected issues. While writing unit tests may add some overhead, the benefits far outweigh the costs.
If you found this video helpful, please like and share it. Stay tuned for more exciting content on C++ game engine infrastructure.