From d47febcb179ef6b9c1f65748190bb84c990ef6b2 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Fri, 10 Mar 2017 15:42:42 +0100 Subject: [PATCH] Minor pytest maintenance (#702) * Add `pytest.ini` config file and set default options there instead of in `CMakeLists.txt` (command line arguments). * Change all output capture from `capfd` (filedescriptors) to `capsys` (Python's `sys.stdout` and `sys.stderr`). This avoids capturing low-level C errors, e.g. from the debug build of Python. * Set pytest minimum version to 3.0 to make it easier to use new features. Removed conditional use of `excinfo.match()`. * Clean up some leftover function-level `@pytest.requires_numpy`. --- tests/CMakeLists.txt | 14 +++++++++----- tests/conftest.py | 6 +++--- tests/pytest.ini | 7 +++++++ tests/test_buffers.py | 4 ++-- tests/test_kwargs_and_defaults.py | 6 ++---- 5 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 tests/pytest.ini diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cb2b0afc1..11be49e53 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -150,16 +150,20 @@ endif() # Make sure pytest is found or produce a fatal error if(NOT PYBIND11_PYTEST_FOUND) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import pytest" OUTPUT_QUIET ERROR_QUIET - RESULT_VARIABLE PYBIND11_EXEC_PYTHON_ERR) - if(PYBIND11_EXEC_PYTHON_ERR) - message(FATAL_ERROR "Running the tests requires pytest. Please install it manually (try: ${PYTHON_EXECUTABLE} -m pip install pytest)") + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import pytest; print(pytest.__version__)" + RESULT_VARIABLE pytest_not_found OUTPUT_VARIABLE pytest_version ERROR_QUIET) + if(pytest_not_found) + message(FATAL_ERROR "Running the tests requires pytest. Please install it manually" + " (try: ${PYTHON_EXECUTABLE} -m pip install pytest)") + elseif(pytest_version VERSION_LESS 3.0) + message(FATAL_ERROR "Running the tests requires pytest >= 3.0. Found: ${pytest_version}" + "Please update it (try: ${PYTHON_EXECUTABLE} -m pip install -U pytest)") endif() set(PYBIND11_PYTEST_FOUND TRUE CACHE INTERNAL "") endif() # A single command to compile and run the tests -add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest -rws --capture=sys ${PYBIND11_PYTEST_FILES} +add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_PYTEST_FILES} DEPENDS pybind11_tests WORKING_DIRECTORY ${testdir}) if(PYBIND11_TEST_OVERRIDE) diff --git a/tests/conftest.py b/tests/conftest.py index b69fd6cb2..5b08004e3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -103,9 +103,9 @@ class Capture(object): @pytest.fixture -def capture(capfd): - """Extended `capfd` with context manager and custom equality operators""" - return Capture(capfd) +def capture(capsys): + """Extended `capsys` with context manager and custom equality operators""" + return Capture(capsys) class SanitizedString(object): diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 000000000..401cbe0ad --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,7 @@ +[pytest] +minversion = 3.0 +addopts = + # show summary of skipped tests + -rs + # capture only Python print and C++ py::print, but not C output (low-level Python errors) + --capture=sys diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 956839c1c..24843d95a 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -1,11 +1,12 @@ import pytest from pybind11_tests import Matrix, ConstructorStats +pytestmark = pytest.requires_numpy + with pytest.suppress(ImportError): import numpy as np -@pytest.requires_numpy def test_from_python(): with pytest.raises(RuntimeError) as excinfo: Matrix(np.array([1, 2, 3])) # trying to assign a 1D array @@ -32,7 +33,6 @@ def test_from_python(): # PyPy: Memory leak in the "np.array(m, copy=False)" call # https://bitbucket.org/pypy/pypy/issues/2444 @pytest.unsupported_on_pypy -@pytest.requires_numpy def test_to_python(): m = Matrix(5, 5) diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py index 2b6b94f85..90f8489ed 100644 --- a/tests/test_kwargs_and_defaults.py +++ b/tests/test_kwargs_and_defaults.py @@ -34,10 +34,8 @@ def test_named_arguments(msg): with pytest.raises(TypeError) as excinfo: # noinspection PyArgumentList kw_func2(x=5, y=10, z=12) - if hasattr(excinfo, "match"): # (pytest <3.0 doesn't have `.match()`) - assert excinfo.match( - r'(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))' + - '{3}$') + assert excinfo.match( + r'(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))' + '{3}$') assert kw_func4() == "{13 17}" assert kw_func4(myList=[1, 2, 3]) == "{1 2 3}"