From acff4803f3bbb252e8f0b7f9fbe695c98fc0e115 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 26 Oct 2017 08:20:16 +0300 Subject: [PATCH 01/11] Test testing with pytest --- .travis/install.sh | 4 +++- .travis/script.sh | 3 ++- Tests/helper.py | 11 ++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.travis/install.sh b/.travis/install.sh index 694a460e919..001f27a4ac7 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -8,7 +8,9 @@ sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-tk\ libharfbuzz-dev libfribidi-dev pip install cffi -pip install nose +pip install nose # TODO remove +pip install pytest +pip install pytest-cov pip install check-manifest pip install olefile pip install pyroma diff --git a/.travis/script.sh b/.travis/script.sh index e1d52212273..21a70ec7bd8 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -7,7 +7,8 @@ python setup.py clean CFLAGS="-coverage" python setup.py build_ext --inplace coverage run --append --include=PIL/* selftest.py -coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py +# coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py TODO remove +py.test -v --cov PIL --cov-report term Tests pushd /tmp/check-manifest && check-manifest --ignore ".coveragerc,.editorconfig,*.yml,*.yaml,tox.ini" && popd # Docs diff --git a/Tests/helper.py b/Tests/helper.py index 1375eb7e5dd..609db153623 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -42,8 +42,9 @@ def delete_tempfile(self, path): try: ok = self.currentResult.wasSuccessful() except AttributeError: # for nosetests - proxy = self.currentResult - ok = (len(proxy.errors) + len(proxy.failures) == 0) + # proxy = self.currentResult + # ok = (len(proxy.errors) + len(proxy.failures) == 0) + ok = True # TODO pytest if ok: # only clean out tempfiles if test passed @@ -180,7 +181,7 @@ class PillowLeakTestCase(PillowTestCase): # requires unix/osx iterations = 100 # count mem_limit = 512 # k - + def _get_mem_usage(self): """ Gets the RUSAGE memory usage, returns in K. Encapsulates the difference @@ -188,7 +189,7 @@ def _get_mem_usage(self): :returns; memory usage in kilobytes """ - + from resource import getpagesize, getrusage, RUSAGE_SELF mem = getrusage(RUSAGE_SELF).ru_maxrss if sys.platform == 'darwin': @@ -199,7 +200,7 @@ def _get_mem_usage(self): # linux # man 2 getrusage # ru_maxrss (since Linux 2.6.32) - # This is the maximum resident set size used (in kilobytes). + # This is the maximum resident set size used (in kilobytes). return mem # Kb def _test_leak(self, core): From 1ba03059b4d6436c47d545b68d63a022bd658427 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 26 Oct 2017 08:46:19 +0300 Subject: [PATCH 02/11] --cov-append --- .travis/script.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis/script.sh b/.travis/script.sh index 21a70ec7bd8..74c48ea1896 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -6,9 +6,9 @@ coverage erase python setup.py clean CFLAGS="-coverage" python setup.py build_ext --inplace -coverage run --append --include=PIL/* selftest.py -# coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py TODO remove -py.test -v --cov PIL --cov-report term Tests +coverage run --append --include="PIL/*" selftest.py +# coverage run --append --include="PIL/*" -m nose -vx Tests/test_*.py TODO remove +py.test -v --cov PIL --cov-append --cov-report term Tests pushd /tmp/check-manifest && check-manifest --ignore ".coveragerc,.editorconfig,*.yml,*.yaml,tox.ini" && popd # Docs From bfa9c9683211964f645d01b54b3490353a356b9e Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 26 Oct 2017 16:55:13 +0300 Subject: [PATCH 03/11] Run pytest as module --- .travis/install.sh | 7 +++---- .travis/script.sh | 3 +-- requirements.txt | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.travis/install.sh b/.travis/install.sh index 001f27a4ac7..27a342e8601 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -7,14 +7,13 @@ sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-tk\ python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick\ libharfbuzz-dev libfribidi-dev +pip install check-manifest pip install cffi -pip install nose # TODO remove +pip install coverage +pip install olefile pip install pytest pip install pytest-cov -pip install check-manifest -pip install olefile pip install pyroma -pip install coverage # docs only on Python 2.7 if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then pip install -r requirements.txt ; fi diff --git a/.travis/script.sh b/.travis/script.sh index 74c48ea1896..a47307ca570 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -7,8 +7,7 @@ python setup.py clean CFLAGS="-coverage" python setup.py build_ext --inplace coverage run --append --include="PIL/*" selftest.py -# coverage run --append --include="PIL/*" -m nose -vx Tests/test_*.py TODO remove -py.test -v --cov PIL --cov-append --cov-report term Tests +python -m pytest -vx --cov PIL --cov-append --cov-report term Tests pushd /tmp/check-manifest && check-manifest --ignore ".coveragerc,.editorconfig,*.yml,*.yaml,tox.ini" && popd # Docs diff --git a/requirements.txt b/requirements.txt index 213f145ab09..4cb3c090704 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,10 +11,10 @@ docutils jarn.viewdoc Jinja2 MarkupSafe -nose -nose-cov olefile pycodestyle +pytest +pytest-cov pyflakes Pygments pyroma From bf2c171a5e4df13f0bb739770cdf777866e95bd2 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 26 Oct 2017 18:07:34 +0300 Subject: [PATCH 04/11] Use pytest instead of nose --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d27afaa0bb3..7310dd1d15e 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ co: coverage: coverage erase coverage run --parallel-mode --include=PIL/* selftest.py - nosetests --with-cov --cov='PIL/' --cov-report=html Tests/test_*.py + python -m pytest --cov PIL --cov-append --cov-report html Tests # Doesn't combine properly before report, writing report instead of displaying invalid report. rm -r htmlcov || true coverage combine @@ -81,7 +81,7 @@ release-test: $(MAKE) install-req python setup.py develop python selftest.py - nosetests Tests/test_*.py + python -m pytest Tests python setup.py install python test-installed.py check-manifest From 8b3283507879144bd90f3eb645e924364690edb7 Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 29 Oct 2017 15:11:00 +0200 Subject: [PATCH 05/11] Test with coverage on Windows, update 'setup.py test' --- .gitignore | 9 +++++++++ .travis/install.sh | 6 +++--- .travis/script.sh | 4 ++-- Makefile | 7 ++----- appveyor.yml | 9 +++++++-- setup.cfg | 4 ++++ setup.py | 7 ++++++- winbuild/appveyor_install_msys2_deps.sh | 4 ++-- winbuild/build.py | 4 ++-- 9 files changed, 37 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index aa45f946fa7..242f50845a2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__/ *.so # Distribution / packaging +.eggs/ .Python env/ bin/ @@ -69,3 +70,11 @@ docs/_build/ #OS .DS_Store +# JetBrains +.idea + +# Extra test images installed from pillow-depends/test_images +Tests/images/README.md +Tests/images/msp +Tests/images/picins +Tests/images/sunraster diff --git a/.travis/install.sh b/.travis/install.sh index 27a342e8601..8d5e973fb46 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -7,12 +7,12 @@ sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-tk\ python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick\ libharfbuzz-dev libfribidi-dev -pip install check-manifest pip install cffi +pip install check-manifest pip install coverage pip install olefile -pip install pytest -pip install pytest-cov +pip install -U pytest +pip install -U pytest-cov pip install pyroma # docs only on Python 2.7 diff --git a/.travis/script.sh b/.travis/script.sh index a47307ca570..1473ab07925 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -6,8 +6,8 @@ coverage erase python setup.py clean CFLAGS="-coverage" python setup.py build_ext --inplace -coverage run --append --include="PIL/*" selftest.py -python -m pytest -vx --cov PIL --cov-append --cov-report term Tests +python selftest.py +python setup.py test pushd /tmp/check-manifest && check-manifest --ignore ".coveragerc,.editorconfig,*.yml,*.yaml,tox.ini" && popd # Docs diff --git a/Makefile b/Makefile index 7310dd1d15e..8e60024aec0 100644 --- a/Makefile +++ b/Makefile @@ -15,12 +15,9 @@ co: done coverage: - coverage erase - coverage run --parallel-mode --include=PIL/* selftest.py - python -m pytest --cov PIL --cov-append --cov-report html Tests -# Doesn't combine properly before report, writing report instead of displaying invalid report. + python selftest.py + python setup.py test rm -r htmlcov || true - coverage combine coverage report doc: diff --git a/appveyor.yml b/appveyor.yml index d966c88ffef..a34d4690aec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -74,8 +74,13 @@ build_script: test_script: - cd c:\pillow -- '%PYTHON%\%PIP_DIR%\pip.exe install nose' -- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' +- '%PYTHON%\%PIP_DIR%\pip.exe install pytest pytest-cov' +- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov-append --cov-report term --cov-report xml Tests' +#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest? + +after_test: +- pip install codecov +- codecov --file coverage.xml --name %PYTHON% matrix: fast_finish: true diff --git a/setup.cfg b/setup.cfg index 0c9e0fc1447..fb2d177d664 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,6 @@ +[aliases] +test=pytest [metadata] license_file = LICENSE +[tool:pytest] +addopts = -vx --cov PIL --cov-append --cov-report term Tests diff --git a/setup.py b/setup.py index 58a282ac300..1902d937307 100755 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ class RequiredDependencyException(Exception): pass PLATFORM_MINGW = 'mingw' in ccompiler.get_default_compiler() PLATFORM_PYPY = hasattr(sys, 'pypy_version_info') + def _dbg(s, tp=None): if DEBUG: if tp: @@ -748,6 +749,9 @@ def debug_build(): return hasattr(sys, 'gettotalrefcount') +needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) +pytest_runner = ['pytest-runner'] if needs_pytest else [] + try: setup(name=NAME, version=PILLOW_VERSION, @@ -779,7 +783,8 @@ def debug_build(): include_package_data=True, packages=find_packages(), scripts=glob.glob("Scripts/*.py"), - test_suite='nose.collector', + setup_requires=pytest_runner, + tests_require=['pytest'], keywords=["Imaging", ], license='Standard PIL License', zip_safe=not (debug_build() or PLATFORM_MINGW), ) diff --git a/winbuild/appveyor_install_msys2_deps.sh b/winbuild/appveyor_install_msys2_deps.sh index 52b81443324..b13dc9e98b0 100644 --- a/winbuild/appveyor_install_msys2_deps.sh +++ b/winbuild/appveyor_install_msys2_deps.sh @@ -7,5 +7,5 @@ pacman -S --noconfirm mingw32/mingw-w64-i686-python3 \ mingw32/mingw-w64-i686-python2-setuptools \ mingw-w64-i686-libjpeg-turbo -/mingw32/bin/pip install nose olefile -/mingw32/bin/pip3 install nose olefile +/mingw32/bin/pip install pytest pytest-cov olefile +/mingw32/bin/pip3 install pytest pytest-cov olefile diff --git a/winbuild/build.py b/winbuild/build.py index 3d6c6e57f54..859a4027787 100755 --- a/winbuild/build.py +++ b/winbuild/build.py @@ -16,7 +16,7 @@ def setup_vms(): for arch in ('', X64_EXT): ret.append("virtualenv -p c:/Python%s%s/python.exe --clear %s%s%s" % (py, arch, VIRT_BASE, py, arch)) - ret.append(r"%s%s%s\Scripts\pip.exe install nose" % + ret.append(r"%s%s%s\Scripts\pip.exe install pytest pytest-cov" % (VIRT_BASE, py, arch)) return "\n".join(ret) @@ -76,7 +76,7 @@ def build_one(py_ver, compiler): args['executable'] = "python.exe" if 'EXECUTABLE' in os.environ: args['executable'] = "%EXECUTABLE%" - + args['py_ver'] = py_ver if '34' in py_ver: args['tcl_ver'] = '86' From d954554015b9d57672a11b88437f9436893b3a40 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 1 Nov 2017 22:29:45 +0200 Subject: [PATCH 06/11] No need for --cov-append --- appveyor.yml | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a34d4690aec..94886c8b62e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -75,7 +75,7 @@ build_script: test_script: - cd c:\pillow - '%PYTHON%\%PIP_DIR%\pip.exe install pytest pytest-cov' -- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov-append --cov-report term --cov-report xml Tests' +- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov-report term --cov-report xml Tests' #- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest? after_test: diff --git a/setup.cfg b/setup.cfg index fb2d177d664..4a133839622 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,4 +3,4 @@ test=pytest [metadata] license_file = LICENSE [tool:pytest] -addopts = -vx --cov PIL --cov-append --cov-report term Tests +addopts = -vx --cov PIL --cov-report term Tests From c58b51d3c615709c35d4c590ab8cf87aa33d424e Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 1 Nov 2017 23:31:24 +0200 Subject: [PATCH 07/11] Update test instructions --- Tests/README.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Tests/README.rst b/Tests/README.rst index 0985e0f260c..f0118c62941 100644 --- a/Tests/README.rst +++ b/Tests/README.rst @@ -8,7 +8,7 @@ Dependencies Install:: - pip install coverage nose + pip install pytest pytest-cov Execution --------- @@ -21,12 +21,11 @@ To run an individual test:: Run all the tests from the root of the Pillow source distribution:: - nosetests -vx Tests/test_*.py + pytest -vx Tests Or with coverage:: - coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py - coverage report + pytest -vx --cov PIL --cov-report term Tests coverage html open htmlcov/index.html @@ -39,6 +38,3 @@ To run an individual test:: Run all the tests from the root of the Pillow source distribution:: ./test-installed.py - - - From 13ebc612274d540ceaac5994650b15636612dbdf Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 6 Nov 2017 18:40:23 +0200 Subject: [PATCH 08/11] Update with pytest --- test-installed.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/test-installed.py b/test-installed.py index c5aff1360c4..7269b3494a2 100755 --- a/test-installed.py +++ b/test-installed.py @@ -1,8 +1,8 @@ #!/usr/bin/env python -import nose import os import sys -import glob + +import pytest # monkey with the path, removing the local directory but adding the Tests/ # directory for helper.py and the other local imports there. @@ -13,23 +13,20 @@ # if there's no test selected (mostly) choose a working default. # Something is required, because if we import the tests from the local # directory, once again, we've got the non-installed PIL in the way -for arg in sys.argv[1:]: - if '.py' in arg: +for i, arg in enumerate(sys.argv[1:]): + print(i, arg) + if arg.startswith('Tests/test_') and arg.endswith('.py'): + print("bingo") + sys.argv.insert(i+1, '-k') break else: - sys.argv.extend(glob.glob('Tests/test*.py')) - -# Make sure that nose doesn't muck with our paths. -if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv): - sys.argv.insert(1, '--no-path-adjustment') + sys.argv.append('Tests') -if 'NOSE_PROCESSES' not in os.environ: - for arg in sys.argv: - if '--processes' in arg: - break - else: # for - sys.argv.insert(1, '--processes=-1') # -1 == number of cores - sys.argv.insert(1, '--process-timeout=30') +# for arg in sys.argv: +# if '-n' in arg or '--numprocesses' in arg: +# break +# else: # for +# sys.argv.extend(['--numprocesses' ,'auto']) # auto-detect number of CPUs if __name__ == '__main__': - nose.main() + pytest.main() From 821729506650e7a9178a47e78424a9be9c619bab Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 7 Nov 2017 12:35:46 +0200 Subject: [PATCH 09/11] Remove unused/unrunnable profile-installed.py --- profile-installed.py | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100755 profile-installed.py diff --git a/profile-installed.py b/profile-installed.py deleted file mode 100755 index e3a04c21cb8..00000000000 --- a/profile-installed.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -import os -import sys -import glob - -import profile - -# monkey with the path, removing the local directory but adding the Tests/ -# directory for helper.py and the other local imports there. - -del(sys.path[0]) -sys.path.insert(0, os.path.abspath('./Tests')) - -# if there's no test selected (mostly) choose a working default. -# Something is required, because if we import the tests from the local -# directory, once again, we've got the non-installed PIL in the way -if len(sys.argv) == 1: - sys.argv.extend(glob.glob('Tests/test*.py')) - -# Make sure that nose doesn't muck with our paths. -if ('--no-path-adjustment' not in sys.argv) and ('-P' not in sys.argv): - sys.argv.insert(1, '--no-path-adjustment') - -if __name__ == '__main__': - profile.run("nose.main()", sort=2) From a05837099b1eee12c9021b823dabe11676168761 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 15 Nov 2017 22:22:52 +0200 Subject: [PATCH 10/11] Test with multiprocessing --- test-installed.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test-installed.py b/test-installed.py index 7269b3494a2..35a3b4ccc6c 100755 --- a/test-installed.py +++ b/test-installed.py @@ -14,19 +14,18 @@ # Something is required, because if we import the tests from the local # directory, once again, we've got the non-installed PIL in the way for i, arg in enumerate(sys.argv[1:]): - print(i, arg) if arg.startswith('Tests/test_') and arg.endswith('.py'): - print("bingo") sys.argv.insert(i+1, '-k') break else: sys.argv.append('Tests') -# for arg in sys.argv: -# if '-n' in arg or '--numprocesses' in arg: -# break -# else: # for -# sys.argv.extend(['--numprocesses' ,'auto']) # auto-detect number of CPUs +for arg in sys.argv: + if '-n' in arg or '--numprocesses' in arg: + break +else: # for + sys.argv.extend(['--numprocesses', 'auto']) # auto-detect number of CPUs + if __name__ == '__main__': pytest.main() From 0e16233848cff28a061d9c91bc2d73d8a1fde2dc Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 16 Nov 2017 18:27:07 +0200 Subject: [PATCH 11/11] 'Make test' calls 'pytest -qq' directly --- Makefile | 2 +- test-installed.py | 31 ------------------------------- 2 files changed, 1 insertion(+), 32 deletions(-) delete mode 100755 test-installed.py diff --git a/Makefile b/Makefile index 8e60024aec0..7d9d3447205 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ sdist: python setup.py sdist --format=gztar test: - python test-installed.py + pytest -qq # https://docs.python.org/2/distutils/packageindex.html#the-pypirc-file upload-test: diff --git a/test-installed.py b/test-installed.py deleted file mode 100755 index 35a3b4ccc6c..00000000000 --- a/test-installed.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -import pytest - -# monkey with the path, removing the local directory but adding the Tests/ -# directory for helper.py and the other local imports there. - -del(sys.path[0]) -sys.path.insert(0, os.path.abspath('./Tests')) - -# if there's no test selected (mostly) choose a working default. -# Something is required, because if we import the tests from the local -# directory, once again, we've got the non-installed PIL in the way -for i, arg in enumerate(sys.argv[1:]): - if arg.startswith('Tests/test_') and arg.endswith('.py'): - sys.argv.insert(i+1, '-k') - break -else: - sys.argv.append('Tests') - -for arg in sys.argv: - if '-n' in arg or '--numprocesses' in arg: - break -else: # for - sys.argv.extend(['--numprocesses', 'auto']) # auto-detect number of CPUs - - -if __name__ == '__main__': - pytest.main()