|
|
@@ -1,50 +1,80 @@
|
|
|
Step 5: Installing and Testing
|
|
|
==============================
|
|
|
|
|
|
-Now we can start adding install rules and testing support to our project.
|
|
|
+.. _`Tutorial Testing Support`:
|
|
|
+
|
|
|
+Exercise 1 - Install Rules
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
+
|
|
|
+Often, it is not enough to only build an executable, it should also be
|
|
|
+installable. With CMake, we can specify install rules using the
|
|
|
+:command:`install` command. Supporting local installations for your builds in
|
|
|
+CMake is often as simple as specifying an install location and the targets and
|
|
|
+files to be installed.
|
|
|
+
|
|
|
+Goal
|
|
|
+----
|
|
|
+
|
|
|
+Install the ``Tutorial`` executable and the ``MathFunctions`` library.
|
|
|
+
|
|
|
+Helpful Materials
|
|
|
+-----------------
|
|
|
+
|
|
|
+* :command:`install`
|
|
|
|
|
|
-Install Rules
|
|
|
+Files to Edit
|
|
|
-------------
|
|
|
|
|
|
-The install rules are fairly simple: for ``MathFunctions`` we want to install
|
|
|
-the library and header file and for the application we want to install the
|
|
|
-executable and configured header.
|
|
|
+* ``MathFunctions/CMakeLists.txt``
|
|
|
+* ``CMakeLists.txt``
|
|
|
|
|
|
-So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
|
|
+Getting Started
|
|
|
+---------------
|
|
|
|
|
|
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
|
|
- :caption: MathFunctions/CMakeLists.txt
|
|
|
- :name: MathFunctions/CMakeLists.txt-install-TARGETS
|
|
|
- :language: cmake
|
|
|
- :start-after: # install rules
|
|
|
+The starting code is provided in the ``Step5`` directory. In this
|
|
|
+exercise, complete ``TODO 1`` through ``TODO 4``.
|
|
|
|
|
|
-And to the end of the top-level ``CMakeLists.txt`` we add:
|
|
|
+First, update ``MathFunctions/CMakeLists.txt`` to install the
|
|
|
+``MathFunctions`` and ``tutorial_compiler_flags`` libraries to the ``lib``
|
|
|
+directory. In that same file, specify the install rules needed to install
|
|
|
+``MathFunctions.h`` to the ``include`` directory.
|
|
|
|
|
|
-.. literalinclude:: Step6/CMakeLists.txt
|
|
|
- :caption: CMakeLists.txt
|
|
|
- :name: CMakeLists.txt-install-TARGETS
|
|
|
- :language: cmake
|
|
|
- :start-after: # add the install targets
|
|
|
- :end-before: # enable testing
|
|
|
+Then, update the top level ``CMakeLists.txt`` to install
|
|
|
+the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files
|
|
|
+should be installed to the ``include`` directory. Remember that
|
|
|
+``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`.
|
|
|
|
|
|
-That is all that is needed to create a basic local install of the tutorial.
|
|
|
+Build and Run
|
|
|
+-------------
|
|
|
|
|
|
-Now run the :manual:`cmake <cmake(1)>` executable or the
|
|
|
+Make a new directory called ``Step5_build``. Run the
|
|
|
+:manual:`cmake <cmake(1)>` executable or the
|
|
|
:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
|
|
|
with your chosen build tool.
|
|
|
|
|
|
-Then run the install step by using the ``install`` option of the
|
|
|
+Then, run the install step by using the ``install`` option of the
|
|
|
:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of
|
|
|
-CMake must use ``make install``) from the command line. For
|
|
|
-multi-configuration tools, don't forget to use the ``--config`` argument to
|
|
|
-specify the configuration. If using an IDE, simply build the ``INSTALL``
|
|
|
-target. This step will install the appropriate header files, libraries, and
|
|
|
-executables. For example:
|
|
|
+CMake must use ``make install``) from the command line. This step will
|
|
|
+install the appropriate header files, libraries, and executables. For example:
|
|
|
|
|
|
.. code-block:: console
|
|
|
|
|
|
cmake --install .
|
|
|
|
|
|
+For multi-configuration tools, don't forget to use the ``--config`` argument to
|
|
|
+specify the configuration.
|
|
|
+
|
|
|
+.. code-block:: console
|
|
|
+
|
|
|
+ cmake --install . --config Release
|
|
|
+
|
|
|
+If using an IDE, simply build the ``INSTALL`` target. You can build the same
|
|
|
+install target from the command line like the following:
|
|
|
+
|
|
|
+.. code-block:: console
|
|
|
+
|
|
|
+ cmake --build . --target install --config Debug
|
|
|
+
|
|
|
The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the
|
|
|
root of where the files will be installed. If using the ``cmake --install``
|
|
|
command, the installation prefix can be overridden via the ``--prefix``
|
|
|
@@ -54,42 +84,227 @@ argument. For example:
|
|
|
|
|
|
cmake --install . --prefix "/home/myuser/installdir"
|
|
|
|
|
|
-Navigate to the install directory and verify that the installed Tutorial runs.
|
|
|
+Navigate to the install directory and verify that the installed ``Tutorial``
|
|
|
+runs.
|
|
|
|
|
|
-.. _`Tutorial Testing Support`:
|
|
|
+Solution
|
|
|
+--------
|
|
|
|
|
|
-Testing Support
|
|
|
----------------
|
|
|
+The install rules for our project are fairly simple:
|
|
|
|
|
|
-Next let's test our application. At the end of the top-level ``CMakeLists.txt``
|
|
|
-file we can enable testing and then add a number of basic tests to verify that
|
|
|
-the application is working correctly.
|
|
|
+* For ``MathFunctions``, we want to install the libraries and header file to
|
|
|
+ the ``lib`` and ``include`` directories respectively.
|
|
|
+
|
|
|
+* For the ``Tutorial`` executable, we want to install the executable and
|
|
|
+ configured header file to the ``bin`` and ``include`` directories
|
|
|
+ respectively.
|
|
|
+
|
|
|
+So to the end of ``MathFunctions/CMakeLists.txt`` we add:
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 1: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
|
|
+ :caption: TODO 1: MathFunctions/CMakeLists.txt
|
|
|
+ :name: MathFunctions/CMakeLists.txt-install-TARGETS
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # install libs
|
|
|
+ :end-before: # install include headers
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+and
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 2: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
|
|
|
+ :caption: TODO 2: MathFunctions/CMakeLists.txt
|
|
|
+ :name: MathFunctions/CMakeLists.txt-install-headers
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # install include headers
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+The install rules for the ``Tutorial`` executable and configured header file
|
|
|
+are similar. To the end of the top-level ``CMakeLists.txt`` we add:
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 3,4: Click to show/hide answer</summary>
|
|
|
|
|
|
.. literalinclude:: Step6/CMakeLists.txt
|
|
|
:caption: CMakeLists.txt
|
|
|
- :name: CMakeLists.txt-enable_testing
|
|
|
+ :name: TODO 3,4: CMakeLists.txt-install-TARGETS
|
|
|
:language: cmake
|
|
|
- :start-after: # enable testing
|
|
|
+ :start-after: # add the install targets
|
|
|
+ :end-before: # enable testing
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
|
|
|
-The first test simply verifies that the application runs, does not segfault or
|
|
|
-otherwise crash, and has a zero return value. This is the basic form of a
|
|
|
-CTest test.
|
|
|
+That is all that is needed to create a basic local
|
|
|
+install of the tutorial.
|
|
|
|
|
|
-The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test
|
|
|
-property to verify that the output of the test contains certain strings. In
|
|
|
-this case, verifying that the usage message is printed when an incorrect number
|
|
|
-of arguments are provided.
|
|
|
+Exercise 2 - Testing Support
|
|
|
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-Lastly, we have a function called ``do_test`` that runs the application and
|
|
|
-verifies that the computed square root is correct for given input. For each
|
|
|
-invocation of ``do_test``, another test is added to the project with a name,
|
|
|
-input, and expected results based on the passed arguments.
|
|
|
+CTest offers a way to easily manage tests for your project. Tests can be
|
|
|
+added through the :command:`add_test` command. Although it is not
|
|
|
+explicitly covered in this tutorial, there is a lot of compatibility
|
|
|
+between CTest and other testing frameworks such as :module:`GoogleTest`.
|
|
|
|
|
|
-Rebuild the application and then cd to the binary directory and run the
|
|
|
+Goal
|
|
|
+----
|
|
|
+
|
|
|
+Create unit tests for our executable using CTest.
|
|
|
+
|
|
|
+Helpful Materials
|
|
|
+-----------------
|
|
|
+
|
|
|
+* :command:`enable_testing`
|
|
|
+* :command:`add_test`
|
|
|
+* :command:`function`
|
|
|
+* :command:`set_tests_properties`
|
|
|
+* :manual:`ctest <ctest(1)>`
|
|
|
+
|
|
|
+Files to Edit
|
|
|
+-------------
|
|
|
+
|
|
|
+* ``CMakeLists.txt``
|
|
|
+
|
|
|
+Getting Started
|
|
|
+---------------
|
|
|
+
|
|
|
+The starting source code is provided in the ``Step5`` directory. In this
|
|
|
+exercise, complete ``TODO 5`` through ``TODO 9``.
|
|
|
+
|
|
|
+First, we need to enable testing. Next, begin adding tests to our project
|
|
|
+using :command:`add_test`. We will work through adding 3 simple tests and
|
|
|
+then you can add additional testing as you see fit.
|
|
|
+
|
|
|
+Build and Run
|
|
|
+-------------
|
|
|
+
|
|
|
+Navigate to the build directory and rebuild the application. Then, run the
|
|
|
:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
|
|
|
multi-config generators (e.g. Visual Studio), the configuration type must be
|
|
|
specified with the ``-C <mode>`` flag. For example, to run tests in Debug
|
|
|
-mode use ``ctest -C Debug -VV`` from the binary directory
|
|
|
+mode use ``ctest -C Debug -VV`` from the build directory
|
|
|
(not the Debug subdirectory!). Release mode would be executed from the same
|
|
|
-location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
|
|
+location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
|
|
|
target from the IDE.
|
|
|
+
|
|
|
+Solution
|
|
|
+--------
|
|
|
+
|
|
|
+Let's test our application. At the end of the top-level ``CMakeLists.txt``
|
|
|
+file we first need to enable testing with the
|
|
|
+:command:`enable_testing` command.
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 5: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/CMakeLists.txt
|
|
|
+ :caption: TODO 5: CMakeLists.txt
|
|
|
+ :name: CMakeLists.txt-enable_testing
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # enable testing
|
|
|
+ :end-before: # does the application run
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+With testing enabled, we will add a number of basic tests to verify
|
|
|
+that the application is working correctly. First, we create a test using
|
|
|
+:command:`add_test` which runs the ``Tutorial`` executable with the
|
|
|
+parameter 25 passed in. For this test, we are not going to check the
|
|
|
+executable's computed answer. This test will verify that
|
|
|
+application runs, does not segfault or otherwise crash, and has a zero
|
|
|
+return value. This is the basic form of a CTest test.
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 6: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/CMakeLists.txt
|
|
|
+ :caption: TODO 6: CMakeLists.txt
|
|
|
+ :name: CMakeLists.txt-test-runs
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # does the application run
|
|
|
+ :end-before: # does the usage message work
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+Next, let's use the :prop_test:`PASS_REGULAR_EXPRESSION` test property to
|
|
|
+verify that the output of the test contains certain strings. In this case,
|
|
|
+verifying that the usage message is printed when an incorrect number of
|
|
|
+arguments are provided.
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 7: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/CMakeLists.txt
|
|
|
+ :caption: TODO 7: CMakeLists.txt
|
|
|
+ :name: CMakeLists.txt-test-usage
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # does the usage message work?
|
|
|
+ :end-before: # define a function to simplify adding tests
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+The next test we will add verifies the computed value is truly the
|
|
|
+square root.
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 8: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. code-block:: cmake
|
|
|
+ :caption: TODO 8: CMakeLists.txt
|
|
|
+ :name: CMakeLists.txt-test-standard
|
|
|
+
|
|
|
+ add_test(NAME StandardUse COMMAND Tutorial 4)
|
|
|
+ set_tests_properties(StandardUse
|
|
|
+ PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2"
|
|
|
+ )
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|
|
|
+
|
|
|
+This one test is not enough to give us confidence that it will
|
|
|
+work for all values passed in. We should add more tests to verify this.
|
|
|
+To easily add more tests, we make a function called ``do_test`` that runs the
|
|
|
+application and verifies that the computed square root is correct for
|
|
|
+given input. For each invocation of ``do_test``, another test is added to
|
|
|
+the project with a name, input, and expected results based on the passed
|
|
|
+arguments.
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ <details><summary>TODO 9: Click to show/hide answer</summary>
|
|
|
+
|
|
|
+.. literalinclude:: Step6/CMakeLists.txt
|
|
|
+ :caption: TODO 9: CMakeLists.txt
|
|
|
+ :name: CMakeLists.txt-generalized-tests
|
|
|
+ :language: cmake
|
|
|
+ :start-after: # define a function to simplify adding tests
|
|
|
+
|
|
|
+.. raw:: html
|
|
|
+
|
|
|
+ </details>
|