Testing and CTest.rst 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. Step 8: Testing and CTest
  2. =========================
  3. Testing is, historically, not the role of the build system. At best it might
  4. have a specific target which maps to building and running the project's tests.
  5. In the CMake ecosystem, the opposite is true. CMake's testing ecosystem is
  6. known as CTest. This ecosystem is both deceivingly simple and incredibly
  7. powerful. In fact it is so powerful it deserves its own full tutorial to
  8. describe everything we could achieve with it.
  9. This is not that tutorial. In this step, we will scratch the surface of some
  10. of the facilities that CTest provides.
  11. Background
  12. ^^^^^^^^^^
  13. At its core, CTest is a task launcher which runs commands and reports if they
  14. have returned zero or non-zero values. This is the level we will be dealing
  15. with CTest at.
  16. CMake provides direct integration with CTest via the :command:`enable_testing`
  17. and :command:`add_test` commands. These allow CMake to setup the necessary
  18. infrastructure in the build folder for CTest to discover, run, and report
  19. on various tests we might be interested in.
  20. After setting up and building tests, the easiest way to invoke CTest is to run
  21. it directly on the build directory with:
  22. .. code-block:: console
  23. ctest --test-dir build
  24. Which will run all available tests. Specific tests can be run with regular
  25. expressions.
  26. .. code-block:: console
  27. ctest --test-dir build -R SpecificTest
  28. CTest also has advanced mechanisms for scripting, fixtures, sanitizers,
  29. job servers, metric reportings, and much more. See the :manual:`ctest(1)`
  30. manual for more information.
  31. Exercise 1 - Adding Tests
  32. ^^^^^^^^^^^^^^^^^^^^^^^^^
  33. CTest convention dictates the building and running of tests be based on a
  34. default-``ON`` variable named :variable:`BUILD_TESTING`. When using the full
  35. suite of CTest capabilities via the :module:`CTest` module, this
  36. :command:`option` is setup for us. When using a more stripped-down approach to
  37. testing, it's expected the project will setup the option (or at least one of a
  38. similar name) on its own.
  39. When :variable:`BUILD_TESTING` is true, the :command:`enable_testing` command
  40. should be called in the root CML.
  41. .. code-block:: cmake
  42. enable_testing()
  43. This will generate all the necessary metadata into the build tree for CTest to
  44. find and run tests.
  45. Once that has been done, the :command:`add_test` command can be used to create
  46. a test anywhere in the project. The semantics of this command are similar to
  47. :command:`add_custom_command`; we can name an executable target as the "command".
  48. .. code-block:: cmake
  49. add_test(
  50. NAME MyAppWithTestFlag
  51. COMMAND MyApp --test
  52. )
  53. Goal
  54. ----
  55. Add tests for the MathFunctions library to the project and run them with CTest.
  56. Helpful Resources
  57. -----------------
  58. * :variable:`BUILD_TESTING`
  59. * :command:`enable_testing`
  60. * :command:`function`
  61. * :command:`add_test`
  62. Files to Edit
  63. -------------
  64. * ``Tests/CMakeLists.txt``
  65. * ``CMakeLists.txt``
  66. Getting Started
  67. ---------------
  68. A testing program has been written in the file ``Tests/TestMathFunctions.cxx``.
  69. This program takes a single command line argument, the math function to be
  70. tested, with valid values of ``add``, ``mul``, ``sqrt``, and ``sub``. The return
  71. code is zero if the operation is recognized and the calculated value is valid,
  72. otherwise it is non-zero.
  73. Complete ``TODO 1`` through ``TODO 7``.
  74. Build and Run
  75. -------------
  76. No special configuration is needed, configure and build as usual.
  77. .. code-block:: console
  78. cmake --preset tutorial
  79. cmake --build build
  80. Verify all the tests pass with CTest.
  81. .. note::
  82. If using a multi-config generator, eg Visual Studio, it will be necessary to
  83. specify a configuration with ``ctest -C <config> <remaining flags>``, where
  84. ``<config>`` is a value like ``Debug`` or ``Release``. This is true whenever
  85. using a multi-config generator, and won't be called out specifically in
  86. future commands.
  87. .. code-block:: console
  88. ctest --test-dir build
  89. You can run individual tests with the :option:`-R <ctest -R>` flag.
  90. .. code-block:: console
  91. ctest --test-dir build -R sqrt
  92. Solution
  93. --------
  94. First we add a new executable for the tests.
  95. .. raw:: html
  96. <details><summary>TODO 1-2: Click to show/hide answer</summary>
  97. .. literalinclude:: Step9/Tests/CMakeLists.txt
  98. :caption: TODO 1-2: Tests/CMakeLists.txt
  99. :name: Tests/CMakeLists.txt-add_executable
  100. :language: cmake
  101. :start-at: add_executable
  102. :end-at: TestMathFunctions.cxx
  103. :append: )
  104. .. raw:: html
  105. </details>
  106. Then we link in the library we are testing.
  107. .. raw:: html
  108. <details><summary>TODO 3: Click to show/hide answer</summary>
  109. .. literalinclude:: Step9/Tests/CMakeLists.txt
  110. :caption: TODO 3: Tests/CMakeLists.txt
  111. :name: Tests/CMakeLists.txt-target_link_libraries
  112. :language: cmake
  113. :start-at: target_link_libraries(TestMathFunctions
  114. :end-at: )
  115. .. raw:: html
  116. </details>
  117. We need to call :command:`add_test` for each of the valid operations, but this
  118. would get repetitive, so we write a :command:`function` to do it for us.
  119. .. raw:: html
  120. <details><summary>TODO 4: Click to show/hide answer</summary>
  121. .. literalinclude:: Step9/Tests/CMakeLists.txt
  122. :caption: TODO 4: Tests/CMakeLists.txt
  123. :name: Tests/CMakeLists.txt-function
  124. :language: cmake
  125. :start-at: function
  126. :end-at: endfunction
  127. .. raw:: html
  128. </details>
  129. Now we can use our :command:`function` to add all the tests.
  130. .. raw:: html
  131. <details><summary>TODO 5: Click to show/hide answer</summary>
  132. .. literalinclude:: Step9/Tests/CMakeLists.txt
  133. :caption: TODO 5: Tests/CMakeLists.txt
  134. :name: Tests/CMakeLists.txt-add_test
  135. :language: cmake
  136. :start-at: MathFunctionTest(add
  137. :end-at: MathFunctionTest(sub
  138. .. raw:: html
  139. </details>
  140. Finally, we can add the :variable:`BUILD_TESTING` option and conditionally
  141. enable building and running tests in the top-level CML.
  142. .. raw:: html
  143. <details><summary>TODO 6-7: Click to show/hide answer</summary>
  144. .. literalinclude:: Step9/CMakeLists.txt
  145. :caption: TODO 6: CMakeLists.txt
  146. :name: CMakeLists.txt-BUILD_TESTING
  147. :language: cmake
  148. :start-at: option(BUILD_TESTING
  149. :end-at: option(BUILD_TESTING
  150. .. literalinclude:: Step9/CMakeLists.txt
  151. :caption: TODO 7: CMakeLists.txt
  152. :name: CMakeLists.txt-enable_testing
  153. :language: cmake
  154. :start-at: if(BUILD_TESTING)
  155. :end-at: endif()
  156. .. raw:: html
  157. </details>