From 9c1cb0774b08828a88222febe431143301e1bacc Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sat, 18 Feb 2023 22:26:14 +0100 Subject: [PATCH 01/11] use pathlib.Path fixes #7 --- .gitignore | 3 + .travis.yml | 6 +- CHANGELOG.rst | 12 +- Makefile | 26 +- README.rst | 695 ++++++++++++++--------- docs/readme/README.rst | 218 +++++++ docs/readme/conf.py | 8 + pytest_datafiles.py | 82 ++- setup.py | 16 +- src/pytest_datafiles/__init__.py | 0 tests/__init__.py | 0 tests/conftest.py | 3 + tests/examples/__init__.py | 0 tests/examples/_fixture_files/dir1/fileA | 1 + tests/examples/_fixture_files/dir1/fileB | 1 + tests/examples/_fixture_files/dir2/fileA | 1 + tests/examples/_fixture_files/dir2/fileB | 1 + tests/examples/_fixture_files/dir3/fileA | 1 + tests/examples/_fixture_files/dir3/fileB | 1 + tests/examples/conftest.py | 31 + tests/examples/test_example_1.py | 20 + tests/examples/test_example_2.py | 50 ++ tests/examples/test_example_3.py | 45 ++ tests/examples/test_example_4.py | 98 ++++ tests/examples/test_example_5.py | 18 + tests/examples/test_example_upgradev3.py | 53 ++ tests/examples/test_files/img1.jpg | 0 tests/examples/test_files/img2.jpg | 0 tests/examples/test_files/img3.jpg | 0 tests/examples/test_files/img4.jpg | 0 tests/examples/test_files/img5.jpg | 0 tests/examples/test_files/img6.jpg | 0 tests/examples/test_files/img7.jpg | 0 tests/examples/test_files/img8.jpg | 0 tests/test_pytest_datafiles.py | 232 ++++---- tox.ini | 26 +- 36 files changed, 1197 insertions(+), 451 deletions(-) create mode 100644 docs/readme/README.rst create mode 100644 docs/readme/conf.py create mode 100644 src/pytest_datafiles/__init__.py create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/examples/__init__.py create mode 100644 tests/examples/_fixture_files/dir1/fileA create mode 100644 tests/examples/_fixture_files/dir1/fileB create mode 100644 tests/examples/_fixture_files/dir2/fileA create mode 100644 tests/examples/_fixture_files/dir2/fileB create mode 100644 tests/examples/_fixture_files/dir3/fileA create mode 100644 tests/examples/_fixture_files/dir3/fileB create mode 100644 tests/examples/conftest.py create mode 100644 tests/examples/test_example_1.py create mode 100644 tests/examples/test_example_2.py create mode 100644 tests/examples/test_example_3.py create mode 100644 tests/examples/test_example_4.py create mode 100644 tests/examples/test_example_5.py create mode 100644 tests/examples/test_example_upgradev3.py create mode 100644 tests/examples/test_files/img1.jpg create mode 100644 tests/examples/test_files/img2.jpg create mode 100644 tests/examples/test_files/img3.jpg create mode 100644 tests/examples/test_files/img4.jpg create mode 100644 tests/examples/test_files/img5.jpg create mode 100644 tests/examples/test_files/img6.jpg create mode 100644 tests/examples/test_files/img7.jpg create mode 100644 tests/examples/test_files/img8.jpg diff --git a/.gitignore b/.gitignore index 25f71b9..6b9d3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ build/ dist/ htmlcov/ pytest_datafiles.egg-info/ +.doctrees/ +.idea/ +.venv diff --git a/.travis.yml b/.travis.yml index 432e8dc..6b5b370 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,12 @@ language: python python: - - 2.7 - - 3.4 - - 3.5 - 3.6 - 3.7 - 3.8 + - 3.9 + - 3.10 + - 3.11 - pypy install: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6fdf021..24c3b85 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,14 @@ Removed Fixed Security +`3.0`_ +~~~~~~ + +Changed + +* BREAKING CHANGE: Using `pathlib.Path` instead of `py.path` (`#7`_) +* BREAKING CHANGE: Removed support for Python 2.7 and Python 3 <= 3.6 + `2.0.1`_ ~~~~~~~~ @@ -74,7 +82,8 @@ Added function -.. _`Unreleased`: https://github.com/omarkohl/pytest-datafiles/compare/2.0.1...master +.. _`Unreleased`: https://github.com/omarkohl/pytest-datafiles/compare/3.0...master +.. _`3.0`: https://github.com/omarkohl/pytest-datafiles/compare/2.0.1...3.0 .. _`2.0.1`: https://github.com/omarkohl/pytest-datafiles/compare/2.0...2.0.1 .. _`2.0`: https://github.com/omarkohl/pytest-datafiles/compare/1.0...2.0 .. _`1.0`: https://github.com/omarkohl/pytest-datafiles/compare/0.2...1.0 @@ -84,6 +93,7 @@ Added .. _`#1`: https://github.com/omarkohl/pytest-datafiles/issues/1 .. _`#2`: https://github.com/omarkohl/pytest-datafiles/issues/2 +.. _`#7`: https://github.com/omarkohl/pytest-datafiles/issues/7 .. _`#18`: https://github.com/omarkohl/pytest-datafiles/issues/18 diff --git a/Makefile b/Makefile index 01bab1f..dbabb4f 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,11 @@ help: @echo "clean-pyc Remove Python file artifacts" @echo "clean-test Remove test and coverage artifacts" @echo "lint Check style with Flake8 and Pylint" - @echo "test Run tests quickly with Python 3.5" + @echo "test Run tests quickly with Python 3.11" @echo "test-all Run tests on every Python version with tox" @echo "coverage Check code coverage quickly with Python 3" @echo "dist Package" + @echo "README.rst Generate README.rst from docs/readme" clean: clean-build clean-pyc clean-test @@ -31,20 +32,33 @@ clean-test: rm -f .coverage rm -fr htmlcov/ +all: lint test-all coverage dist readme + lint: tox -e lint -test: - tox -e py35 +test: test-example | test-quick + +test-quick: + tox -e py311 + +test-all: test-example | test-all-env -test-all: +test-all-env: tox +test-example: + tox -e examples + coverage: tox -e coverage - xdg-open htmlcov/index.html + command -v xdg-open && xdg-open htmlcov/index.html || true -dist: clean +dist: readme | clean python3 setup.py sdist python3 setup.py bdist_wheel ls -l dist + +readme: + touch README.rst + tox -e doc diff --git a/README.rst b/README.rst index fe7f95d..ece31ee 100644 --- a/README.rst +++ b/README.rst @@ -1,334 +1,503 @@ -================ + pytest-datafiles -================ +**************** -.. image:: https://img.shields.io/travis/omarkohl/pytest-datafiles.svg - :target: https://travis-ci.org/omarkohl/pytest-datafiles +https://travis-ci.org/omarkohl/pytest-datafileshttps://coveralls.io/github/omarkohl/pytest-datafiles?branch=masterhttps://pypi.python.org/pypi/pytest-datafileshttps://codeclimate.com/github/omarkohl/pytest-datafiles +`pytest `_ plugin to +create a `tmp_path `_ +containing a preconfigured set of files and/or directories. -.. image:: https://coveralls.io/repos/omarkohl/pytest-datafiles/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/omarkohl/pytest-datafiles?branch=master +**Note about maintenance:** This project is maintained and bug reports +or pull requests will be addressed. There is little activity because +it simply works and no changes are required. -.. image:: https://img.shields.io/pypi/v/pytest-datafiles.svg - :target: https://pypi.python.org/pypi/pytest-datafiles +Features +======== +This plugin allows you to specify one or several files/directories +that are copied to a temporary directory (`tmp_path +`_) before the +execution of the test. This means the original files are not modified +and every test runs on its own version of the same files. -.. image:: https://codeclimate.com/github/omarkohl/pytest-datafiles/badges/gpa.svg - :target: https://codeclimate.com/github/omarkohl/pytest-datafiles - :alt: Code Climate +Files/directories can be specified either as *strings* or as +*pathlib.Path* objects. +To take advantage of the *datafiles* fixture in a test function, add +*datafiles* as one of the test function parameters (per usual with +`pytest `_ fixtures) +and decorate the test function with *@pytest.mark.datafiles(file1, +file2, dir1, dir2, …)*. See the examples below. -`pytest`_ plugin to create a `tmpdir`_ containing a preconfigured set of -files and/or directories. +The *datafiles* variable in your test function is a pathlib.Path +object (`tmp_path `_) +where the copied files are located. Under Linux systems this will most +likely be some subdirectory of */tmp/*. -**Note about maintenance:** This project is maintained and bug reports or pull -requests will be addressed. There is little activity because it simply works and -no changes are required. -Features --------- +Options +======= -This plugin allows you to specify one or several files/directories that are -copied to a temporary directory (`tmpdir`_) before the execution of the test. -This means the original files are not modified and every test runs on its own -version of the same files. +The following options can be specified as keyword arguments (kwargs) +to the *@pytest.mark.datafiles* decorator function: -Files/directories can be specified either as *strings* or as *py.path* objects. +* **keep_top_dir:** For all parameters that represent directories, + keep that directory instead of only (recursively) copying its + content. Possible values are *True* or *False*. *False* is the + default value. -To take advantage of the *datafiles* fixture in a test function, add -*datafiles* as one of the test function parameters (per usual with `pytest`_ -fixtures) and decorate the test function with *@pytest.mark.datafiles(file1, -file2, dir1, dir2, ...)*. See the examples below. +* **on_duplicate:** Specify the action to take when duplicate + files/directories are found. Possible values are: *exception*, + *ignore* and *replace*. The default value is *exception*. -The *datafiles* variable in your test function is a py.path object -(`tmpdir`_) where the copied files are located. Under Linux systems this -will most likely be some subdirectory of */tmp/*. + * *exception:* An exception is raised instead of copying the + duplicate file/directory. + * *ignore:* The second (or subsequent) files/directories with the + same name as the first one are simply ignored (i.e., the first + file/directory with the duplicate name is kept). -Options -------- - -The following options can be specified as keyword arguments (kwargs) to the -*@pytest.mark.datafiles* decorator function: - -- **keep_top_dir:** For all parameters that represent directories, keep that - directory instead of only (recursively) copying its content. Possible values - are *True* or *False*. *False* is the default value. -- **on_duplicate:** Specify the action to take when duplicate files/directories - are found. Possible values are: *exception*, *ignore* and *replace*. The - default value is *exception*. - - - *exception:* An exception is raised instead of copying the duplicate - file/directory. - - *ignore:* The second (or subsequent) files/directories with the same name - as the first one are simply ignored (i.e., the first file/directory with the - duplicate name is kept). - - *replace:* The second (or subsequent) files/directories with the same name - replace the previous ones (i.e., the last file/directory with the duplicate - name is kept). + * *replace:* The second (or subsequent) files/directories with the + same name replace the previous ones (i.e., the last + file/directory with the duplicate name is kept). See below for some *examples*. Installation ------------- +============ + +.. code:: bash + + pip install pytest-datafiles + + +Upgrade to 3.0 +============== + +Version 3 now uses `tmp_path +`_, resulting in +*pathlib.Path* objects instead of *py.path*. + +Your tests may need to be adjusted. + +.. code:: python + + """Upgrade to v3.""" + import os + + import pytest + import py + -.. code-block:: bash + @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + def test_convert_to_pypath(datafiles): + """Convert `datafiles` to `py.path` in place. - pip install pytest-datafiles + Changing the type back to py.path - should be avoided! + + Better to update the tests to make use of `pathlib`. + """ + + # changing the type back to py.path - should be avoided + datafiles = py.path.local(str(datafiles)) + + # code remains as before + assert len(datafiles.listdir()) == 1 + assert (datafiles / 'film1.mp4').check(file=1) + + + @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + def test_update_to_pathlib(datafiles): + """Upgrade code to use `pathlib`. + + Some examples showing `pathlib` style. + """ + + # For demo purpose: this is the old-style + pypath_datafiles = py.path.local(str(datafiles)) + + # old style + assert len(pypath_datafiles.listdir()) == 1 + assert (pypath_datafiles / 'film1.mp4').check(file=1) + + # new style # pylint: disable=R0801 + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'film1.mp4').is_file() + + + @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + def test_keep_using_str(datafiles): + """Keep using plain `os`. + + Nothing changes. + """ + + path = str(datafiles) + assert len(os.listdir(path)) == 1 + assert os.path.isfile(os.path.join(path, 'film1.mp4')) Usage ------ +===== + +These examples can also be found in *src/pytest_datafiles/examples*. + Example 1 -~~~~~~~~~ +--------- + +One possible use case is when you are running tests on very big files +that are not included or packaged with your tests. For example, your +test files are large video files stored under */opt/big_files/* . You +don’t want your tests modifying the original files, but the files are +required by the tests. You can reference these data files in your test +method as follows: + +.. code:: python + + """Example: Reference files anywhere """ + import os + import pytest -One possible use case is when you are running tests on very big files that are -not included or packaged with your tests. For example, your test files are -large video files stored under */opt/big_files/* . You don't want your tests modifying -the original files, but the files are required by the tests. You can reference these -data files in your test method as follows: -.. code-block:: python + @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + def test_fast_forward(datafiles): + """Work with a copy of the big file.""" + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'film1.mp4').is_file() + # assert some_operation(datafiles / 'film1.mp4') == expected_result - import os - import pytest - @pytest.mark.datafiles('/opt/big_files/film1.mp4') - def test_fast_forward(datafiles): - path = str(datafiles) # Convert from py.path object to path (str) - assert len(os.listdir(path)) == 1 - assert os.path.isfile(os.path.join(path, 'film1.mp4')) - #assert some_operation(os.path.join(path, 'film1.mp4')) == expected_result + @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + def test_fast_forward_alternative(datafiles): + """Work with a copy of the bigfile, using `str`.""" + path = str(datafiles) # Convert from py.path object to path (str) + assert len(os.listdir(path)) == 1 + assert os.path.isfile(os.path.join(path, 'film1.mp4')) + # assert some_operation(os.path.join(path, 'film1.mp4')) == expected_result - # Using py.path syntax - assert len(datafiles.listdir()) == 1 - assert (datafiles / 'film1.mp4').check(file=1) Example 2 -~~~~~~~~~ - -Now for another use case: let's say in the directory where your tests are located, you -place a directory named *test_files*. Here you have a lot of images you want to run tests -on. By using this plugin, you make sure the original files under *test_files* are not -modified by every test. - -.. code-block:: python - - import os - import pytest - - FIXTURE_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - 'test_files', - ) - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'img1.jpg'), - os.path.join(FIXTURE_DIR, 'img2.jpg'), - os.path.join(FIXTURE_DIR, 'img3.jpg'), - ) - def test_find_borders(datafiles): - for img in datafiles.listdir(): - print(img) - #assert process(img) == some_expected_value - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'img4.jpg'), - os.path.join(FIXTURE_DIR, 'img5.jpg'), - ) - def test_brightness(datafiles): - for img in datafiles.listdir(): - print(img) - #assert process(img) == some_expected_value +--------- + +Now for another use case: let’s say in the directory where your tests +are located, you place a directory named *test_files*. Here you have a +lot of images you want to run tests on. By using this plugin, you make +sure the original files under *test_files* are not modified by every +test. + +.. code:: python + + """Example: make a subset of the files in a dir available.""" + from pathlib import Path + + import pytest + + # Dir containing 8 files + FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', + ) + def test_find_borders(datafiles): + """Work with a copy of only 3 files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + # and only the referenced files are available + assert img.name != 'img4.jpg' + + assert len(list(datafiles.iterdir())) == 3 + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'img4.jpg', + FIXTURE_DIR / 'img5.jpg', + ) + def test_brightness(datafiles): + """Work with a copy of only 2 files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + # and only the referenced files are available + assert img.name != 'img3.jpg' + + assert len(list(datafiles.iterdir())) == 2 + + + @pytest.mark.datafiles(FIXTURE_DIR) + def test_resize(datafiles): + """Work with a copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 + Example 3 -~~~~~~~~~ - -If all (or many) of your tests rely on the same files it can be easier to -define one decorator beforehand and apply it to every test like this example: - -.. code-block:: python - - import os - import pytest - - FIXTURE_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - 'test_files', - ) - - ALL_IMGS = pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'img1.jpg'), - os.path.join(FIXTURE_DIR, 'img2.jpg'), - os.path.join(FIXTURE_DIR, 'img3.jpg'), - os.path.join(FIXTURE_DIR, 'img4.jpg'), - os.path.join(FIXTURE_DIR, 'img5.jpg'), - os.path.join(FIXTURE_DIR, 'img6.jpg'), - os.path.join(FIXTURE_DIR, 'img7.jpg'), - os.path.join(FIXTURE_DIR, 'img8.jpg'), - ) - - @ALL_IMGS - def test_something1(datafiles): - for img in datafiles.listdir(): - print(img) - #assert process(img) == some_expected_value - - @ALL_IMGS - def test_something2(datafiles): - for img in datafiles.listdir(): - print(img) - #assert process(img) == some_expected_value +--------- + +If all (or many) of your tests rely on the same files it can be easier +to define one decorator beforehand and apply it to every test like +this example: + +.. code:: python + + """Example: re-use file selection.""" + from pathlib import Path + + import pytest + + FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' + + ALL_IMGS = pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', + FIXTURE_DIR / 'img4.jpg', + FIXTURE_DIR / 'img5.jpg', + FIXTURE_DIR / 'img6.jpg', + FIXTURE_DIR / 'img7.jpg', + FIXTURE_DIR / 'img8.jpg', + ) + + + @ALL_IMGS + def test_something1(datafiles): + """Work with copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 + + # we can do something destructive + (datafiles / 'img3.jpg').unlink() + assert len(list(datafiles.iterdir())) == 7 + + + @ALL_IMGS + def test_something2(datafiles): + """Work with copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 + + # we can do something destructive + (datafiles / 'img1.jpg').unlink() + assert len(list(datafiles.iterdir())) == 7 + Example 4 -~~~~~~~~~ - -Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the files -(*fileA* and *fileB*). - -This example clarifies the options **on_duplicate** and **keep_top_dir**. - -.. code-block:: python - - import os - import pytest - - FIXTURE_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - '_fixture_files', - ) - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir1'), - os.path.join(FIXTURE_DIR, 'dir2'), - os.path.join(FIXTURE_DIR, 'dir3'), - on_duplicate='ignore', - ) - def test_dir_ignore(datafiles): - # datafiles.listdir() will list fileA and fileB originally from dir1 - pass - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir1'), - os.path.join(FIXTURE_DIR, 'dir2'), - os.path.join(FIXTURE_DIR, 'dir3'), - on_duplicate='replace', - ) - def test_dir_replace(datafiles): - # datafiles.listdir() will list fileA and fileB originally from dir3 - pass - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir1'), - os.path.join(FIXTURE_DIR, 'dir2'), - os.path.join(FIXTURE_DIR, 'dir3'), - # on_duplicate='exception' is the default and does not need to be - # specified - ) - def test_dir_exception(datafiles): - # An exception will be raised because of duplicate filename fileA - pass - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir1'), - os.path.join(FIXTURE_DIR, 'dir2'), - os.path.join(FIXTURE_DIR, 'dir3'), - keep_top_dir=True, - ) - def test_dir_keep_top_dir(datafiles): - # datafiles.listdir() will list dir1, dir2 and dir3 (each containing - # fileA and fileB) - pass +--------- + +Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each +containing the files (*fileA* and *fileB*). + +This example clarifies the options **on_duplicate** and +**keep_top_dir**. + +.. code:: python + + """Example: files with same names.""" + from pathlib import Path + + import pytest + + FIXTURE_DIR = Path(__file__).parent.resolve() / '_fixture_files' + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + on_duplicate='ignore', + ) + def test_dir_ignore(datafiles): + """Use files from dir1 (first dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '1a\n' + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir3', + on_duplicate='ignore', + ) + def test_dir_ignore2(datafiles): + """Use files from dir2 (first dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '2a\n' + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + on_duplicate='overwrite', + ) + def test_dir_overwrite(datafiles): + """Use files from dir3 (last dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '3a\n' + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + # on_duplicate='exception' is the default + ) + @pytest.mark.skip( + reason='will raise an exception that cannot be caught in the test itself' + ) + def test_dir_exception(datafiles): # pylint: disable=W0613 + """Raise exception because of duplicate filename fileA.""" + assert False + + + def test_dir_exception_generated(testdir): + """Raise exception because of duplicate filename fileA.""" + testdir.makepyfile(f''' + import pytest + from pathlib import Path + + FIXTURE_DIR = Path('{FIXTURE_DIR}') + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + # on_duplicate='exception' is the default + ) + def test_exception(datafiles): + assert True + ''') + result = testdir.runpytest('-s') + result.stdout.fnmatch_lines([ + 'E*ValueError: *already exists*', + ]) + + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + keep_top_dir=True, + ) + def test_dir_keep_top_dir(datafiles): + """Use all files.""" + # 3 subdirs + assert len(list(datafiles.iterdir())) == 3 + # 3 subdirs with each 2 files: 3 + 3*2 + assert len(list(datafiles.glob('**/*'))) == 9 + assert (datafiles / 'dir3' / 'fileA').exists() + assert (datafiles / 'dir3' / 'fileA').read_text() == '3a\n' + Example 5 -~~~~~~~~~ +--------- -You can also use a py.path object instead of str paths. +You can also use a str paths. -.. code-block:: python +.. code:: python - import os - import py - import pytest + """Example: use `str` paths.""" + import os + import pytest - _dir = os.path.dirname(os.path.realpath(__file__)) - FIXTURE_DIR = py.path.local(_dir) / 'test_files' + FIXTURE_DIR = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'test_files' + ) - @pytest.mark.datafiles( - FIXTURE_DIR / 'img1.jpg', - FIXTURE_DIR / 'img2.jpg', - FIXTURE_DIR / 'img3.jpg', - ) - def test_fast_forward(datafiles): - assert len(datafiles.listdir()) == 3 + + @pytest.mark.datafiles( + os.path.join(FIXTURE_DIR, 'img1.jpg'), + os.path.join(FIXTURE_DIR, 'img2.jpg'), + os.path.join(FIXTURE_DIR, 'img3.jpg'), + ) + def test_str(datafiles): + """Work with `str`.""" + assert len(list(datafiles.iterdir())) == 3 Contributing ------------- +============ -Contributions are very welcome. Tests can be run with `tox`_. Please -ensure the coverage stays at least the same before you submit a pull -request. +Contributions are very welcome. Tests can be run with `tox +`_. Please ensure the coverage +stays at least the same before you submit a pull request. -To create and upload a new package first update the version number and then: +To create and upload a new package first update the version number and +then: -.. code-block:: bash +.. code:: bash - pip3 install --user -U twine - make clean - make dist - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - # Verify the package is usable - virtualenv -p python3 test-venv - test-venv/bin/pip install pytest - test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles - # Create some test_example.py (e.g. with one of the examples above) - test-venv/bin/pytest test_example.py - # Set the git tag for final release - git tag -a 2.0 - git push --tags - # Upload the package for final release - twine upload dist/* + pip3 install --user -U twine + make clean + make dist + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + # Verify the package is usable + virtualenv -p python3 test-venv + test-venv/bin/pip install pytest + test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles + # Create some test_example.py (e.g. with one of the examples above) + test-venv/bin/pytest test_example.py + # Set the git tag for final release + git tag -a 3.0 + git push --tags + # Upload the package for final release + twine upload dist/* -Finally create a release on GitHub and add the packages from dist/* to it. +Finally create a release on GitHub and add the packages from dist/* to +it. -Of course this will only work if you have the necessary PyPI credentials for -this package. +Of course this will only work if you have the necessary PyPI +credentials for this package. License -------- +======= -Distributed under the terms of the `MIT license`_, "pytest-datafiles" is -free and open source software. +Distributed under the terms of the `MIT license +`_, “pytest-datafiles” is free and +open source software. Issues ------- +====== -If you encounter any problems, please `file an issue`_ along with a +If you encounter any problems, please `file an issue +`_ along with a detailed description. Acknowledgements ----------------- - -Thanks to `@flub`_ for the idea to use `pytest`_ marks to solve the -problem this plugin is trying to solve. - -Some ideas to improve this project were taken from the `Cookiecutter`_ -templates `cookiecutter-pypackage`_ and `cookiecutter-pytest-plugin`_. +================ +Thanks to `@flub `_ for the idea to use +`pytest `_ marks to +solve the problem this plugin is trying to solve. -.. _`pytest`: https://docs.pytest.org/en/latest/contents.html -.. _`tmpdir`: https://docs.pytest.org/en/latest/tmpdir.html -.. _`tox`: https://tox.readthedocs.org/en/latest/ -.. _`MIT License`: http://opensource.org/licenses/MIT -.. _`file an issue`: https://github.com/omarkohl/pytest-datafiles/issues -.. _`@flub`: https://github.com/flub -.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter -.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage -.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin +Some ideas to improve this project were taken from the `Cookiecutter +`_ templates +`cookiecutter-pypackage +`_ and +`cookiecutter-pytest-plugin +`_. diff --git a/docs/readme/README.rst b/docs/readme/README.rst new file mode 100644 index 0000000..3462d78 --- /dev/null +++ b/docs/readme/README.rst @@ -0,0 +1,218 @@ +.. This file will be rendered to teh README.rst in the root + +================ +pytest-datafiles +================ + +.. image:: https://img.shields.io/travis/omarkohl/pytest-datafiles.svg + :target: https://travis-ci.org/omarkohl/pytest-datafiles + + +.. image:: https://coveralls.io/repos/omarkohl/pytest-datafiles/badge.svg?branch=master&service=github + :target: https://coveralls.io/github/omarkohl/pytest-datafiles?branch=master + + +.. image:: https://img.shields.io/pypi/v/pytest-datafiles.svg + :target: https://pypi.python.org/pypi/pytest-datafiles + + +.. image:: https://codeclimate.com/github/omarkohl/pytest-datafiles/badges/gpa.svg + :target: https://codeclimate.com/github/omarkohl/pytest-datafiles + :alt: Code Climate + + +`pytest`_ plugin to create a `tmp_path`_ containing a preconfigured set of +files and/or directories. + +**Note about maintenance:** This project is maintained and bug reports or pull +requests will be addressed. There is little activity because it simply works and +no changes are required. + +Features +-------- + +This plugin allows you to specify one or several files/directories that are +copied to a temporary directory (`tmp_path`_) before the execution of the test. +This means the original files are not modified and every test runs on its own +version of the same files. + +Files/directories can be specified either as *strings* or as *pathlib.Path* objects. + +To take advantage of the *datafiles* fixture in a test function, add +*datafiles* as one of the test function parameters (per usual with `pytest`_ +fixtures) and decorate the test function with *@pytest.mark.datafiles(file1, +file2, dir1, dir2, ...)*. See the examples below. + +The *datafiles* variable in your test function is a pathlib.Path object +(`tmp_path`_) where the copied files are located. Under Linux systems this +will most likely be some subdirectory of */tmp/*. + + +Options +------- + +The following options can be specified as keyword arguments (kwargs) to the +*@pytest.mark.datafiles* decorator function: + +- **keep_top_dir:** For all parameters that represent directories, keep that + directory instead of only (recursively) copying its content. Possible values + are *True* or *False*. *False* is the default value. +- **on_duplicate:** Specify the action to take when duplicate files/directories + are found. Possible values are: *exception*, *ignore* and *replace*. The + default value is *exception*. + + - *exception:* An exception is raised instead of copying the duplicate + file/directory. + - *ignore:* The second (or subsequent) files/directories with the same name + as the first one are simply ignored (i.e., the first file/directory with the + duplicate name is kept). + - *replace:* The second (or subsequent) files/directories with the same name + replace the previous ones (i.e., the last file/directory with the duplicate + name is kept). + +See below for some *examples*. + + +Installation +------------ + +.. code-block:: bash + + pip install pytest-datafiles + + +Upgrade to 3.0 +-------------- + +Version 3 now uses `tmp_path`_, resulting in `pathlib.Path` objects +instead of `py.path`. + +Your tests may need to be adjusted. + +.. literalinclude:: ../../tests/examples/test_example_upgradev3.py + :language: python + + +Usage +----- + +These examples can also be found in `src/pytest_datafiles/examples`. + +Example 1 +~~~~~~~~~ + +One possible use case is when you are running tests on very big files that are +not included or packaged with your tests. For example, your test files are +large video files stored under */opt/big_files/* . You don't want your tests modifying +the original files, but the files are required by the tests. You can reference these +data files in your test method as follows: + +.. literalinclude:: ../../tests/examples/test_example_1.py + :language: python + +Example 2 +~~~~~~~~~ + +Now for another use case: let's say in the directory where your tests are located, you +place a directory named *test_files*. Here you have a lot of images you want to run tests +on. By using this plugin, you make sure the original files under *test_files* are not +modified by every test. + +.. literalinclude:: ../../tests/examples/test_example_2.py + :language: python + +Example 3 +~~~~~~~~~ + +If all (or many) of your tests rely on the same files it can be easier to +define one decorator beforehand and apply it to every test like this example: + +.. literalinclude:: ../../tests/examples/test_example_3.py + :language: python + +Example 4 +~~~~~~~~~ + +Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the files +(*fileA* and *fileB*). + +This example clarifies the options **on_duplicate** and **keep_top_dir**. + +.. literalinclude:: ../../tests/examples/test_example_4.py + :language: python + +Example 5 +~~~~~~~~~ + +You can also use a str paths. + +.. literalinclude:: ../../tests/examples/test_example_5.py + :language: python + + +Contributing +------------ + +Contributions are very welcome. Tests can be run with `tox`_. Please +ensure the coverage stays at least the same before you submit a pull +request. + +To create and upload a new package first update the version number and then: + +.. code-block:: bash + + pip3 install --user -U twine + make clean + make dist + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + # Verify the package is usable + virtualenv -p python3 test-venv + test-venv/bin/pip install pytest + test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles + # Create some test_example.py (e.g. with one of the examples above) + test-venv/bin/pytest test_example.py + # Set the git tag for final release + git tag -a 3.0 + git push --tags + # Upload the package for final release + twine upload dist/* + +Finally create a release on GitHub and add the packages from dist/* to it. + +Of course this will only work if you have the necessary PyPI credentials for +this package. + + +License +------- + +Distributed under the terms of the `MIT license`_, "pytest-datafiles" is +free and open source software. + + +Issues +------ + +If you encounter any problems, please `file an issue`_ along with a +detailed description. + + +Acknowledgements +---------------- + +Thanks to `@flub`_ for the idea to use `pytest`_ marks to solve the +problem this plugin is trying to solve. + +Some ideas to improve this project were taken from the `Cookiecutter`_ +templates `cookiecutter-pypackage`_ and `cookiecutter-pytest-plugin`_. + + +.. _`pytest`: https://docs.pytest.org/en/latest/contents.html +.. _`tmp_path`: https://docs.pytest.org/en/latest/tmp_path.html +.. _`tox`: https://tox.readthedocs.org/en/latest/ +.. _`MIT License`: http://opensource.org/licenses/MIT +.. _`file an issue`: https://github.com/omarkohl/pytest-datafiles/issues +.. _`@flub`: https://github.com/flub +.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter +.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage +.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin diff --git a/docs/readme/conf.py b/docs/readme/conf.py new file mode 100644 index 0000000..43f5d30 --- /dev/null +++ b/docs/readme/conf.py @@ -0,0 +1,8 @@ +"""Sphinx configuration.""" +from pathlib import Path + +extensions = [ + 'sphinxcontrib.restbuilder', +] + +master_doc = Path(__file__).parent.name.upper() diff --git a/pytest_datafiles.py b/pytest_datafiles.py index 7e3a008..331c6ba 100644 --- a/pytest_datafiles.py +++ b/pytest_datafiles.py @@ -1,64 +1,50 @@ """ Module containing a 'datafiles' fixture for pytest Tests. """ +import shutil +from pathlib import Path +from typing import List import pytest -from py import path # pylint: disable=E0611 from _pytest.config import Config def pytest_configure(config: Config) -> None: + """Perform initial configuration.""" config.addinivalue_line( "markers", - "datafiles(path, ..., *, keep_top_dir=False, on_duplicate='exception'): " - "Paths to copy to tmpdir before the test. 'keep_top_dir': For all " - "parameters that represent directories, keep that directory instead of " - "only (recursively) copying its content (default is False). Use the " - "option 'on_duplicate' to specify the action to take when duplicate " - "files/directories are found. Possible values are: exception, ignore and " - "replace. The default value is exception.", + "datafiles(path, ..., *, keep_top_dir=False, " + "on_duplicate='exception'): Paths to copy to tmpdir before the test. " + "'keep_top_dir': For all parameters that represent directories, keep " + "that directory instead of only (recursively) copying its content " + "(default is False). Use the option 'on_duplicate' to specify the " + "action to take when duplicate files/directories are found. Possible " + "values are: exception, ignore and replace. The default value is " + "exception.", ) -def _copy(src, target): - """ - Copies a single entry (file, dir) named 'src' to 'target'. Softlinks are - processed properly as well. - """ - if not src.exists(): - raise ValueError("'%s' does not exist!" % src) - - if src.isdir(): - src.copy(target / src.basename) - elif src.islink(): - (target / src.basename).mksymlinkto(src.realpath()) - else: # file - src.copy(target) - - -def _copy_all(entry_list, target_dir, on_duplicate): +def _copy_all(entry_list: List[Path], target_dir: Path, on_duplicate: str): """ Copies all entries (files, dirs) from 'entry_list' to 'target_dir' taking into account the 'on_duplicate' option (which defines what should happen if an entry already exists: raise an exception, overwrite it or ignore it). """ for entry in entry_list: - target_entry = target_dir / entry.basename + target_entry = target_dir / entry.name if not target_entry.exists() or on_duplicate == 'overwrite': - _copy(entry, target_dir) + if entry.is_file(): + shutil.copy(entry, target_entry, follow_symlinks=False) + else: + shutil.copytree(entry, target_entry, symlinks=True) elif on_duplicate == 'exception': - raise ValueError( - "'%s' already exists (src %s)" % ( - target_entry, - entry, - ) - ) + raise ValueError(f"'{target_entry}' already exists (src {entry})") else: # ignore continue -def _get_all_entries(entry_list, keep_top_dir): +def _get_all_entries(entry_list: List[str], keep_top_dir: bool) -> List[Path]: """ Returns a list of all entries (files, directories) that should be copied. The main purpose of this function is to evaluate 'keep_top_dir' and in case @@ -66,23 +52,23 @@ def _get_all_entries(entry_list, keep_top_dir): """ all_files = [] - entry_list = [path.local(entry) for entry in entry_list] + entry_list = [Path(entry) for entry in entry_list] if keep_top_dir: - all_files = entry_list - else: - for entry in entry_list: - if entry.isdir(): - all_files.extend(entry.listdir()) - else: - all_files.append(entry) + return entry_list + + for entry in entry_list: + if entry.is_dir(): + all_files.extend(entry.iterdir()) + else: + all_files.append(entry) return all_files @pytest.fixture -def datafiles(request, tmpdir): +def datafiles(request, tmp_path: Path) -> Path: """ - pytest fixture to define a 'tmpdir' containing files or directories + pytest fixture to define a 'tmp_path' containing files or directories specified with a 'datafiles' mark. """ entry_list = [] @@ -100,9 +86,9 @@ def datafiles(request, tmpdir): if keep_top_dir not in (True, False): raise ValueError("'keep_top_dir' must be True or False") if on_duplicate not in ('exception', 'ignore', 'overwrite'): - raise ValueError("'on_duplicate' must be 'exception', 'ignore' or " - "'overwrite'") + raise ValueError(f"'on_duplicate' must be 'exception', 'ignore' or " + f"'overwrite', got '{on_duplicate}'") all_entries = _get_all_entries(entry_list, keep_top_dir) - _copy_all(all_entries, tmpdir, on_duplicate) - return tmpdir + _copy_all(all_entries, tmp_path, on_duplicate) + return tmp_path diff --git a/setup.py b/setup.py index 1a9229d..af8d395 100755 --- a/setup.py +++ b/setup.py @@ -12,17 +12,15 @@ def _read(fname): DEPENDENCIES = [ - 'py', 'pytest>=3.6', ] -DESCRIPTION = ("py.test plugin to create a 'tmpdir' containing predefined " - "files/directories.") +DESCRIPTION = "py.test plugin to create a 'tmp_path' containing predefined files/directories." LONG_DESCRIPTION = _read('README.rst') + '\n\n' + _read('CHANGELOG.rst') setup( name='pytest-datafiles', - version='2.0.1', + version='3.0.0', py_modules=['pytest_datafiles'], url='https://github.com/omarkohl/pytest-datafiles', license='MIT', @@ -36,21 +34,21 @@ def _read(fname): long_description_content_type='text/x-rst', entry_points={ 'pytest11': ['pytest_datafiles = pytest_datafiles'], - }, - keywords='pytest datafiles tmpdir', + }, + keywords='pytest datafiles tmp_path', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Framework :: Pytest', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Topic :: Software Development :: Testing', ] ) diff --git a/src/pytest_datafiles/__init__.py b/src/pytest_datafiles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..810b03b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,3 @@ +# pylint: skip-file + +pytest_plugins = ['pytester'] diff --git a/tests/examples/__init__.py b/tests/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/_fixture_files/dir1/fileA b/tests/examples/_fixture_files/dir1/fileA new file mode 100644 index 0000000..a8994dc --- /dev/null +++ b/tests/examples/_fixture_files/dir1/fileA @@ -0,0 +1 @@ +1a diff --git a/tests/examples/_fixture_files/dir1/fileB b/tests/examples/_fixture_files/dir1/fileB new file mode 100644 index 0000000..6f8bafa --- /dev/null +++ b/tests/examples/_fixture_files/dir1/fileB @@ -0,0 +1 @@ +1b diff --git a/tests/examples/_fixture_files/dir2/fileA b/tests/examples/_fixture_files/dir2/fileA new file mode 100644 index 0000000..94226da --- /dev/null +++ b/tests/examples/_fixture_files/dir2/fileA @@ -0,0 +1 @@ +2a diff --git a/tests/examples/_fixture_files/dir2/fileB b/tests/examples/_fixture_files/dir2/fileB new file mode 100644 index 0000000..b8a4cf4 --- /dev/null +++ b/tests/examples/_fixture_files/dir2/fileB @@ -0,0 +1 @@ +2b diff --git a/tests/examples/_fixture_files/dir3/fileA b/tests/examples/_fixture_files/dir3/fileA new file mode 100644 index 0000000..31cd755 --- /dev/null +++ b/tests/examples/_fixture_files/dir3/fileA @@ -0,0 +1 @@ +3a diff --git a/tests/examples/_fixture_files/dir3/fileB b/tests/examples/_fixture_files/dir3/fileB new file mode 100644 index 0000000..f6fc7b7 --- /dev/null +++ b/tests/examples/_fixture_files/dir3/fileB @@ -0,0 +1 @@ +3b diff --git a/tests/examples/conftest.py b/tests/examples/conftest.py new file mode 100644 index 0000000..dbed544 --- /dev/null +++ b/tests/examples/conftest.py @@ -0,0 +1,31 @@ +# pylint: skip-file +import shutil +from pathlib import Path + +import pytest + + +def first_not_existing_parent(path: Path) -> Path: + parent = path.parent + if parent.exists(): + return path + return first_not_existing_parent(parent) + + +@pytest.fixture(scope="session") +def example_1(): + file = Path('/tmp/big_files/film1.mp4') + path = first_not_existing_parent(file) + print(f'found {path}') + + file.parent.mkdir(parents=True, exist_ok=True) + file.touch() + yield 1 + file.unlink() + if path.is_dir(): + shutil.rmtree(path) + + +@pytest.fixture(autouse=True) +def setup_examples(example_1): + pass diff --git a/tests/examples/test_example_1.py b/tests/examples/test_example_1.py new file mode 100644 index 0000000..5a933c4 --- /dev/null +++ b/tests/examples/test_example_1.py @@ -0,0 +1,20 @@ +"""Example: Reference files anywhere """ +import os +import pytest + + +@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +def test_fast_forward(datafiles): + """Work with a copy of the big file.""" + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'film1.mp4').is_file() + # assert some_operation(datafiles / 'film1.mp4') == expected_result + + +@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +def test_fast_forward_alternative(datafiles): + """Work with a copy of the bigfile, using `str`.""" + path = str(datafiles) # Convert from py.path object to path (str) + assert len(os.listdir(path)) == 1 + assert os.path.isfile(os.path.join(path, 'film1.mp4')) + # assert some_operation(os.path.join(path, 'film1.mp4')) == expected_result diff --git a/tests/examples/test_example_2.py b/tests/examples/test_example_2.py new file mode 100644 index 0000000..23b41d3 --- /dev/null +++ b/tests/examples/test_example_2.py @@ -0,0 +1,50 @@ +"""Example: make a subset of the files in a dir available.""" +from pathlib import Path + +import pytest + +# Dir containing 8 files +FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', +) +def test_find_borders(datafiles): + """Work with a copy of only 3 files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + # and only the referenced files are available + assert img.name != 'img4.jpg' + + assert len(list(datafiles.iterdir())) == 3 + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'img4.jpg', + FIXTURE_DIR / 'img5.jpg', +) +def test_brightness(datafiles): + """Work with a copy of only 2 files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + # and only the referenced files are available + assert img.name != 'img3.jpg' + + assert len(list(datafiles.iterdir())) == 2 + + +@pytest.mark.datafiles(FIXTURE_DIR) +def test_resize(datafiles): + """Work with a copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 diff --git a/tests/examples/test_example_3.py b/tests/examples/test_example_3.py new file mode 100644 index 0000000..2070d4c --- /dev/null +++ b/tests/examples/test_example_3.py @@ -0,0 +1,45 @@ +"""Example: re-use file selection.""" +from pathlib import Path + +import pytest + +FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' + +ALL_IMGS = pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', + FIXTURE_DIR / 'img4.jpg', + FIXTURE_DIR / 'img5.jpg', + FIXTURE_DIR / 'img6.jpg', + FIXTURE_DIR / 'img7.jpg', + FIXTURE_DIR / 'img8.jpg', +) + + +@ALL_IMGS +def test_something1(datafiles): + """Work with copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 + + # we can do something destructive + (datafiles / 'img3.jpg').unlink() + assert len(list(datafiles.iterdir())) == 7 + + +@ALL_IMGS +def test_something2(datafiles): + """Work with copy of all files.""" + for img in datafiles.iterdir(): + print(img) + # assert process(img) == some_expected_value + + assert len(list(datafiles.iterdir())) == 8 + + # we can do something destructive + (datafiles / 'img1.jpg').unlink() + assert len(list(datafiles.iterdir())) == 7 diff --git a/tests/examples/test_example_4.py b/tests/examples/test_example_4.py new file mode 100644 index 0000000..daab4a2 --- /dev/null +++ b/tests/examples/test_example_4.py @@ -0,0 +1,98 @@ +"""Example: files with same names.""" +from pathlib import Path + +import pytest + +FIXTURE_DIR = Path(__file__).parent.resolve() / '_fixture_files' + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + on_duplicate='ignore', +) +def test_dir_ignore(datafiles): + """Use files from dir1 (first dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '1a\n' + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir3', + on_duplicate='ignore', +) +def test_dir_ignore2(datafiles): + """Use files from dir2 (first dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '2a\n' + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + on_duplicate='overwrite', +) +def test_dir_overwrite(datafiles): + """Use files from dir3 (last dir added).""" + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'fileA').exists() + assert (datafiles / 'fileA').read_text() == '3a\n' + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + # on_duplicate='exception' is the default +) +@pytest.mark.skip( + reason='will raise an exception that cannot be caught in the test itself' +) +def test_dir_exception(datafiles): # pylint: disable=W0613 + """Raise exception because of duplicate filename fileA.""" + assert False + + +def test_dir_exception_generated(testdir): + """Raise exception because of duplicate filename fileA.""" + testdir.makepyfile(f''' + import pytest + from pathlib import Path + + FIXTURE_DIR = Path('{FIXTURE_DIR}') + + @pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + # on_duplicate='exception' is the default + ) + def test_exception(datafiles): + assert True + ''') + result = testdir.runpytest('-s') + result.stdout.fnmatch_lines([ + 'E*ValueError: *already exists*', + ]) + + +@pytest.mark.datafiles( + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', + keep_top_dir=True, +) +def test_dir_keep_top_dir(datafiles): + """Use all files.""" + # 3 subdirs + assert len(list(datafiles.iterdir())) == 3 + # 3 subdirs with each 2 files: 3 + 3*2 + assert len(list(datafiles.glob('**/*'))) == 9 + assert (datafiles / 'dir3' / 'fileA').exists() + assert (datafiles / 'dir3' / 'fileA').read_text() == '3a\n' diff --git a/tests/examples/test_example_5.py b/tests/examples/test_example_5.py new file mode 100644 index 0000000..0e030a3 --- /dev/null +++ b/tests/examples/test_example_5.py @@ -0,0 +1,18 @@ +"""Example: use `str` paths.""" +import os +import pytest + +FIXTURE_DIR = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'test_files' +) + + +@pytest.mark.datafiles( + os.path.join(FIXTURE_DIR, 'img1.jpg'), + os.path.join(FIXTURE_DIR, 'img2.jpg'), + os.path.join(FIXTURE_DIR, 'img3.jpg'), +) +def test_str(datafiles): + """Work with `str`.""" + assert len(list(datafiles.iterdir())) == 3 diff --git a/tests/examples/test_example_upgradev3.py b/tests/examples/test_example_upgradev3.py new file mode 100644 index 0000000..1a354a0 --- /dev/null +++ b/tests/examples/test_example_upgradev3.py @@ -0,0 +1,53 @@ +"""Upgrade to v3.""" +import os + +import pytest +import py + + +@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +def test_convert_to_pypath(datafiles): + """Convert `datafiles` to `py.path` in place. + + Changing the type back to py.path - should be avoided! + + Better to update the tests to make use of `pathlib`. + """ + + # changing the type back to py.path - should be avoided + datafiles = py.path.local(str(datafiles)) + + # code remains as before + assert len(datafiles.listdir()) == 1 + assert (datafiles / 'film1.mp4').check(file=1) + + +@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +def test_update_to_pathlib(datafiles): + """Upgrade code to use `pathlib`. + + Some examples showing `pathlib` style. + """ + + # For demo purpose: this is the old-style + pypath_datafiles = py.path.local(str(datafiles)) + + # old style + assert len(pypath_datafiles.listdir()) == 1 + assert (pypath_datafiles / 'film1.mp4').check(file=1) + + # new style # pylint: disable=R0801 + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'film1.mp4').is_file() + + +@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +def test_keep_using_str(datafiles): + """Keep using plain `os`. + + Nothing changes. + """ + + path = str(datafiles) + assert len(os.listdir(path)) == 1 + assert os.path.isfile(os.path.join(path, 'film1.mp4')) diff --git a/tests/examples/test_files/img1.jpg b/tests/examples/test_files/img1.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img2.jpg b/tests/examples/test_files/img2.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img3.jpg b/tests/examples/test_files/img3.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img4.jpg b/tests/examples/test_files/img4.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img5.jpg b/tests/examples/test_files/img5.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img6.jpg b/tests/examples/test_files/img6.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img7.jpg b/tests/examples/test_files/img7.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/examples/test_files/img8.jpg b/tests/examples/test_files/img8.jpg new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_pytest_datafiles.py b/tests/test_pytest_datafiles.py index 4af5f15..76d7bd5 100644 --- a/tests/test_pytest_datafiles.py +++ b/tests/test_pytest_datafiles.py @@ -1,9 +1,9 @@ """ Tests for the pytest-datafiles pytest plugin """ - import os -from py import path # pylint: disable=E0611 +from pathlib import Path + import pytest @@ -23,7 +23,7 @@ @pytest.mark.datafiles( - path.local( + Path( FIXTURE_FILES[0], # huckleberry.txt ) ) @@ -31,7 +31,7 @@ def test_single_file_pypath(datafiles): """ Verify that a single file (py.path.local) is copied correctly """ - assert (datafiles / 'huckleberry.txt').check(file=1) + assert (datafiles / 'huckleberry.txt').is_file() assert 'Mark Twain' in (datafiles / 'huckleberry.txt').read_text('utf-8') @@ -40,21 +40,21 @@ def test_single_file_str(datafiles): """ Verify that a single file (str) is copied correctly """ - assert (datafiles / 'huckleberry.txt').check(file=1) + assert (datafiles / 'huckleberry.txt').is_file() assert 'Mark Twain' in (datafiles / 'huckleberry.txt').read_text('utf-8') @pytest.mark.datafiles( - *[path.local(p) for p in FIXTURE_FILES] + *[Path(p) for p in FIXTURE_FILES] ) def test_multiple_files_pypath(datafiles): """ Verify multiple files (py.path.local) are copied correctly """ - assert (datafiles / 'huckleberry.txt').check(file=1) - assert (datafiles / 'random.bin').check(file=1) - assert (datafiles / 'sparrow.jpg').check(file=1) - assert len((datafiles).listdir()) == 3 + assert (datafiles / 'huckleberry.txt').is_file() + assert (datafiles / 'random.bin').is_file() + assert (datafiles / 'sparrow.jpg').is_file() + assert len(list(datafiles.iterdir())) == 3 @pytest.mark.datafiles(*FIXTURE_FILES) @@ -62,10 +62,10 @@ def test_multiple_files_str(datafiles): """ Verify multiple files (str) are copied correctly """ - assert (datafiles / 'huckleberry.txt').check(file=1) - assert (datafiles / 'random.bin').check(file=1) - assert (datafiles / 'sparrow.jpg').check(file=1) - assert len((datafiles).listdir()) == 3 + assert (datafiles / 'huckleberry.txt').is_file() + assert (datafiles / 'random.bin').is_file() + assert (datafiles / 'sparrow.jpg').is_file() + assert len(list(datafiles.iterdir())) == 3 @pytest.mark.datafiles(FIXTURE_FILES[0]) @@ -75,10 +75,10 @@ def test_multiple_marks(datafiles): """ Verify multiple marks are combined """ - assert (datafiles / 'huckleberry.txt').check(file=1) - assert (datafiles / 'random.bin').check(file=1) - assert (datafiles / 'sparrow.jpg').check(file=1) - assert len((datafiles).listdir()) == 3 + assert (datafiles / 'huckleberry.txt').is_file() + assert (datafiles / 'random.bin').is_file() + assert (datafiles / 'sparrow.jpg').is_file() + assert len(list(datafiles.iterdir())) == 3 @pytest.mark.datafiles @@ -86,14 +86,14 @@ def test_no_files1(datafiles): """ Verify if datafiles marker is set but empty the directory is empty """ - assert not datafiles.listdir() + assert not list(datafiles.iterdir()) def test_no_files2(datafiles): """ Verify if datafiles marker is not set the directory is empty """ - assert not datafiles.listdir() + assert not list(datafiles.iterdir()) @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'dir1')) @@ -103,10 +103,10 @@ def test_single_dir_str(datafiles): The content of the directory is copied. """ - assert len(datafiles.listdir()) == 3 - assert (datafiles / 'file1').check(file=1) - assert (datafiles / 'file2').check(file=1) - assert (datafiles / 'file3').check(file=1) + assert len(list(datafiles.iterdir())) == 3 + assert (datafiles / 'file1').is_file() + assert (datafiles / 'file2').is_file() + assert (datafiles / 'file3').is_file() @pytest.mark.datafiles( @@ -119,58 +119,58 @@ def test_multi_dir_str(datafiles): The content of the directories is copied. """ - assert len(datafiles.listdir()) == 6 + assert len(list(datafiles.iterdir())) == 6 # files from dir1 - assert (datafiles / 'file1').check(file=1) - assert (datafiles / 'file2').check(file=1) - assert (datafiles / 'file3').check(file=1) + assert (datafiles / 'file1').is_file() + assert (datafiles / 'file2').is_file() + assert (datafiles / 'file3').is_file() # files from dir2 - assert (datafiles / 'file4').check(file=1) - assert (datafiles / 'file5').check(file=1) - assert (datafiles / 'file6').check(file=1) + assert (datafiles / 'file4').is_file() + assert (datafiles / 'file5').is_file() + assert (datafiles / 'file6').is_file() @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1', - path.local(FIXTURE_FILES[0]), # huckleberry.txt - path.local(FIXTURE_DIR) / 'dir4', - path.local(FIXTURE_FILES[1]), # random.bin + Path(FIXTURE_DIR) / 'dir1', + Path(FIXTURE_FILES[0]), # huckleberry.txt + Path(FIXTURE_DIR) / 'dir4', + Path(FIXTURE_FILES[1]), # random.bin ) def test_multiple(datafiles): """ Verify multiple files and directories (with subdirectories) are copied """ - assert len(datafiles.listdir()) == 7 - assert (datafiles / 'huckleberry.txt').check(file=1) - assert (datafiles / 'random.bin').check(file=1) - assert (datafiles / 'file1').check(file=1) - assert (datafiles / 'file2').check(file=1) - assert (datafiles / 'file3').check(file=1) - assert (datafiles / 'subdir1').check(dir=1) - assert (datafiles / 'subdir2').check(dir=1) - assert (datafiles / 'subdir1' / 'file1').check(file=1) - assert (datafiles / 'subdir1' / 'file1').check(file=1) - assert (datafiles / 'subdir2' / 'file2').check(file=1) - assert (datafiles / 'subdir2' / 'file2').check(file=1) + assert len(list(datafiles.iterdir())) == 7 + assert (datafiles / 'huckleberry.txt').is_file() + assert (datafiles / 'random.bin').is_file() + assert (datafiles / 'file1').is_file() + assert (datafiles / 'file2').is_file() + assert (datafiles / 'file3').is_file() + assert (datafiles / 'subdir1').is_dir() + assert (datafiles / 'subdir2').is_dir() + assert (datafiles / 'subdir1' / 'file1').is_file() + assert (datafiles / 'subdir1' / 'file1').is_file() + assert (datafiles / 'subdir2' / 'file2').is_file() + assert (datafiles / 'subdir2' / 'file2').is_file() @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1', - path.local(FIXTURE_DIR) / 'dir2', + Path(FIXTURE_DIR) / 'dir1', + Path(FIXTURE_DIR) / 'dir2', keep_top_dir=True, ) def test_keep_top_dir(datafiles): """ Verify top level directory is kept (instead of only copying the content) """ - assert len(datafiles.listdir()) == 2 - assert (datafiles / 'dir1').check(dir=1) + assert len(list(datafiles.iterdir())) == 2 + assert (datafiles / 'dir1').is_dir() @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1', - path.local(FIXTURE_DIR) / 'dir2', - path.local(FIXTURE_DIR) / 'dir3', + Path(FIXTURE_DIR) / 'dir1', + Path(FIXTURE_DIR) / 'dir2', + Path(FIXTURE_DIR) / 'dir3', on_duplicate='ignore', ) def test_on_duplicate_ignore_dir_with_file(datafiles): @@ -178,18 +178,18 @@ def test_on_duplicate_ignore_dir_with_file(datafiles): Verify duplicate files are ignored (i.e. the first one is kept) If duplicate files appear (to be copied) then the duplicates are ignored - and the first occurence is kept. In this example the file 'file1' appears + and the first occurrence is kept. In this example the file 'file1' appears both in dir1 and dir3 and 'file4' appears both in dir2 and dir3. """ - assert len(datafiles.listdir()) == 6 - assert (datafiles / 'file1').read() == "dir1\n123\n" - assert (datafiles / 'file4').read() == "dir2\n101112\n" + assert len(list(datafiles.iterdir())) == 6 + assert (datafiles / 'file1').read_text() == "dir1\n123\n" + assert (datafiles / 'file4').read_text() == "dir2\n101112\n" @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1', - path.local(FIXTURE_DIR) / 'dir2', - path.local(FIXTURE_DIR) / 'dir3', + Path(FIXTURE_DIR) / 'dir1', + Path(FIXTURE_DIR) / 'dir2', + Path(FIXTURE_DIR) / 'dir3', on_duplicate='overwrite', ) def test_on_duplicate_overwrite(datafiles): @@ -200,9 +200,9 @@ def test_on_duplicate_overwrite(datafiles): overwritten and the first last is kept. In this example the file 'file1' appears both in dir1 and dir3 and 'file4' appears both in dir2 and dir3. """ - assert len(datafiles.listdir()) == 6 - assert (datafiles / 'file1').read() == "dir3\n123\n" - assert (datafiles / 'file4').read() == "dir3\n101112\n" + assert len(list(datafiles.iterdir())) == 6 + assert (datafiles / 'file1').read_text() == "dir3\n123\n" + assert (datafiles / 'file4').read_text() == "dir3\n101112\n" def test_on_duplicate_exception(testdir): @@ -214,19 +214,19 @@ def test_on_duplicate_exception(testdir): If duplicate files appear (to be copied) then a ValueError is raised. In this example the file 'file1' appears both in dir1 and dir3. """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1', - path.local(FIXTURE_DIR) / 'dir3', + Path(FIXTURE_DIR) / 'dir1', + Path(FIXTURE_DIR) / 'dir3', ) def test_ode(datafiles): - assert len(datafiles.listdir()) == 6 - '''.format(FIXTURE_DIR)) + assert len(list(datafiles.iterdir())) == 6 + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines(["E*ValueError:*file1'*already exists*"]) @@ -235,19 +235,19 @@ def test_on_duplicate_exception2(testdir): """ Verify that a ValueError is raised when duplicate files appear """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1' / 'file1', - path.local(FIXTURE_DIR) / 'dir3' / 'file1', + Path(FIXTURE_DIR) / 'dir1' / 'file1', + Path(FIXTURE_DIR) / 'dir3' / 'file1', ) def test_ode(datafiles): - assert len(datafiles.listdir()) == 2 - '''.format(FIXTURE_DIR)) + assert len(list(datafiles.iterdir())) == 2 + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines(["E*ValueError:*file1'*already exists*"]) @@ -261,27 +261,27 @@ def test_on_duplicate_exception_dir(testdir): If duplicate files appear (to be copied) then a ValueError is raised. In this example the directory 'subdir1' appears twice. """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir4' / 'subdir1', - path.local(FIXTURE_DIR) / 'dir5' / 'subdir1', + Path(FIXTURE_DIR) / 'dir4' / 'subdir1', + Path(FIXTURE_DIR) / 'dir5' / 'subdir1', keep_top_dir=True, ) def test_duplicate_dir(datafiles): assert True - '''.format(FIXTURE_DIR)) + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines(["E*ValueError:*subdir1'*already exists*"]) @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir4' / 'subdir1', - path.local(FIXTURE_DIR) / 'dir5' / 'subdir1', + Path(FIXTURE_DIR) / 'dir4' / 'subdir1', + Path(FIXTURE_DIR) / 'dir5' / 'subdir1', keep_top_dir=True, on_duplicate='ignore', ) @@ -289,41 +289,41 @@ def test_on_duplicate_ignore_dir(datafiles): """ Verify that the second (duplicate) directory is ignored. """ - assert (datafiles / 'subdir1' / 'file1').check(file=1) + assert (datafiles / 'subdir1' / 'file1').is_file() @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'dir1' / 'file1', - path.local(FIXTURE_DIR) / 'dir3' / 'file1', + Path(FIXTURE_DIR) / 'dir1' / 'file1', + Path(FIXTURE_DIR) / 'dir3' / 'file1', on_duplicate='ignore', ) def test_on_duplicate_ignore_file(datafiles): """ Verify on_duplicate=ignore causes the first file to be used """ - assert (datafiles / 'file1').check(file=1) - assert (datafiles / 'file1').read() == "dir1\n123\n" + assert (datafiles / 'file1').is_file() + assert (datafiles / 'file1').read_text() == "dir1\n123\n" def test_non_existing_file(testdir): """ Verify exception is raised if file doesn't exist. """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'fileZZ', + Path(FIXTURE_DIR) / 'fileZZ', ) def test_ode(datafiles): - assert len(datafiles.listdir()) == 1 - '''.format(FIXTURE_DIR)) + assert len(list(datafiles.iterdir())) == 1 + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines([ - "E*ValueError:*fileZZ'*does not exist!*", + "E*FileNotFoundError:*fileZZ'", ]) @@ -331,42 +331,42 @@ def test_invalid_keep_top_dir(testdir): """ Verify ValueError is raised if parameter isn't boolean """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'fileZZ', + Path(FIXTURE_DIR) / 'fileZZ', keep_top_dir='invalid-value', ) def test_invalid_param(datafiles): assert True - '''.format(FIXTURE_DIR)) + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines([ "E*ValueError: 'keep_top_dir' must be True or False*", - ]) + ]) def test_invalid_on_duplicate(testdir): """ Verify ValueError is raised if parameter isn't boolean """ - testdir.makepyfile(''' + testdir.makepyfile(f''' import pytest - from py import path + from pathlib import Path - FIXTURE_DIR = '{0}' + FIXTURE_DIR = '{FIXTURE_DIR}' @pytest.mark.datafiles( - path.local(FIXTURE_DIR) / 'fileZZ', + Path(FIXTURE_DIR) / 'fileZZ', on_duplicate='invalid-value', ) def test_invalid_param(datafiles): assert True - '''.format(FIXTURE_DIR)) + ''') result = testdir.runpytest('-s') result.stdout.fnmatch_lines([ "E*ValueError: 'on_duplicate' must be 'exception', 'ignore' or *", @@ -378,8 +378,8 @@ def test_copy_symlink(datafiles): """ Verify that symlinks are copied and not their targets. """ - assert len(datafiles.listdir()) == 1 - assert (datafiles / 'sparrow_link.jpg').check(link=1) + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'sparrow_link.jpg').is_symlink() @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'dir6')) @@ -387,8 +387,8 @@ def test_copy_symlink_in_dir(datafiles): """ Verify that symlinks are copied and not their targets. """ - assert len(datafiles.listdir()) == 1 - assert (datafiles / 'sparrow_link.jpg').check(link=1) + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'sparrow_link.jpg').is_symlink() @pytest.mark.datafiles( @@ -399,6 +399,6 @@ def test_copy_symlink_in_dir2(datafiles): """ Verify that symlinks are copied and not their targets. """ - assert len(datafiles.listdir()) == 1 - assert len((datafiles / 'dir6').listdir()) == 1 - assert (datafiles / 'dir6' / 'sparrow_link.jpg').check(link=1) + assert len(list(datafiles.iterdir())) == 1 + assert len(list((datafiles / 'dir6').iterdir())) == 1 + assert (datafiles / 'dir6' / 'sparrow_link.jpg').is_symlink() diff --git a/tox.ini b/tox.ini index e9cd71f..697b0ad 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,17 @@ [tox] -envlist = py27, py34, py35, py36, py37, py38 +envlist = py36, py37, py38, py39, py310, py311 [testenv] -commands = py.test tests/test_pytest_datafiles.py -deps = pytest +deps = + pytest +commands = + pytest tests/test_pytest_datafiles.py + +[testenv:examples] +deps = + pytest +commands = + pytest tests/examples/ [testenv:coverage] usedevelop = True @@ -20,5 +28,13 @@ deps = pylint flake8 commands = - flake8 --max-complexity=10 pytest_datafiles.py tests/test_pytest_datafiles.py - pylint pytest_datafiles.py tests/test_pytest_datafiles.py + flake8 --max-complexity=10 pytest_datafiles.py tests/ + pylint pytest_datafiles.py tests/ + +[testenv:doc] +basepython = python3 +deps = + sphinx + sphinxcontrib-restbuilder +commands = + sphinx-build -b rst docs/readme . From 163283c723128fb97a3e16fa896f36e53ceb78b5 Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sat, 18 Feb 2023 22:45:48 +0100 Subject: [PATCH 02/11] correct reference for example files --- README.rst | 2 +- docs/readme/README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index ece31ee..98c9905 100644 --- a/README.rst +++ b/README.rst @@ -143,7 +143,7 @@ Your tests may need to be adjusted. Usage ===== -These examples can also be found in *src/pytest_datafiles/examples*. +These examples can also be found in *tests/examples*. Example 1 diff --git a/docs/readme/README.rst b/docs/readme/README.rst index 3462d78..a996656 100644 --- a/docs/readme/README.rst +++ b/docs/readme/README.rst @@ -96,7 +96,7 @@ Your tests may need to be adjusted. Usage ----- -These examples can also be found in `src/pytest_datafiles/examples`. +These examples can also be found in `tests/examples`. Example 1 ~~~~~~~~~ From 4dc2d1cf1ad8cbf09399bdce87755fd12276f1c1 Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 11:29:44 +0100 Subject: [PATCH 03/11] Default to Path in tests --- tests/test_pytest_datafiles.py | 98 ++++++++++++++++------------------ 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/tests/test_pytest_datafiles.py b/tests/test_pytest_datafiles.py index 76d7bd5..d6dd4f2 100644 --- a/tests/test_pytest_datafiles.py +++ b/tests/test_pytest_datafiles.py @@ -10,10 +10,10 @@ pytest_plugins = 'pytester' # pylint: disable=C0103 -TEST_DIR = os.path.dirname(os.path.realpath(__file__)) -FIXTURE_DIR = os.path.join(TEST_DIR, '_fixture_files') +TEST_DIR = Path(__file__).parent.resolve() +FIXTURE_DIR = TEST_DIR / '_fixture_files' FIXTURE_FILES = [ - os.path.join(FIXTURE_DIR, name) + FIXTURE_DIR / name for name in [ 'huckleberry.txt', 'random.bin', @@ -22,20 +22,16 @@ ] -@pytest.mark.datafiles( - Path( - FIXTURE_FILES[0], # huckleberry.txt - ) - ) +@pytest.mark.datafiles(FIXTURE_FILES[0]) # huckleberry.txt def test_single_file_pypath(datafiles): """ - Verify that a single file (py.path.local) is copied correctly + Verify that a single file (pathlib.Path) is copied correctly """ assert (datafiles / 'huckleberry.txt').is_file() assert 'Mark Twain' in (datafiles / 'huckleberry.txt').read_text('utf-8') -@pytest.mark.datafiles(FIXTURE_FILES[0]) # huckleberry.txt +@pytest.mark.datafiles(str(FIXTURE_FILES[0])) # huckleberry.txt def test_single_file_str(datafiles): """ Verify that a single file (str) is copied correctly @@ -44,12 +40,10 @@ def test_single_file_str(datafiles): assert 'Mark Twain' in (datafiles / 'huckleberry.txt').read_text('utf-8') -@pytest.mark.datafiles( - *[Path(p) for p in FIXTURE_FILES] - ) +@pytest.mark.datafiles(*FIXTURE_FILES) def test_multiple_files_pypath(datafiles): """ - Verify multiple files (py.path.local) are copied correctly + Verify multiple files (pathlib.Path) are copied correctly """ assert (datafiles / 'huckleberry.txt').is_file() assert (datafiles / 'random.bin').is_file() @@ -57,7 +51,7 @@ def test_multiple_files_pypath(datafiles): assert len(list(datafiles.iterdir())) == 3 -@pytest.mark.datafiles(*FIXTURE_FILES) +@pytest.mark.datafiles(*[str(f) for f in FIXTURE_FILES]) def test_multiple_files_str(datafiles): """ Verify multiple files (str) are copied correctly @@ -96,7 +90,7 @@ def test_no_files2(datafiles): assert not list(datafiles.iterdir()) -@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'dir1')) +@pytest.mark.datafiles(os.path.join(str(FIXTURE_DIR), 'dir1')) def test_single_dir_str(datafiles): """ Verify that a single directory (specified as a string) is copied correctly. @@ -110,8 +104,8 @@ def test_single_dir_str(datafiles): @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir1'), - os.path.join(FIXTURE_DIR, 'dir2'), + os.path.join(str(FIXTURE_DIR), 'dir1'), + os.path.join(str(FIXTURE_DIR), 'dir2'), ) def test_multi_dir_str(datafiles): """ @@ -131,10 +125,10 @@ def test_multi_dir_str(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1', - Path(FIXTURE_FILES[0]), # huckleberry.txt - Path(FIXTURE_DIR) / 'dir4', - Path(FIXTURE_FILES[1]), # random.bin + FIXTURE_DIR / 'dir1', + FIXTURE_FILES[0], # huckleberry.txt + FIXTURE_DIR / 'dir4', + FIXTURE_FILES[1], # random.bin ) def test_multiple(datafiles): """ @@ -155,8 +149,8 @@ def test_multiple(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1', - Path(FIXTURE_DIR) / 'dir2', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', keep_top_dir=True, ) def test_keep_top_dir(datafiles): @@ -168,9 +162,9 @@ def test_keep_top_dir(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1', - Path(FIXTURE_DIR) / 'dir2', - Path(FIXTURE_DIR) / 'dir3', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', on_duplicate='ignore', ) def test_on_duplicate_ignore_dir_with_file(datafiles): @@ -187,9 +181,9 @@ def test_on_duplicate_ignore_dir_with_file(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1', - Path(FIXTURE_DIR) / 'dir2', - Path(FIXTURE_DIR) / 'dir3', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir2', + FIXTURE_DIR / 'dir3', on_duplicate='overwrite', ) def test_on_duplicate_overwrite(datafiles): @@ -218,11 +212,11 @@ def test_on_duplicate_exception(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1', - Path(FIXTURE_DIR) / 'dir3', + FIXTURE_DIR / 'dir1', + FIXTURE_DIR / 'dir3', ) def test_ode(datafiles): assert len(list(datafiles.iterdir())) == 6 @@ -239,11 +233,11 @@ def test_on_duplicate_exception2(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1' / 'file1', - Path(FIXTURE_DIR) / 'dir3' / 'file1', + FIXTURE_DIR / 'dir1' / 'file1', + FIXTURE_DIR / 'dir3' / 'file1', ) def test_ode(datafiles): assert len(list(datafiles.iterdir())) == 2 @@ -265,11 +259,11 @@ def test_on_duplicate_exception_dir(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir4' / 'subdir1', - Path(FIXTURE_DIR) / 'dir5' / 'subdir1', + FIXTURE_DIR / 'dir4' / 'subdir1', + FIXTURE_DIR / 'dir5' / 'subdir1', keep_top_dir=True, ) def test_duplicate_dir(datafiles): @@ -280,8 +274,8 @@ def test_duplicate_dir(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir4' / 'subdir1', - Path(FIXTURE_DIR) / 'dir5' / 'subdir1', + FIXTURE_DIR / 'dir4' / 'subdir1', + FIXTURE_DIR / 'dir5' / 'subdir1', keep_top_dir=True, on_duplicate='ignore', ) @@ -293,8 +287,8 @@ def test_on_duplicate_ignore_dir(datafiles): @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'dir1' / 'file1', - Path(FIXTURE_DIR) / 'dir3' / 'file1', + FIXTURE_DIR / 'dir1' / 'file1', + FIXTURE_DIR / 'dir3' / 'file1', on_duplicate='ignore', ) def test_on_duplicate_ignore_file(datafiles): @@ -313,10 +307,10 @@ def test_non_existing_file(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'fileZZ', + FIXTURE_DIR / 'fileZZ', ) def test_ode(datafiles): assert len(list(datafiles.iterdir())) == 1 @@ -335,10 +329,10 @@ def test_invalid_keep_top_dir(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'fileZZ', + FIXTURE_DIR / 'fileZZ', keep_top_dir='invalid-value', ) def test_invalid_param(datafiles): @@ -358,10 +352,10 @@ def test_invalid_on_duplicate(testdir): import pytest from pathlib import Path - FIXTURE_DIR = '{FIXTURE_DIR}' + FIXTURE_DIR = Path('{FIXTURE_DIR}') @pytest.mark.datafiles( - Path(FIXTURE_DIR) / 'fileZZ', + FIXTURE_DIR / 'fileZZ', on_duplicate='invalid-value', ) def test_invalid_param(datafiles): @@ -373,7 +367,7 @@ def test_invalid_param(datafiles): ]) -@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'sparrow_link.jpg')) +@pytest.mark.datafiles(FIXTURE_DIR / 'sparrow_link.jpg') def test_copy_symlink(datafiles): """ Verify that symlinks are copied and not their targets. @@ -382,7 +376,7 @@ def test_copy_symlink(datafiles): assert (datafiles / 'sparrow_link.jpg').is_symlink() -@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'dir6')) +@pytest.mark.datafiles(FIXTURE_DIR / 'dir6') def test_copy_symlink_in_dir(datafiles): """ Verify that symlinks are copied and not their targets. @@ -392,7 +386,7 @@ def test_copy_symlink_in_dir(datafiles): @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'dir6'), + FIXTURE_DIR / 'dir6', keep_top_dir=True, ) def test_copy_symlink_in_dir2(datafiles): From 126b9fdeb3091f8e25ad1de190c4cf156ab37723 Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 11:31:01 +0100 Subject: [PATCH 04/11] Remove old leftovers --- src/pytest_datafiles/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/pytest_datafiles/__init__.py diff --git a/src/pytest_datafiles/__init__.py b/src/pytest_datafiles/__init__.py deleted file mode 100644 index e69de29..0000000 From 4c98bde002e614df8202ed6cc77d753156301ced Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 12:44:53 +0100 Subject: [PATCH 05/11] Remove old leftovers --- tests/test_pytest_datafiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_pytest_datafiles.py b/tests/test_pytest_datafiles.py index d6dd4f2..2618cc8 100644 --- a/tests/test_pytest_datafiles.py +++ b/tests/test_pytest_datafiles.py @@ -23,7 +23,7 @@ @pytest.mark.datafiles(FIXTURE_FILES[0]) # huckleberry.txt -def test_single_file_pypath(datafiles): +def test_single_file_path(datafiles): """ Verify that a single file (pathlib.Path) is copied correctly """ @@ -41,7 +41,7 @@ def test_single_file_str(datafiles): @pytest.mark.datafiles(*FIXTURE_FILES) -def test_multiple_files_pypath(datafiles): +def test_multiple_files_path(datafiles): """ Verify multiple files (pathlib.Path) are copied correctly """ From cd94fdb8f4edc76729e722c438244075d1447a4d Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 15:22:51 +0100 Subject: [PATCH 06/11] Review remarks --- Makefile | 6 +- README.rst | 64 +++++++---------- docs/readme/README.rst | 14 ++-- tests/examples/conftest.py | 31 -------- .../{test_example_1.py => example_1.py} | 4 +- .../{test_example_2.py => example_2.py} | 0 .../{test_example_3.py => example_3.py} | 0 .../{test_example_4.py => example_4.py} | 26 ------- .../{test_example_5.py => example_5.py} | 0 tests/examples/example_upgradev3.py | 63 ++++++++++++++++ tests/examples/test_example_upgradev3.py | 53 -------------- tests/test_examples.py | 71 +++++++++++++++++++ tox.ini | 2 +- 13 files changed, 171 insertions(+), 163 deletions(-) delete mode 100644 tests/examples/conftest.py rename tests/examples/{test_example_1.py => example_1.py} (86%) rename tests/examples/{test_example_2.py => example_2.py} (100%) rename tests/examples/{test_example_3.py => example_3.py} (100%) rename tests/examples/{test_example_4.py => example_4.py} (73%) rename tests/examples/{test_example_5.py => example_5.py} (100%) create mode 100644 tests/examples/example_upgradev3.py delete mode 100644 tests/examples/test_example_upgradev3.py create mode 100644 tests/test_examples.py diff --git a/Makefile b/Makefile index dbabb4f..ceed87b 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ help: @echo "test-all Run tests on every Python version with tox" @echo "coverage Check code coverage quickly with Python 3" @echo "dist Package" - @echo "README.rst Generate README.rst from docs/readme" + @echo "docs Generate docs from docs/ (eg README.rst)" clean: clean-build clean-pyc clean-test @@ -54,11 +54,11 @@ coverage: tox -e coverage command -v xdg-open && xdg-open htmlcov/index.html || true -dist: readme | clean +dist: docs | clean python3 setup.py sdist python3 setup.py bdist_wheel ls -l dist -readme: +docs: touch README.rst tox -e doc diff --git a/README.rst b/README.rst index 98c9905..2a699de 100644 --- a/README.rst +++ b/README.rst @@ -87,29 +87,39 @@ Your tests may need to be adjusted. """Upgrade to v3.""" import os + from pathlib import Path import pytest import py + FIXTURE_DIR = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'test_files', + ) + + FIXTURE_DIR_NEW_STYLE = Path(__file__).parent.resolve() / 'test_files' - @pytest.mark.datafiles('/tmp/big_files/film1.mp4') - def test_convert_to_pypath(datafiles): - """Convert `datafiles` to `py.path` in place. - Changing the type back to py.path - should be avoided! + @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) + def test_convert_to_pypath(datafiles): + """ + If your tests are taking advantage of py.path the simplest change + you can make is at the top of each test convert the pathlib.Path + object back to a py.path . - Better to update the tests to make use of `pathlib`. + Note that it would be better to migrate to pathlib.Path, as shown in + the next example, because py.path is deprecated. """ - # changing the type back to py.path - should be avoided + # changing the type back to py.path as a quick fix datafiles = py.path.local(str(datafiles)) # code remains as before assert len(datafiles.listdir()) == 1 - assert (datafiles / 'film1.mp4').check(file=1) + assert (datafiles / 'img1.jpg').check(file=1) - @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + @pytest.mark.datafiles(FIXTURE_DIR_NEW_STYLE / 'img1.jpg') def test_update_to_pathlib(datafiles): """Upgrade code to use `pathlib`. @@ -121,14 +131,14 @@ Your tests may need to be adjusted. # old style assert len(pypath_datafiles.listdir()) == 1 - assert (pypath_datafiles / 'film1.mp4').check(file=1) + assert (pypath_datafiles / 'img1.jpg').check(file=1) # new style # pylint: disable=R0801 assert len(list(datafiles.iterdir())) == 1 - assert (datafiles / 'film1.mp4').is_file() + assert (datafiles / 'img1.jpg').is_file() - @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) def test_keep_using_str(datafiles): """Keep using plain `os`. @@ -137,7 +147,7 @@ Your tests may need to be adjusted. path = str(datafiles) assert len(os.listdir(path)) == 1 - assert os.path.isfile(os.path.join(path, 'film1.mp4')) + assert os.path.isfile(os.path.join(path, 'img1.jpg')) Usage @@ -163,7 +173,7 @@ method as follows: import pytest - @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + @pytest.mark.datafiles('/opt/big_files/film1.mp4') def test_fast_forward(datafiles): """Work with a copy of the big file.""" assert len(list(datafiles.iterdir())) == 1 @@ -171,7 +181,7 @@ method as follows: # assert some_operation(datafiles / 'film1.mp4') == expected_result - @pytest.mark.datafiles('/tmp/big_files/film1.mp4') + @pytest.mark.datafiles('/opt/big_files/film1.mp4') def test_fast_forward_alternative(datafiles): """Work with a copy of the bigfile, using `str`.""" path = str(datafiles) # Convert from py.path object to path (str) @@ -363,37 +373,11 @@ This example clarifies the options **on_duplicate** and FIXTURE_DIR / 'dir3', # on_duplicate='exception' is the default ) - @pytest.mark.skip( - reason='will raise an exception that cannot be caught in the test itself' - ) def test_dir_exception(datafiles): # pylint: disable=W0613 """Raise exception because of duplicate filename fileA.""" assert False - def test_dir_exception_generated(testdir): - """Raise exception because of duplicate filename fileA.""" - testdir.makepyfile(f''' - import pytest - from pathlib import Path - - FIXTURE_DIR = Path('{FIXTURE_DIR}') - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - # on_duplicate='exception' is the default - ) - def test_exception(datafiles): - assert True - ''') - result = testdir.runpytest('-s') - result.stdout.fnmatch_lines([ - 'E*ValueError: *already exists*', - ]) - - @pytest.mark.datafiles( FIXTURE_DIR / 'dir1', FIXTURE_DIR / 'dir2', diff --git a/docs/readme/README.rst b/docs/readme/README.rst index a996656..a4ee51c 100644 --- a/docs/readme/README.rst +++ b/docs/readme/README.rst @@ -1,4 +1,4 @@ -.. This file will be rendered to teh README.rst in the root +.. This file will be rendered to the README.rst in the root ================ pytest-datafiles @@ -89,7 +89,7 @@ instead of `py.path`. Your tests may need to be adjusted. -.. literalinclude:: ../../tests/examples/test_example_upgradev3.py +.. literalinclude:: ../../tests/examples/example_upgradev3.py :language: python @@ -107,7 +107,7 @@ large video files stored under */opt/big_files/* . You don't want your tests mod the original files, but the files are required by the tests. You can reference these data files in your test method as follows: -.. literalinclude:: ../../tests/examples/test_example_1.py +.. literalinclude:: ../../tests/examples/example_1.py :language: python Example 2 @@ -118,7 +118,7 @@ place a directory named *test_files*. Here you have a lot of images you want to on. By using this plugin, you make sure the original files under *test_files* are not modified by every test. -.. literalinclude:: ../../tests/examples/test_example_2.py +.. literalinclude:: ../../tests/examples/example_2.py :language: python Example 3 @@ -127,7 +127,7 @@ Example 3 If all (or many) of your tests rely on the same files it can be easier to define one decorator beforehand and apply it to every test like this example: -.. literalinclude:: ../../tests/examples/test_example_3.py +.. literalinclude:: ../../tests/examples/example_3.py :language: python Example 4 @@ -138,7 +138,7 @@ Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the file This example clarifies the options **on_duplicate** and **keep_top_dir**. -.. literalinclude:: ../../tests/examples/test_example_4.py +.. literalinclude:: ../../tests/examples/example_4.py :language: python Example 5 @@ -146,7 +146,7 @@ Example 5 You can also use a str paths. -.. literalinclude:: ../../tests/examples/test_example_5.py +.. literalinclude:: ../../tests/examples/example_5.py :language: python diff --git a/tests/examples/conftest.py b/tests/examples/conftest.py deleted file mode 100644 index dbed544..0000000 --- a/tests/examples/conftest.py +++ /dev/null @@ -1,31 +0,0 @@ -# pylint: skip-file -import shutil -from pathlib import Path - -import pytest - - -def first_not_existing_parent(path: Path) -> Path: - parent = path.parent - if parent.exists(): - return path - return first_not_existing_parent(parent) - - -@pytest.fixture(scope="session") -def example_1(): - file = Path('/tmp/big_files/film1.mp4') - path = first_not_existing_parent(file) - print(f'found {path}') - - file.parent.mkdir(parents=True, exist_ok=True) - file.touch() - yield 1 - file.unlink() - if path.is_dir(): - shutil.rmtree(path) - - -@pytest.fixture(autouse=True) -def setup_examples(example_1): - pass diff --git a/tests/examples/test_example_1.py b/tests/examples/example_1.py similarity index 86% rename from tests/examples/test_example_1.py rename to tests/examples/example_1.py index 5a933c4..2c9849e 100644 --- a/tests/examples/test_example_1.py +++ b/tests/examples/example_1.py @@ -3,7 +3,7 @@ import pytest -@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +@pytest.mark.datafiles('/opt/big_files/film1.mp4') def test_fast_forward(datafiles): """Work with a copy of the big file.""" assert len(list(datafiles.iterdir())) == 1 @@ -11,7 +11,7 @@ def test_fast_forward(datafiles): # assert some_operation(datafiles / 'film1.mp4') == expected_result -@pytest.mark.datafiles('/tmp/big_files/film1.mp4') +@pytest.mark.datafiles('/opt/big_files/film1.mp4') def test_fast_forward_alternative(datafiles): """Work with a copy of the bigfile, using `str`.""" path = str(datafiles) # Convert from py.path object to path (str) diff --git a/tests/examples/test_example_2.py b/tests/examples/example_2.py similarity index 100% rename from tests/examples/test_example_2.py rename to tests/examples/example_2.py diff --git a/tests/examples/test_example_3.py b/tests/examples/example_3.py similarity index 100% rename from tests/examples/test_example_3.py rename to tests/examples/example_3.py diff --git a/tests/examples/test_example_4.py b/tests/examples/example_4.py similarity index 73% rename from tests/examples/test_example_4.py rename to tests/examples/example_4.py index daab4a2..cd06a51 100644 --- a/tests/examples/test_example_4.py +++ b/tests/examples/example_4.py @@ -51,37 +51,11 @@ def test_dir_overwrite(datafiles): FIXTURE_DIR / 'dir3', # on_duplicate='exception' is the default ) -@pytest.mark.skip( - reason='will raise an exception that cannot be caught in the test itself' -) def test_dir_exception(datafiles): # pylint: disable=W0613 """Raise exception because of duplicate filename fileA.""" assert False -def test_dir_exception_generated(testdir): - """Raise exception because of duplicate filename fileA.""" - testdir.makepyfile(f''' - import pytest - from pathlib import Path - - FIXTURE_DIR = Path('{FIXTURE_DIR}') - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - # on_duplicate='exception' is the default - ) - def test_exception(datafiles): - assert True - ''') - result = testdir.runpytest('-s') - result.stdout.fnmatch_lines([ - 'E*ValueError: *already exists*', - ]) - - @pytest.mark.datafiles( FIXTURE_DIR / 'dir1', FIXTURE_DIR / 'dir2', diff --git a/tests/examples/test_example_5.py b/tests/examples/example_5.py similarity index 100% rename from tests/examples/test_example_5.py rename to tests/examples/example_5.py diff --git a/tests/examples/example_upgradev3.py b/tests/examples/example_upgradev3.py new file mode 100644 index 0000000..9e8d093 --- /dev/null +++ b/tests/examples/example_upgradev3.py @@ -0,0 +1,63 @@ +"""Upgrade to v3.""" +import os +from pathlib import Path + +import pytest +import py + +FIXTURE_DIR = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'test_files', +) + +FIXTURE_DIR_NEW_STYLE = Path(__file__).parent.resolve() / 'test_files' + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) +def test_convert_to_pypath(datafiles): + """ + If your tests are taking advantage of py.path the simplest change + you can make is at the top of each test convert the pathlib.Path + object back to a py.path . + + Note that it would be better to migrate to pathlib.Path, as shown in + the next example, because py.path is deprecated. + """ + + # changing the type back to py.path as a quick fix + datafiles = py.path.local(str(datafiles)) + + # code remains as before + assert len(datafiles.listdir()) == 1 + assert (datafiles / 'img1.jpg').check(file=1) + + +@pytest.mark.datafiles(FIXTURE_DIR_NEW_STYLE / 'img1.jpg') +def test_update_to_pathlib(datafiles): + """Upgrade code to use `pathlib`. + + Some examples showing `pathlib` style. + """ + + # For demo purpose: this is the old-style + pypath_datafiles = py.path.local(str(datafiles)) + + # old style + assert len(pypath_datafiles.listdir()) == 1 + assert (pypath_datafiles / 'img1.jpg').check(file=1) + + # new style # pylint: disable=R0801 + assert len(list(datafiles.iterdir())) == 1 + assert (datafiles / 'img1.jpg').is_file() + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) +def test_keep_using_str(datafiles): + """Keep using plain `os`. + + Nothing changes. + """ + + path = str(datafiles) + assert len(os.listdir(path)) == 1 + assert os.path.isfile(os.path.join(path, 'img1.jpg')) diff --git a/tests/examples/test_example_upgradev3.py b/tests/examples/test_example_upgradev3.py deleted file mode 100644 index 1a354a0..0000000 --- a/tests/examples/test_example_upgradev3.py +++ /dev/null @@ -1,53 +0,0 @@ -"""Upgrade to v3.""" -import os - -import pytest -import py - - -@pytest.mark.datafiles('/tmp/big_files/film1.mp4') -def test_convert_to_pypath(datafiles): - """Convert `datafiles` to `py.path` in place. - - Changing the type back to py.path - should be avoided! - - Better to update the tests to make use of `pathlib`. - """ - - # changing the type back to py.path - should be avoided - datafiles = py.path.local(str(datafiles)) - - # code remains as before - assert len(datafiles.listdir()) == 1 - assert (datafiles / 'film1.mp4').check(file=1) - - -@pytest.mark.datafiles('/tmp/big_files/film1.mp4') -def test_update_to_pathlib(datafiles): - """Upgrade code to use `pathlib`. - - Some examples showing `pathlib` style. - """ - - # For demo purpose: this is the old-style - pypath_datafiles = py.path.local(str(datafiles)) - - # old style - assert len(pypath_datafiles.listdir()) == 1 - assert (pypath_datafiles / 'film1.mp4').check(file=1) - - # new style # pylint: disable=R0801 - assert len(list(datafiles.iterdir())) == 1 - assert (datafiles / 'film1.mp4').is_file() - - -@pytest.mark.datafiles('/tmp/big_files/film1.mp4') -def test_keep_using_str(datafiles): - """Keep using plain `os`. - - Nothing changes. - """ - - path = str(datafiles) - assert len(os.listdir(path)) == 1 - assert os.path.isfile(os.path.join(path, 'film1.mp4')) diff --git a/tests/test_examples.py b/tests/test_examples.py new file mode 100644 index 0000000..4847b04 --- /dev/null +++ b/tests/test_examples.py @@ -0,0 +1,71 @@ +""" +Tests for the examples. +""" +import shutil +from pathlib import Path + +import pytest +from _pytest.config import ExitCode +from _pytest.pytester import Pytester + +EXAMPLE_DIR = Path(__file__).parent.resolve() / 'examples' + + +@pytest.fixture +def example_files(pytester: Pytester): + """Get all examples and dependencies into the testing env.""" + shutil.copytree(EXAMPLE_DIR, pytester.path, dirs_exist_ok=True) + return pytester + + +@pytest.mark.parametrize("example,expected", [ + ('example_1', ExitCode.TESTS_FAILED), + ('example_2', ExitCode.OK), + ('example_3', ExitCode.OK), + ('example_4', ExitCode.TESTS_FAILED), + ('example_5', ExitCode.OK), + ('example_upgradev3', ExitCode.OK), +]) +def test_examples(example_files, example, expected): # pylint: disable=W0621 + """ + Smoke test all provided examples. + + For those with expected failures, additional tests have been + created to validate the correctness of the failure. + """ + result = example_files.runpytest(f'{example}.py') + assert result.ret == expected + + +def test_example_1_ok(example_files): # pylint: disable=W0621 + """ + Example 1 is referring to a file in '/opt'. + + For the smoke test, just use a local existing file. + """ + target_file = example_files.path / 'film1.mp4' + target_file.write_text('dummy') + + example = (example_files.path / 'example_1.py').read_text().replace( + '/opt/big_files/film1.mp4', str(target_file) + ) + + new_example = example_files.makepyfile(example) + result = example_files.runpytest(new_example) + assert result.ret == ExitCode.OK + + +def test_example_4_ok(example_files): # pylint: disable=W0621 + """ + Example 4 contains an expected failure during test setup, that cannot + be captured in a nice way without disturbing the example. + """ + result = example_files.runpytest('example_4.py') + + assert result.ret == ExitCode.TESTS_FAILED + result.assert_outcomes(passed=4, errors=1) + + result.stdout.fnmatch_lines([ + '*ERROR at setup of test_dir_exception*', + 'E*ValueError: *already exists*', + ]) diff --git a/tox.ini b/tox.ini index 697b0ad..20836bc 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ commands = deps = pytest commands = - pytest tests/examples/ + pytest tests/test_examples.py [testenv:coverage] usedevelop = True From 1e01558afeedfae2ccd125661f7383a86c8e4076 Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 15:25:37 +0100 Subject: [PATCH 07/11] Dropping generated README --- Makefile | 7 +- README.rst | 543 +++++++++++------------------------------ docs/readme/README.rst | 218 ----------------- docs/readme/conf.py | 8 - 4 files changed, 138 insertions(+), 638 deletions(-) delete mode 100644 docs/readme/README.rst delete mode 100644 docs/readme/conf.py diff --git a/Makefile b/Makefile index ceed87b..6be976f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,6 @@ help: @echo "test-all Run tests on every Python version with tox" @echo "coverage Check code coverage quickly with Python 3" @echo "dist Package" - @echo "docs Generate docs from docs/ (eg README.rst)" clean: clean-build clean-pyc clean-test @@ -54,11 +53,7 @@ coverage: tox -e coverage command -v xdg-open && xdg-open htmlcov/index.html || true -dist: docs | clean +dist: clean python3 setup.py sdist python3 setup.py bdist_wheel ls -l dist - -docs: - touch README.rst - tox -e doc diff --git a/README.rst b/README.rst index 2a699de..a03b492 100644 --- a/README.rst +++ b/README.rst @@ -1,487 +1,218 @@ +.. This file will be rendered to the README.rst in the root +================ pytest-datafiles -**************** +================ -https://travis-ci.org/omarkohl/pytest-datafileshttps://coveralls.io/github/omarkohl/pytest-datafiles?branch=masterhttps://pypi.python.org/pypi/pytest-datafileshttps://codeclimate.com/github/omarkohl/pytest-datafiles +.. image:: https://img.shields.io/travis/omarkohl/pytest-datafiles.svg + :target: https://travis-ci.org/omarkohl/pytest-datafiles -`pytest `_ plugin to -create a `tmp_path `_ -containing a preconfigured set of files and/or directories. -**Note about maintenance:** This project is maintained and bug reports -or pull requests will be addressed. There is little activity because -it simply works and no changes are required. +.. image:: https://coveralls.io/repos/omarkohl/pytest-datafiles/badge.svg?branch=master&service=github + :target: https://coveralls.io/github/omarkohl/pytest-datafiles?branch=master -Features -======== +.. image:: https://img.shields.io/pypi/v/pytest-datafiles.svg + :target: https://pypi.python.org/pypi/pytest-datafiles -This plugin allows you to specify one or several files/directories -that are copied to a temporary directory (`tmp_path -`_) before the -execution of the test. This means the original files are not modified -and every test runs on its own version of the same files. -Files/directories can be specified either as *strings* or as -*pathlib.Path* objects. +.. image:: https://codeclimate.com/github/omarkohl/pytest-datafiles/badges/gpa.svg + :target: https://codeclimate.com/github/omarkohl/pytest-datafiles + :alt: Code Climate -To take advantage of the *datafiles* fixture in a test function, add -*datafiles* as one of the test function parameters (per usual with -`pytest `_ fixtures) -and decorate the test function with *@pytest.mark.datafiles(file1, -file2, dir1, dir2, …)*. See the examples below. -The *datafiles* variable in your test function is a pathlib.Path -object (`tmp_path `_) -where the copied files are located. Under Linux systems this will most -likely be some subdirectory of */tmp/*. +`pytest`_ plugin to create a `tmp_path`_ containing a preconfigured set of +files and/or directories. +**Note about maintenance:** This project is maintained and bug reports or pull +requests will be addressed. There is little activity because it simply works and +no changes are required. -Options -======= +Features +-------- -The following options can be specified as keyword arguments (kwargs) -to the *@pytest.mark.datafiles* decorator function: +This plugin allows you to specify one or several files/directories that are +copied to a temporary directory (`tmp_path`_) before the execution of the test. +This means the original files are not modified and every test runs on its own +version of the same files. -* **keep_top_dir:** For all parameters that represent directories, - keep that directory instead of only (recursively) copying its - content. Possible values are *True* or *False*. *False* is the - default value. +Files/directories can be specified either as *strings* or as *pathlib.Path* objects. -* **on_duplicate:** Specify the action to take when duplicate - files/directories are found. Possible values are: *exception*, - *ignore* and *replace*. The default value is *exception*. +To take advantage of the *datafiles* fixture in a test function, add +*datafiles* as one of the test function parameters (per usual with `pytest`_ +fixtures) and decorate the test function with *@pytest.mark.datafiles(file1, +file2, dir1, dir2, ...)*. See the examples below. - * *exception:* An exception is raised instead of copying the - duplicate file/directory. +The *datafiles* variable in your test function is a pathlib.Path object +(`tmp_path`_) where the copied files are located. Under Linux systems this +will most likely be some subdirectory of */tmp/*. - * *ignore:* The second (or subsequent) files/directories with the - same name as the first one are simply ignored (i.e., the first - file/directory with the duplicate name is kept). - * *replace:* The second (or subsequent) files/directories with the - same name replace the previous ones (i.e., the last - file/directory with the duplicate name is kept). +Options +------- + +The following options can be specified as keyword arguments (kwargs) to the +*@pytest.mark.datafiles* decorator function: + +- **keep_top_dir:** For all parameters that represent directories, keep that + directory instead of only (recursively) copying its content. Possible values + are *True* or *False*. *False* is the default value. +- **on_duplicate:** Specify the action to take when duplicate files/directories + are found. Possible values are: *exception*, *ignore* and *replace*. The + default value is *exception*. + + - *exception:* An exception is raised instead of copying the duplicate + file/directory. + - *ignore:* The second (or subsequent) files/directories with the same name + as the first one are simply ignored (i.e., the first file/directory with the + duplicate name is kept). + - *replace:* The second (or subsequent) files/directories with the same name + replace the previous ones (i.e., the last file/directory with the duplicate + name is kept). See below for some *examples*. Installation -============ +------------ -.. code:: bash +.. code-block:: bash - pip install pytest-datafiles + pip install pytest-datafiles Upgrade to 3.0 -============== +-------------- -Version 3 now uses `tmp_path -`_, resulting in -*pathlib.Path* objects instead of *py.path*. +Version 3 now uses `tmp_path`_, resulting in `pathlib.Path` objects +instead of `py.path`. Your tests may need to be adjusted. -.. code:: python - - """Upgrade to v3.""" - import os - from pathlib import Path - - import pytest - import py - - FIXTURE_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - 'test_files', - ) - - FIXTURE_DIR_NEW_STYLE = Path(__file__).parent.resolve() / 'test_files' - - - @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) - def test_convert_to_pypath(datafiles): - """ - If your tests are taking advantage of py.path the simplest change - you can make is at the top of each test convert the pathlib.Path - object back to a py.path . - - Note that it would be better to migrate to pathlib.Path, as shown in - the next example, because py.path is deprecated. - """ - - # changing the type back to py.path as a quick fix - datafiles = py.path.local(str(datafiles)) - - # code remains as before - assert len(datafiles.listdir()) == 1 - assert (datafiles / 'img1.jpg').check(file=1) - - - @pytest.mark.datafiles(FIXTURE_DIR_NEW_STYLE / 'img1.jpg') - def test_update_to_pathlib(datafiles): - """Upgrade code to use `pathlib`. - - Some examples showing `pathlib` style. - """ - - # For demo purpose: this is the old-style - pypath_datafiles = py.path.local(str(datafiles)) - - # old style - assert len(pypath_datafiles.listdir()) == 1 - assert (pypath_datafiles / 'img1.jpg').check(file=1) - - # new style # pylint: disable=R0801 - assert len(list(datafiles.iterdir())) == 1 - assert (datafiles / 'img1.jpg').is_file() - - - @pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'img1.jpg')) - def test_keep_using_str(datafiles): - """Keep using plain `os`. - - Nothing changes. - """ - - path = str(datafiles) - assert len(os.listdir(path)) == 1 - assert os.path.isfile(os.path.join(path, 'img1.jpg')) +.. literalinclude:: tests/examples/example_upgradev3.py + :language: python Usage -===== - -These examples can also be found in *tests/examples*. +----- +These examples can also be found in `tests/examples`. Example 1 ---------- - -One possible use case is when you are running tests on very big files -that are not included or packaged with your tests. For example, your -test files are large video files stored under */opt/big_files/* . You -don’t want your tests modifying the original files, but the files are -required by the tests. You can reference these data files in your test -method as follows: - -.. code:: python - - """Example: Reference files anywhere """ - import os - import pytest +~~~~~~~~~ +One possible use case is when you are running tests on very big files that are +not included or packaged with your tests. For example, your test files are +large video files stored under */opt/big_files/* . You don't want your tests modifying +the original files, but the files are required by the tests. You can reference these +data files in your test method as follows: - @pytest.mark.datafiles('/opt/big_files/film1.mp4') - def test_fast_forward(datafiles): - """Work with a copy of the big file.""" - assert len(list(datafiles.iterdir())) == 1 - assert (datafiles / 'film1.mp4').is_file() - # assert some_operation(datafiles / 'film1.mp4') == expected_result - - - @pytest.mark.datafiles('/opt/big_files/film1.mp4') - def test_fast_forward_alternative(datafiles): - """Work with a copy of the bigfile, using `str`.""" - path = str(datafiles) # Convert from py.path object to path (str) - assert len(os.listdir(path)) == 1 - assert os.path.isfile(os.path.join(path, 'film1.mp4')) - # assert some_operation(os.path.join(path, 'film1.mp4')) == expected_result - +.. literalinclude:: tests/examples/example_1.py + :language: python Example 2 ---------- - -Now for another use case: let’s say in the directory where your tests -are located, you place a directory named *test_files*. Here you have a -lot of images you want to run tests on. By using this plugin, you make -sure the original files under *test_files* are not modified by every -test. +~~~~~~~~~ -.. code:: python - - """Example: make a subset of the files in a dir available.""" - from pathlib import Path - - import pytest - - # Dir containing 8 files - FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'img1.jpg', - FIXTURE_DIR / 'img2.jpg', - FIXTURE_DIR / 'img3.jpg', - ) - def test_find_borders(datafiles): - """Work with a copy of only 3 files.""" - for img in datafiles.iterdir(): - print(img) - # assert process(img) == some_expected_value - - # and only the referenced files are available - assert img.name != 'img4.jpg' - - assert len(list(datafiles.iterdir())) == 3 - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'img4.jpg', - FIXTURE_DIR / 'img5.jpg', - ) - def test_brightness(datafiles): - """Work with a copy of only 2 files.""" - for img in datafiles.iterdir(): - print(img) - # assert process(img) == some_expected_value - - # and only the referenced files are available - assert img.name != 'img3.jpg' - - assert len(list(datafiles.iterdir())) == 2 - - - @pytest.mark.datafiles(FIXTURE_DIR) - def test_resize(datafiles): - """Work with a copy of all files.""" - for img in datafiles.iterdir(): - print(img) - # assert process(img) == some_expected_value - - assert len(list(datafiles.iterdir())) == 8 +Now for another use case: let's say in the directory where your tests are located, you +place a directory named *test_files*. Here you have a lot of images you want to run tests +on. By using this plugin, you make sure the original files under *test_files* are not +modified by every test. +.. literalinclude:: tests/examples/example_2.py + :language: python Example 3 ---------- - -If all (or many) of your tests rely on the same files it can be easier -to define one decorator beforehand and apply it to every test like -this example: - -.. code:: python - - """Example: re-use file selection.""" - from pathlib import Path +~~~~~~~~~ - import pytest +If all (or many) of your tests rely on the same files it can be easier to +define one decorator beforehand and apply it to every test like this example: - FIXTURE_DIR = Path(__file__).parent.resolve() / 'test_files' +.. literalinclude:: tests/examples/example_3.py + :language: python - ALL_IMGS = pytest.mark.datafiles( - FIXTURE_DIR / 'img1.jpg', - FIXTURE_DIR / 'img2.jpg', - FIXTURE_DIR / 'img3.jpg', - FIXTURE_DIR / 'img4.jpg', - FIXTURE_DIR / 'img5.jpg', - FIXTURE_DIR / 'img6.jpg', - FIXTURE_DIR / 'img7.jpg', - FIXTURE_DIR / 'img8.jpg', - ) - - - @ALL_IMGS - def test_something1(datafiles): - """Work with copy of all files.""" - for img in datafiles.iterdir(): - print(img) - # assert process(img) == some_expected_value - - assert len(list(datafiles.iterdir())) == 8 - - # we can do something destructive - (datafiles / 'img3.jpg').unlink() - assert len(list(datafiles.iterdir())) == 7 - - - @ALL_IMGS - def test_something2(datafiles): - """Work with copy of all files.""" - for img in datafiles.iterdir(): - print(img) - # assert process(img) == some_expected_value - - assert len(list(datafiles.iterdir())) == 8 +Example 4 +~~~~~~~~~ - # we can do something destructive - (datafiles / 'img1.jpg').unlink() - assert len(list(datafiles.iterdir())) == 7 +Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the files +(*fileA* and *fileB*). +This example clarifies the options **on_duplicate** and **keep_top_dir**. -Example 4 ---------- - -Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each -containing the files (*fileA* and *fileB*). - -This example clarifies the options **on_duplicate** and -**keep_top_dir**. - -.. code:: python - - """Example: files with same names.""" - from pathlib import Path - - import pytest - - FIXTURE_DIR = Path(__file__).parent.resolve() / '_fixture_files' - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - on_duplicate='ignore', - ) - def test_dir_ignore(datafiles): - """Use files from dir1 (first dir added).""" - assert len(list(datafiles.iterdir())) == 2 - assert (datafiles / 'fileA').exists() - assert (datafiles / 'fileA').read_text() == '1a\n' - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir3', - on_duplicate='ignore', - ) - def test_dir_ignore2(datafiles): - """Use files from dir2 (first dir added).""" - assert len(list(datafiles.iterdir())) == 2 - assert (datafiles / 'fileA').exists() - assert (datafiles / 'fileA').read_text() == '2a\n' - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - on_duplicate='overwrite', - ) - def test_dir_overwrite(datafiles): - """Use files from dir3 (last dir added).""" - assert len(list(datafiles.iterdir())) == 2 - assert (datafiles / 'fileA').exists() - assert (datafiles / 'fileA').read_text() == '3a\n' - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - # on_duplicate='exception' is the default - ) - def test_dir_exception(datafiles): # pylint: disable=W0613 - """Raise exception because of duplicate filename fileA.""" - assert False - - - @pytest.mark.datafiles( - FIXTURE_DIR / 'dir1', - FIXTURE_DIR / 'dir2', - FIXTURE_DIR / 'dir3', - keep_top_dir=True, - ) - def test_dir_keep_top_dir(datafiles): - """Use all files.""" - # 3 subdirs - assert len(list(datafiles.iterdir())) == 3 - # 3 subdirs with each 2 files: 3 + 3*2 - assert len(list(datafiles.glob('**/*'))) == 9 - assert (datafiles / 'dir3' / 'fileA').exists() - assert (datafiles / 'dir3' / 'fileA').read_text() == '3a\n' - +.. literalinclude:: tests/examples/example_4.py + :language: python Example 5 ---------- +~~~~~~~~~ You can also use a str paths. -.. code:: python - - """Example: use `str` paths.""" - import os - import pytest - - FIXTURE_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - 'test_files' - ) - - - @pytest.mark.datafiles( - os.path.join(FIXTURE_DIR, 'img1.jpg'), - os.path.join(FIXTURE_DIR, 'img2.jpg'), - os.path.join(FIXTURE_DIR, 'img3.jpg'), - ) - def test_str(datafiles): - """Work with `str`.""" - assert len(list(datafiles.iterdir())) == 3 +.. literalinclude:: tests/examples/example_5.py + :language: python Contributing -============ +------------ -Contributions are very welcome. Tests can be run with `tox -`_. Please ensure the coverage -stays at least the same before you submit a pull request. +Contributions are very welcome. Tests can be run with `tox`_. Please +ensure the coverage stays at least the same before you submit a pull +request. -To create and upload a new package first update the version number and -then: +To create and upload a new package first update the version number and then: -.. code:: bash +.. code-block:: bash - pip3 install --user -U twine - make clean - make dist - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - # Verify the package is usable - virtualenv -p python3 test-venv - test-venv/bin/pip install pytest - test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles - # Create some test_example.py (e.g. with one of the examples above) - test-venv/bin/pytest test_example.py - # Set the git tag for final release - git tag -a 3.0 - git push --tags - # Upload the package for final release - twine upload dist/* + pip3 install --user -U twine + make clean + make dist + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + # Verify the package is usable + virtualenv -p python3 test-venv + test-venv/bin/pip install pytest + test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles + # Create some test_example.py (e.g. with one of the examples above) + test-venv/bin/pytest test_example.py + # Set the git tag for final release + git tag -a 3.0 + git push --tags + # Upload the package for final release + twine upload dist/* -Finally create a release on GitHub and add the packages from dist/* to -it. +Finally create a release on GitHub and add the packages from dist/* to it. -Of course this will only work if you have the necessary PyPI -credentials for this package. +Of course this will only work if you have the necessary PyPI credentials for +this package. License -======= +------- -Distributed under the terms of the `MIT license -`_, “pytest-datafiles” is free and -open source software. +Distributed under the terms of the `MIT license`_, "pytest-datafiles" is +free and open source software. Issues -====== +------ -If you encounter any problems, please `file an issue -`_ along with a +If you encounter any problems, please `file an issue`_ along with a detailed description. Acknowledgements -================ +---------------- + +Thanks to `@flub`_ for the idea to use `pytest`_ marks to solve the +problem this plugin is trying to solve. + +Some ideas to improve this project were taken from the `Cookiecutter`_ +templates `cookiecutter-pypackage`_ and `cookiecutter-pytest-plugin`_. -Thanks to `@flub `_ for the idea to use -`pytest `_ marks to -solve the problem this plugin is trying to solve. -Some ideas to improve this project were taken from the `Cookiecutter -`_ templates -`cookiecutter-pypackage -`_ and -`cookiecutter-pytest-plugin -`_. +.. _`pytest`: https://docs.pytest.org/en/latest/contents.html +.. _`tmp_path`: https://docs.pytest.org/en/latest/tmp_path.html +.. _`tox`: https://tox.readthedocs.org/en/latest/ +.. _`MIT License`: http://opensource.org/licenses/MIT +.. _`file an issue`: https://github.com/omarkohl/pytest-datafiles/issues +.. _`@flub`: https://github.com/flub +.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter +.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage +.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin diff --git a/docs/readme/README.rst b/docs/readme/README.rst deleted file mode 100644 index a4ee51c..0000000 --- a/docs/readme/README.rst +++ /dev/null @@ -1,218 +0,0 @@ -.. This file will be rendered to the README.rst in the root - -================ -pytest-datafiles -================ - -.. image:: https://img.shields.io/travis/omarkohl/pytest-datafiles.svg - :target: https://travis-ci.org/omarkohl/pytest-datafiles - - -.. image:: https://coveralls.io/repos/omarkohl/pytest-datafiles/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/omarkohl/pytest-datafiles?branch=master - - -.. image:: https://img.shields.io/pypi/v/pytest-datafiles.svg - :target: https://pypi.python.org/pypi/pytest-datafiles - - -.. image:: https://codeclimate.com/github/omarkohl/pytest-datafiles/badges/gpa.svg - :target: https://codeclimate.com/github/omarkohl/pytest-datafiles - :alt: Code Climate - - -`pytest`_ plugin to create a `tmp_path`_ containing a preconfigured set of -files and/or directories. - -**Note about maintenance:** This project is maintained and bug reports or pull -requests will be addressed. There is little activity because it simply works and -no changes are required. - -Features --------- - -This plugin allows you to specify one or several files/directories that are -copied to a temporary directory (`tmp_path`_) before the execution of the test. -This means the original files are not modified and every test runs on its own -version of the same files. - -Files/directories can be specified either as *strings* or as *pathlib.Path* objects. - -To take advantage of the *datafiles* fixture in a test function, add -*datafiles* as one of the test function parameters (per usual with `pytest`_ -fixtures) and decorate the test function with *@pytest.mark.datafiles(file1, -file2, dir1, dir2, ...)*. See the examples below. - -The *datafiles* variable in your test function is a pathlib.Path object -(`tmp_path`_) where the copied files are located. Under Linux systems this -will most likely be some subdirectory of */tmp/*. - - -Options -------- - -The following options can be specified as keyword arguments (kwargs) to the -*@pytest.mark.datafiles* decorator function: - -- **keep_top_dir:** For all parameters that represent directories, keep that - directory instead of only (recursively) copying its content. Possible values - are *True* or *False*. *False* is the default value. -- **on_duplicate:** Specify the action to take when duplicate files/directories - are found. Possible values are: *exception*, *ignore* and *replace*. The - default value is *exception*. - - - *exception:* An exception is raised instead of copying the duplicate - file/directory. - - *ignore:* The second (or subsequent) files/directories with the same name - as the first one are simply ignored (i.e., the first file/directory with the - duplicate name is kept). - - *replace:* The second (or subsequent) files/directories with the same name - replace the previous ones (i.e., the last file/directory with the duplicate - name is kept). - -See below for some *examples*. - - -Installation ------------- - -.. code-block:: bash - - pip install pytest-datafiles - - -Upgrade to 3.0 --------------- - -Version 3 now uses `tmp_path`_, resulting in `pathlib.Path` objects -instead of `py.path`. - -Your tests may need to be adjusted. - -.. literalinclude:: ../../tests/examples/example_upgradev3.py - :language: python - - -Usage ------ - -These examples can also be found in `tests/examples`. - -Example 1 -~~~~~~~~~ - -One possible use case is when you are running tests on very big files that are -not included or packaged with your tests. For example, your test files are -large video files stored under */opt/big_files/* . You don't want your tests modifying -the original files, but the files are required by the tests. You can reference these -data files in your test method as follows: - -.. literalinclude:: ../../tests/examples/example_1.py - :language: python - -Example 2 -~~~~~~~~~ - -Now for another use case: let's say in the directory where your tests are located, you -place a directory named *test_files*. Here you have a lot of images you want to run tests -on. By using this plugin, you make sure the original files under *test_files* are not -modified by every test. - -.. literalinclude:: ../../tests/examples/example_2.py - :language: python - -Example 3 -~~~~~~~~~ - -If all (or many) of your tests rely on the same files it can be easier to -define one decorator beforehand and apply it to every test like this example: - -.. literalinclude:: ../../tests/examples/example_3.py - :language: python - -Example 4 -~~~~~~~~~ - -Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the files -(*fileA* and *fileB*). - -This example clarifies the options **on_duplicate** and **keep_top_dir**. - -.. literalinclude:: ../../tests/examples/example_4.py - :language: python - -Example 5 -~~~~~~~~~ - -You can also use a str paths. - -.. literalinclude:: ../../tests/examples/example_5.py - :language: python - - -Contributing ------------- - -Contributions are very welcome. Tests can be run with `tox`_. Please -ensure the coverage stays at least the same before you submit a pull -request. - -To create and upload a new package first update the version number and then: - -.. code-block:: bash - - pip3 install --user -U twine - make clean - make dist - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - # Verify the package is usable - virtualenv -p python3 test-venv - test-venv/bin/pip install pytest - test-venv/bin/pip install --index-url https://test.pypi.org/simple/ pytest-datafiles - # Create some test_example.py (e.g. with one of the examples above) - test-venv/bin/pytest test_example.py - # Set the git tag for final release - git tag -a 3.0 - git push --tags - # Upload the package for final release - twine upload dist/* - -Finally create a release on GitHub and add the packages from dist/* to it. - -Of course this will only work if you have the necessary PyPI credentials for -this package. - - -License -------- - -Distributed under the terms of the `MIT license`_, "pytest-datafiles" is -free and open source software. - - -Issues ------- - -If you encounter any problems, please `file an issue`_ along with a -detailed description. - - -Acknowledgements ----------------- - -Thanks to `@flub`_ for the idea to use `pytest`_ marks to solve the -problem this plugin is trying to solve. - -Some ideas to improve this project were taken from the `Cookiecutter`_ -templates `cookiecutter-pypackage`_ and `cookiecutter-pytest-plugin`_. - - -.. _`pytest`: https://docs.pytest.org/en/latest/contents.html -.. _`tmp_path`: https://docs.pytest.org/en/latest/tmp_path.html -.. _`tox`: https://tox.readthedocs.org/en/latest/ -.. _`MIT License`: http://opensource.org/licenses/MIT -.. _`file an issue`: https://github.com/omarkohl/pytest-datafiles/issues -.. _`@flub`: https://github.com/flub -.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter -.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage -.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin diff --git a/docs/readme/conf.py b/docs/readme/conf.py deleted file mode 100644 index 43f5d30..0000000 --- a/docs/readme/conf.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Sphinx configuration.""" -from pathlib import Path - -extensions = [ - 'sphinxcontrib.restbuilder', -] - -master_doc = Path(__file__).parent.name.upper() From aba58f775bb1eb4f1570fb43229af8cce813bac8 Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 19 Feb 2023 15:26:48 +0100 Subject: [PATCH 08/11] Dropping generated README --- README.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.rst b/README.rst index a03b492..1bbd317 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,3 @@ -.. This file will be rendered to the README.rst in the root - ================ pytest-datafiles ================ From 3edd8b6d8f2d512e12364b5355e5dc619bc59f7c Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Mon, 20 Feb 2023 01:46:12 +0100 Subject: [PATCH 09/11] Dropping generated README --- tox.ini | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tox.ini b/tox.ini index 20836bc..05a4727 100644 --- a/tox.ini +++ b/tox.ini @@ -30,11 +30,3 @@ deps = commands = flake8 --max-complexity=10 pytest_datafiles.py tests/ pylint pytest_datafiles.py tests/ - -[testenv:doc] -basepython = python3 -deps = - sphinx - sphinxcontrib-restbuilder -commands = - sphinx-build -b rst docs/readme . From cb738d5795bca08bb3fa00a7f68fa3d2c04806df Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Mon, 20 Feb 2023 13:47:30 +0100 Subject: [PATCH 10/11] Makefile help / moving examples. --- Makefile | 9 ++- README.rst | 63 ++++++++++++++----- .../_fixture_files/dir1/fileA | 0 .../_fixture_files/dir1/fileB | 0 .../_fixture_files/dir2/fileA | 0 .../_fixture_files/dir2/fileB | 0 .../_fixture_files/dir3/fileA | 0 .../_fixture_files/dir3/fileB | 0 {tests/examples => examples}/example_1.py | 9 ++- {tests/examples => examples}/example_2.py | 9 ++- {tests/examples => examples}/example_3.py | 6 +- {tests/examples => examples}/example_4.py | 8 ++- {tests/examples => examples}/example_5.py | 0 .../example_upgradev3.py | 0 .../examples => examples}/test_files/img1.jpg | 0 .../examples => examples}/test_files/img2.jpg | 0 .../examples => examples}/test_files/img3.jpg | 0 .../examples => examples}/test_files/img4.jpg | 0 .../examples => examples}/test_files/img5.jpg | 0 .../examples => examples}/test_files/img6.jpg | 0 .../examples => examples}/test_files/img7.jpg | 0 .../examples => examples}/test_files/img8.jpg | 0 tests/examples/__init__.py | 0 tests/test_examples.py | 2 +- tox.ini | 4 +- 25 files changed, 85 insertions(+), 25 deletions(-) rename {tests/examples => examples}/_fixture_files/dir1/fileA (100%) rename {tests/examples => examples}/_fixture_files/dir1/fileB (100%) rename {tests/examples => examples}/_fixture_files/dir2/fileA (100%) rename {tests/examples => examples}/_fixture_files/dir2/fileB (100%) rename {tests/examples => examples}/_fixture_files/dir3/fileA (100%) rename {tests/examples => examples}/_fixture_files/dir3/fileB (100%) rename {tests/examples => examples}/example_1.py (67%) rename {tests/examples => examples}/example_2.py (78%) rename {tests/examples => examples}/example_3.py (86%) rename {tests/examples => examples}/example_4.py (89%) rename {tests/examples => examples}/example_5.py (100%) rename {tests/examples => examples}/example_upgradev3.py (100%) rename {tests/examples => examples}/test_files/img1.jpg (100%) rename {tests/examples => examples}/test_files/img2.jpg (100%) rename {tests/examples => examples}/test_files/img3.jpg (100%) rename {tests/examples => examples}/test_files/img4.jpg (100%) rename {tests/examples => examples}/test_files/img5.jpg (100%) rename {tests/examples => examples}/test_files/img6.jpg (100%) rename {tests/examples => examples}/test_files/img7.jpg (100%) rename {tests/examples => examples}/test_files/img8.jpg (100%) delete mode 100644 tests/examples/__init__.py diff --git a/Makefile b/Makefile index 6be976f..289f0ba 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,16 @@ .PHONY: clean-pyc clean-build docs clean help: + @echo "clean Lint, test, check coverage and package" @echo "clean Remove all build, test, coverage and Python artifacts" @echo "clean-build Remove build artifacts" @echo "clean-pyc Remove Python file artifacts" @echo "clean-test Remove test and coverage artifacts" @echo "lint Check style with Flake8 and Pylint" - @echo "test Run tests quickly with Python 3.11" - @echo "test-all Run tests on every Python version with tox" + @echo "test Run quick tests and those for the example code" + @echo "test-quick Run tests quickly (main code only)with Python 3.11" + @echo "test-example Run tests for the example code" + @echo "test-all Run tests on every Python version with tox and the example" @echo "coverage Check code coverage quickly with Python 3" @echo "dist Package" @@ -31,7 +34,7 @@ clean-test: rm -f .coverage rm -fr htmlcov/ -all: lint test-all coverage dist readme +all: lint test-all coverage dist lint: tox -e lint diff --git a/README.rst b/README.rst index 1bbd317..98ac931 100644 --- a/README.rst +++ b/README.rst @@ -85,16 +85,14 @@ Upgrade to 3.0 Version 3 now uses `tmp_path`_, resulting in `pathlib.Path` objects instead of `py.path`. -Your tests may need to be adjusted. - -.. literalinclude:: tests/examples/example_upgradev3.py - :language: python +Your tests may need to be adjusted. In `examples/example_upgradev3.py` you see some possible +variations. Usage ----- -These examples can also be found in `tests/examples`. +The full code with more details for the examples can be found in `examples/`. Example 1 ~~~~~~~~~ @@ -105,8 +103,14 @@ large video files stored under */opt/big_files/* . You don't want your tests mod the original files, but the files are required by the tests. You can reference these data files in your test method as follows: -.. literalinclude:: tests/examples/example_1.py - :language: python +.. code-block:: python + + # more details in `examples/example_1.py` + + @pytest.mark.datafiles('/opt/big_files/film1.mp4') + def test_fast_forward(datafiles): + # ... + Example 2 ~~~~~~~~~ @@ -116,8 +120,18 @@ place a directory named *test_files*. Here you have a lot of images you want to on. By using this plugin, you make sure the original files under *test_files* are not modified by every test. -.. literalinclude:: tests/examples/example_2.py - :language: python +.. code-block:: python + + # more details in `examples/example_2.py` + + @pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', + ) + def test_find_borders(datafiles): + # ... + Example 3 ~~~~~~~~~ @@ -125,8 +139,20 @@ Example 3 If all (or many) of your tests rely on the same files it can be easier to define one decorator beforehand and apply it to every test like this example: -.. literalinclude:: tests/examples/example_3.py - :language: python +.. code-block:: python + + # more details in `examples/example_3.py` + + ALL_IMGS = pytest.mark.datafiles( + FIXTURE_DIR / 'img1.jpg', + FIXTURE_DIR / 'img2.jpg', + FIXTURE_DIR / 'img3.jpg', + ) + + @ALL_IMGS + def test_something1(datafiles): + # ... + Example 4 ~~~~~~~~~ @@ -136,16 +162,23 @@ Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing the file This example clarifies the options **on_duplicate** and **keep_top_dir**. -.. literalinclude:: tests/examples/example_4.py - :language: python Example 5 ~~~~~~~~~ You can also use a str paths. -.. literalinclude:: tests/examples/example_5.py - :language: python +.. code-block:: python + + # more details in `examples/example_5.py` + + @pytest.mark.datafiles( + os.path.join(FIXTURE_DIR, 'img1.jpg'), + os.path.join(FIXTURE_DIR, 'img2.jpg'), + os.path.join(FIXTURE_DIR, 'img3.jpg'), + ) + def test_str(datafiles): + # ... Contributing diff --git a/tests/examples/_fixture_files/dir1/fileA b/examples/_fixture_files/dir1/fileA similarity index 100% rename from tests/examples/_fixture_files/dir1/fileA rename to examples/_fixture_files/dir1/fileA diff --git a/tests/examples/_fixture_files/dir1/fileB b/examples/_fixture_files/dir1/fileB similarity index 100% rename from tests/examples/_fixture_files/dir1/fileB rename to examples/_fixture_files/dir1/fileB diff --git a/tests/examples/_fixture_files/dir2/fileA b/examples/_fixture_files/dir2/fileA similarity index 100% rename from tests/examples/_fixture_files/dir2/fileA rename to examples/_fixture_files/dir2/fileA diff --git a/tests/examples/_fixture_files/dir2/fileB b/examples/_fixture_files/dir2/fileB similarity index 100% rename from tests/examples/_fixture_files/dir2/fileB rename to examples/_fixture_files/dir2/fileB diff --git a/tests/examples/_fixture_files/dir3/fileA b/examples/_fixture_files/dir3/fileA similarity index 100% rename from tests/examples/_fixture_files/dir3/fileA rename to examples/_fixture_files/dir3/fileA diff --git a/tests/examples/_fixture_files/dir3/fileB b/examples/_fixture_files/dir3/fileB similarity index 100% rename from tests/examples/_fixture_files/dir3/fileB rename to examples/_fixture_files/dir3/fileB diff --git a/tests/examples/example_1.py b/examples/example_1.py similarity index 67% rename from tests/examples/example_1.py rename to examples/example_1.py index 2c9849e..e107c13 100644 --- a/tests/examples/example_1.py +++ b/examples/example_1.py @@ -1,4 +1,11 @@ -"""Example: Reference files anywhere """ +"""Example: Reference files anywhere. + +One possible use case is when you are running tests on very big files that are +not included or packaged with your tests. For example, your test files are +large video files stored under */opt/big_files/* . You don't want your tests +modifying the original files, but the files are required by the tests. + +""" import os import pytest diff --git a/tests/examples/example_2.py b/examples/example_2.py similarity index 78% rename from tests/examples/example_2.py rename to examples/example_2.py index 23b41d3..1044fcf 100644 --- a/tests/examples/example_2.py +++ b/examples/example_2.py @@ -1,4 +1,11 @@ -"""Example: make a subset of the files in a dir available.""" +"""Example: make a subset of the files in a dir available. + +Now for another use case: let's say in the directory where your tests are +located, you place a directory named *test_files*. Here you have a lot of +images you want to run tests on. By using this plugin, you make sure the +original files under *test_files* are not modified by every test. + +""" from pathlib import Path import pytest diff --git a/tests/examples/example_3.py b/examples/example_3.py similarity index 86% rename from tests/examples/example_3.py rename to examples/example_3.py index 2070d4c..13fb982 100644 --- a/tests/examples/example_3.py +++ b/examples/example_3.py @@ -1,4 +1,8 @@ -"""Example: re-use file selection.""" +"""Example: re-use file selection. + +If all (or many) of your tests rely on the same files it can be easier to +define one decorator beforehand and apply it to every test. +""" from pathlib import Path import pytest diff --git a/tests/examples/example_4.py b/examples/example_4.py similarity index 89% rename from tests/examples/example_4.py rename to examples/example_4.py index cd06a51..52085c9 100644 --- a/tests/examples/example_4.py +++ b/examples/example_4.py @@ -1,4 +1,10 @@ -"""Example: files with same names.""" +"""Example: files with same names. + +Imagine you have 3 directories (*dir1*, *dir2*, *dir3*) each containing +the files (*fileA* and *fileB*). + +This example clarifies the options **on_duplicate** and **keep_top_dir**. +""" from pathlib import Path import pytest diff --git a/tests/examples/example_5.py b/examples/example_5.py similarity index 100% rename from tests/examples/example_5.py rename to examples/example_5.py diff --git a/tests/examples/example_upgradev3.py b/examples/example_upgradev3.py similarity index 100% rename from tests/examples/example_upgradev3.py rename to examples/example_upgradev3.py diff --git a/tests/examples/test_files/img1.jpg b/examples/test_files/img1.jpg similarity index 100% rename from tests/examples/test_files/img1.jpg rename to examples/test_files/img1.jpg diff --git a/tests/examples/test_files/img2.jpg b/examples/test_files/img2.jpg similarity index 100% rename from tests/examples/test_files/img2.jpg rename to examples/test_files/img2.jpg diff --git a/tests/examples/test_files/img3.jpg b/examples/test_files/img3.jpg similarity index 100% rename from tests/examples/test_files/img3.jpg rename to examples/test_files/img3.jpg diff --git a/tests/examples/test_files/img4.jpg b/examples/test_files/img4.jpg similarity index 100% rename from tests/examples/test_files/img4.jpg rename to examples/test_files/img4.jpg diff --git a/tests/examples/test_files/img5.jpg b/examples/test_files/img5.jpg similarity index 100% rename from tests/examples/test_files/img5.jpg rename to examples/test_files/img5.jpg diff --git a/tests/examples/test_files/img6.jpg b/examples/test_files/img6.jpg similarity index 100% rename from tests/examples/test_files/img6.jpg rename to examples/test_files/img6.jpg diff --git a/tests/examples/test_files/img7.jpg b/examples/test_files/img7.jpg similarity index 100% rename from tests/examples/test_files/img7.jpg rename to examples/test_files/img7.jpg diff --git a/tests/examples/test_files/img8.jpg b/examples/test_files/img8.jpg similarity index 100% rename from tests/examples/test_files/img8.jpg rename to examples/test_files/img8.jpg diff --git a/tests/examples/__init__.py b/tests/examples/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_examples.py b/tests/test_examples.py index 4847b04..165324b 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -8,7 +8,7 @@ from _pytest.config import ExitCode from _pytest.pytester import Pytester -EXAMPLE_DIR = Path(__file__).parent.resolve() / 'examples' +EXAMPLE_DIR = Path(__file__).parent.parent.resolve() / 'examples' @pytest.fixture diff --git a/tox.ini b/tox.ini index 05a4727..c5ea0f5 100644 --- a/tox.ini +++ b/tox.ini @@ -28,5 +28,5 @@ deps = pylint flake8 commands = - flake8 --max-complexity=10 pytest_datafiles.py tests/ - pylint pytest_datafiles.py tests/ + flake8 --max-complexity=10 pytest_datafiles.py tests/ examples/ + pylint pytest_datafiles.py tests/ examples/ From bd8964481b75cf8cb6038cffa099cdea8d01990f Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Mon, 20 Feb 2023 13:57:10 +0100 Subject: [PATCH 11/11] Updating PHONY targets --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 289f0ba..dd27bd7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -.PHONY: clean-pyc clean-build docs clean +.PHONY: all clean clean-build clean-pyc clean-test lint test test-quick test-example test-all coverage dist help: - @echo "clean Lint, test, check coverage and package" + @echo "all Lint, test, check coverage and package" @echo "clean Remove all build, test, coverage and Python artifacts" @echo "clean-build Remove build artifacts" @echo "clean-pyc Remove Python file artifacts"