C/C++ Tests¶
GoogleTest is the C++ testing framework used to test C/C++ code in Blender.
Building of tests must be enabled using the WITH_GTESTS
CMake build
option, tests can then be run with make test
.
Test Executables¶
Unit tests are bundled in one executable per module, for example
blenlib_test
. Integration tests that depend on other Blender modules
are built as part of the blender_test
executable.
The tests executables are output to bin/tests/
in the build
directory.
Test Source Files¶
Test code is located in tests/
folders in modules, next to the
source files for the module.
Details are described in the Tests section of the C++ style guide.
Example¶
The tests for Blender's path utilities:
blenlib/intern/path_util.c
Test file located in:
blenlib/tests/BLI_path_util_test.cc
The test can be executed from the build directory:
./bin/tests/BLI_test
And produces output, for example:
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from path_util
[ RUN ] path_util.PathUtilClean
[ OK ] path_util.PathUtilClean (0 ms)
[ RUN ] path_util.PathUtilFrame
[ OK ] path_util.PathUtilFrame (0 ms)
[ RUN ] path_util.PathUtilSplitDirfile
[ OK ] path_util.PathUtilSplitDirfile (0 ms)
[----------] 3 tests from path_util (0 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[ PASSED ] 3 tests.
Scaffolding¶
When testing anything other than pure functions working on primitive data types, there are a
number of prerequisite steps that need to be done at startup for the a test to even run. Examples
of times that this would be needed is anything involving Depsgraph
evaluation.
The following are a number of stripped down examples of a TestFixture that can be extended to fit further setup and teardown of test data.
ID Creation¶
class ExampleTestFixture : public testing::Test {
public:
Main *bmain;
Scene *scene;
static void SetUpTestSuite()
{
CLG_init(); // Many systems have a hard dependency on logging being available.
BKE_idtype_init(); // Allows actually adding defined ID blocks (Scene, etc).
RNA_init();
BKE_appdir_init(); // Dependency of IMB_init.
IMB_init(); // Needed for scene initialization.
}
void SetUp() override
{
bmain = BKE_main_new();
scene = BKE_scene_add(bmain, "Test Scene");
}
void TearDown() override
{
BKE_main_free(bmain);
}
static void TearDownTestSuite()
{
RNA_exit();
IMB_exit();
BKE_appdir_exit();
CLG_exit();
}
};
TEST_F(ExampleTestFixture, example) {
EXPECT_TRUE(true);
}
Depsgraph Initialization & Evaluation¶
class ExampleDepsgraphTestFixture : public testing::Test {
public:
Main *bmain;
Scene *scene;
Depsgraph *depsgraph;
Object *object;
static void SetUpTestSuite()
{
CLG_init(); /* Many systems have a hard dependency on logging being available. */
BKE_cpp_types_init(); /* Allows instantiating objects which are C++ types (e.g. Object *). */
BKE_idtype_init(); /* Allows instantiating objects with an ID block. */
BKE_callback_global_init(); /* Needed for depsgraph evaluation. */
DEG_register_node_types(); /* Needed for depsgraph initialization. */
BKE_appdir_init(); /* Needed for IMB initialization. */
IMB_init(); /* Needed for scene initialization. */
}
void SetUp() override
{
bmain = BKE_main_new();
scene = BKE_scene_add(bmain, "Test Scene");
ViewLayer *view_layer = BKE_view_layer_default_view(scene);
depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
DEG_make_active(depsgraph);
object = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, "Empty");
DEG_relations_tag_update(bmain);
DEG_graph_relations_update(depsgraph);
BKE_scene_graph_update_tagged(depsgraph, bmain);
}
void TearDown() override
{
BKE_main_free(bmain);
}
static void TearDownTestSuite()
{
BKE_callback_global_finalize();
IMB_exit();
BKE_appdir_exit();
CLG_exit();
}
};
TEST_F(ExampleDepsgraphTestFixture, is_fully_evaluated)
{
EXPECT_TRUE(DEG_is_fully_evaluated(depsgraph));
}
Further Reading¶
- List of assertions that can be used in tests
- Automated Testing issues on projects.blender.org