Search code examples
pythonpython-3.xcmakepytest

Running a pytest test from CMake where the test and sources are in different folders


I have a CMake based project that uses both C++ and python sources. Tests are added via add_test for all C++ tests in a folder structure like:

src
  mynamespace/foo.cpp
  mypyspace/mypkg/__init__.py
  mypyspace/mypkg/bar.py
test
  mynamespace/testFoo.cpp
  mypyspace/testBar.py

In testBar.py I have a import mypkg and want to run this with add_test(... COMMAND pytest WORKING_DIRECTORY .../test)

Of course it does not find my package, but I also do not want to install it (it is required to generate some stuff during build and is actively developed as part of the other sources).

What is the correct/preferred way of executing those tests?

Notes:

  • I don't want to move the sources out of src or tests out of test
  • set_tests_properties may set environment variables.

I think setting PYTHONPATH=.../src/mypyspace should work, but that would also ignore changes to the users PYTHONPATH.


Solution

  • There are 2 options:

    1. Use PYTHONPATH
    add_test (NAME python-tests
      COMMAND ${PYTHON_EXECUTABLE} -m pytest # Or just COMMAND pytest
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    )
    set_tests_properties(python-tests
        PROPERTIES ENVIRONMENT "PYTHONPATH=${PROJECT_SOURCE_DIR}/src/mypyspace:$ENV{PYTHONPATH}")
    
    1. Invoke inside of the src directory
    add_test (NAME python-tests
      COMMAND ${PYTHON_EXECUTABLE} -m pytest ${CMAKE_CURRENT_SOURCE_DIR}
      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/mypyspace
    )
    

    The first approach has the disadvantage, that the user might configure and later change its environment so that PYTHONPATH is different (e.g. loading modules in HPC clusters) and find that the tests incorrectly succeed.

    The 2nd is the most flexible one. It relies on information from https://docs.pytest.org/en/latest/pythonpath.html. Most important part:

    the [python -m pytest] call will add the current directory to sys.path.

    So we only have to set the current directory when running the tests to the source directory.

    Note: For other alternatives specific to unittest (the module) you may also find something in Running unittest with typical test directory structure