[go: up one dir, main page]

Skip to content

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