diff --git a/appveyor.yml b/appveyor.yml index 684b859c206b2..65e62f887554e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -72,7 +72,7 @@ install: - cmd: conda info -a # create our env - - cmd: conda create -n pandas python=%PYTHON_VERSION% cython pytest pytest-xdist + - cmd: conda create -n pandas python=%PYTHON_VERSION% cython pytest>=3.1.0 pytest-xdist - cmd: activate pandas - SET REQ=ci\requirements-%PYTHON_VERSION%_WIN.run - cmd: echo "installing requirements from %REQ%" diff --git a/ci/install_circle.sh b/ci/install_circle.sh index 00e14b10ebbd6..29ca69970104b 100755 --- a/ci/install_circle.sh +++ b/ci/install_circle.sh @@ -64,7 +64,7 @@ fi # create envbuild deps echo "[create env: ${REQ_BUILD}]" time conda create -n pandas -q --file=${REQ_BUILD} || exit 1 -time conda install -n pandas pytest || exit 1 +time conda install -n pandas pytest>=3.1.0 || exit 1 source activate pandas diff --git a/ci/install_travis.sh b/ci/install_travis.sh index df6969c7cc659..ad8f0bdd8a597 100755 --- a/ci/install_travis.sh +++ b/ci/install_travis.sh @@ -103,7 +103,7 @@ if [ -e ${REQ} ]; then time bash $REQ || exit 1 fi -time conda install -n pandas pytest +time conda install -n pandas pytest>=3.1.0 time pip install pytest-xdist if [ "$LINT" ]; then diff --git a/ci/requirements_all.txt b/ci/requirements_all.txt index de37ec4d20be4..b153b6989df86 100644 --- a/ci/requirements_all.txt +++ b/ci/requirements_all.txt @@ -1,4 +1,4 @@ -pytest +pytest>=3.1.0 pytest-cov pytest-xdist flake8 diff --git a/ci/requirements_dev.txt b/ci/requirements_dev.txt index 1e051802ec9f8..c7190c506ba18 100644 --- a/ci/requirements_dev.txt +++ b/ci/requirements_dev.txt @@ -2,6 +2,6 @@ python-dateutil pytz numpy cython -pytest +pytest>=3.1.0 pytest-cov flake8 diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst index b44d0f36b86a1..e172d0d2a71a2 100644 --- a/doc/source/contributing.rst +++ b/doc/source/contributing.rst @@ -598,6 +598,10 @@ Like many packages, *pandas* uses `pytest extensions in `numpy.testing `_. +.. note:: + + The earliest supported pytest version is 3.1.0. + Writing tests ~~~~~~~~~~~~~ @@ -654,7 +658,9 @@ Using ``pytest`` Here is an example of a self-contained set of tests that illustrate multiple features that we like to use. - functional style: tests are like ``test_*`` and *only* take arguments that are either fixtures or parameters +- ``pytest.mark`` can be used to set metadata on test functions, e.g. ``skip`` or ``xfail``. - using ``parametrize``: allow testing of multiple cases +- to set a mark on a parameter, ``pytest.param(..., marks=...)`` syntax should be used - ``fixture``, code for object construction, on a per-test basis - using bare ``assert`` for scalars and truth-testing - ``tm.assert_series_equal`` (and its counter part ``tm.assert_frame_equal``), for pandas object comparisons. @@ -673,6 +679,13 @@ We would name this file ``test_cool_feature.py`` and put in an appropriate place def test_dtypes(dtype): assert str(np.dtype(dtype)) == dtype + @pytest.mark.parametrize('dtype', ['float32', + pytest.param('int16', marks=pytest.mark.skip), + pytest.param('int32', + marks=pytest.mark.xfail(reason='to show how it works'))]) + def test_mark(dtype): + assert str(np.dtype(dtype)) == 'float32' + @pytest.fixture def series(): return pd.Series([1, 2, 3]) @@ -695,13 +708,16 @@ A test run of this yields ((pandas) bash-3.2$ pytest test_cool_feature.py -v =========================== test session starts =========================== - platform darwin -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 - collected 8 items + platform darwin -- Python 3.6.2, pytest-3.2.1, py-1.4.31, pluggy-0.4.0 + collected 11 items tester.py::test_dtypes[int8] PASSED tester.py::test_dtypes[int16] PASSED tester.py::test_dtypes[int32] PASSED tester.py::test_dtypes[int64] PASSED + tester.py::test_mark[float32] PASSED + tester.py::test_mark[int16] SKIPPED + tester.py::test_mark[int32] xfail tester.py::test_series[int8] PASSED tester.py::test_series[int16] PASSED tester.py::test_series[int32] PASSED @@ -714,8 +730,8 @@ Tests that we have ``parametrized`` are now accessible via the test name, for ex ((pandas) bash-3.2$ pytest test_cool_feature.py -v -k int8 =========================== test session starts =========================== - platform darwin -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 - collected 8 items + platform darwin -- Python 3.6.2, pytest-3.2.1, py-1.4.31, pluggy-0.4.0 + collected 11 items test_cool_feature.py::test_dtypes[int8] PASSED test_cool_feature.py::test_series[int8] PASSED diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 7fc091ebb1892..d2874b1606e72 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -38,13 +38,14 @@ @pytest.fixture(params=( - pytest.mark.skipif(engine == 'numexpr' and not _USE_NUMEXPR, - reason='numexpr enabled->{enabled}, ' - 'installed->{installed}'.format( - enabled=_USE_NUMEXPR, - installed=_NUMEXPR_INSTALLED))(engine) - for engine in _engines # noqa -)) + pytest.param(engine, + marks=pytest.mark.skipif( + engine == 'numexpr' and not _USE_NUMEXPR, + reason='numexpr enabled->{enabled}, ' + 'installed->{installed}'.format( + enabled=_USE_NUMEXPR, + installed=_NUMEXPR_INSTALLED))) + for engine in _engines)) # noqa def engine(request): return request.param diff --git a/pandas/tests/io/parser/test_network.py b/pandas/tests/io/parser/test_network.py index cfa60248605ad..3344243f8137a 100644 --- a/pandas/tests/io/parser/test_network.py +++ b/pandas/tests/io/parser/test_network.py @@ -23,8 +23,10 @@ def salaries_table(): @pytest.mark.parametrize( "compression,extension", [('gzip', '.gz'), ('bz2', '.bz2'), ('zip', '.zip'), - pytest.mark.skipif(not tm._check_if_lzma(), - reason='need backports.lzma to run')(('xz', '.xz'))]) + pytest.param('xz', '.xz', + marks=pytest.mark.skipif(not tm._check_if_lzma(), + reason='need backports.lzma ' + 'to run'))]) @pytest.mark.parametrize('mode', ['explicit', 'infer']) @pytest.mark.parametrize('engine', ['python', 'c']) def test_compressed_urls(salaries_table, compression, extension, mode, engine): diff --git a/pandas/tests/io/test_excel.py b/pandas/tests/io/test_excel.py index 856e8d6466526..92147b46097b8 100644 --- a/pandas/tests/io/test_excel.py +++ b/pandas/tests/io/test_excel.py @@ -2400,8 +2400,10 @@ def check_called(func): @pytest.mark.parametrize('engine', [ - pytest.mark.xfail('xlwt', reason='xlwt does not support ' - 'openpyxl-compatible style dicts'), + pytest.param('xlwt', + marks=pytest.mark.xfail(reason='xlwt does not support ' + 'openpyxl-compatible ' + 'style dicts')), 'xlsxwriter', 'openpyxl', ]) diff --git a/pandas/tests/io/test_parquet.py b/pandas/tests/io/test_parquet.py index ff0935c7dcc6f..78c72e2a05566 100644 --- a/pandas/tests/io/test_parquet.py +++ b/pandas/tests/io/test_parquet.py @@ -26,10 +26,14 @@ # setup engines & skips @pytest.fixture(params=[ - pytest.mark.skipif(not _HAVE_FASTPARQUET, - reason='fastparquet is not installed')('fastparquet'), - pytest.mark.skipif(not _HAVE_PYARROW, - reason='pyarrow is not installed')('pyarrow')]) + pytest.param('fastparquet', + marks=pytest.mark.skipif(not _HAVE_FASTPARQUET, + reason='fastparquet is ' + 'not installed')), + pytest.param('pyarrow', + marks=pytest.mark.skipif(not _HAVE_PYARROW, + reason='pyarrow is ' + 'not installed'))]) def engine(request): return request.param diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index d94e34c41786b..21a9b05d48126 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -530,8 +530,9 @@ def test_numpy_compat(self): @pytest.mark.parametrize( 'expander', - [1, pytest.mark.xfail( - reason='GH 16425 expanding with offset not supported')('1s')]) + [1, pytest.param('ls', marks=pytest.mark.xfail( + reason='GH 16425 expanding with ' + 'offset not supported'))]) def test_empty_df_expanding(self, expander): # GH 15819 Verifies that datetime and integer expanding windows can be # applied to empty DataFrames