switch test runner from nose to pytest

This commit is contained in:
Bastien Gérard 2019-08-25 15:21:30 +03:00
parent ecefa05e03
commit bbfa978861
6 changed files with 87 additions and 18 deletions

View File

@ -63,8 +63,8 @@ install:
- pip install flake8 flake8-import-order
- pip install tox # tox 3.11.0 has requirement virtualenv>=14.0.0
- pip install virtualenv # virtualenv>=14.0.0 has dropped Python 3.2 support (and pypy3 is based on py32)
# Install the tox venv.
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -e test
# Install the tox venv (we make pytest avoid running the test by giving a bad pattern)
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder"
# Install black for Python v3.7 only.
- if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then pip install black; fi
@ -76,7 +76,7 @@ before_script:
- mongo --eval 'db.version();' # Make sure mongo is awake
script:
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- --with-coverage
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') #-- --with-coverage
# For now only submit coveralls for Python v2.7. Python v3.x currently shows
# 0% coverage. That's caused by 'use_2to3', which builds the py3-compatible

View File

@ -116,7 +116,8 @@ Some simple examples of what MongoEngine code looks like:
Tests
=====
To run the test suite, ensure you are running a local instance of MongoDB on
the standard port and have ``nose`` installed. Then, run ``python setup.py nosetests``.
the standard port and have ``pytest`` installed. Then, run ``python setup.py test``
or simply ``pytest``.
To run the test suite on every supported Python and PyMongo version, you can
use ``tox``. You'll need to make sure you have each supported Python version
@ -129,16 +130,14 @@ installed in your environment and then:
# Run the test suites
$ tox
If you wish to run a subset of tests, use the nosetests convention:
If you wish to run a subset of tests, use the pytest convention:
.. code-block:: shell
# Run all the tests in a particular test file
$ python setup.py nosetests --tests tests/fields/fields.py
$ pytest tests/fields/test_fields.py
# Run only particular test class in that file
$ python setup.py nosetests --tests tests/fields/fields.py:FieldTest
# Use the -s option if you want to print some debug statements or use pdb
$ python setup.py nosetests --tests tests/fields/fields.py:FieldTest -s
$ pytest tests/fields/test_fields.py::TestField
Community
=========

View File

@ -1,11 +1,10 @@
[nosetests]
verbosity=2
detailed-errors=1
#tests=tests
cover-package=mongoengine
[flake8]
ignore=E501,F401,F403,F405,I201,I202,W504, W605, W503
exclude=build,dist,docs,venv,venv3,.tox,.eggs,tests
max-complexity=47
application-import-names=mongoengine,tests
[tool:pytest]
# Limits the discovery to tests directory
# avoids that it runs for instance the benchmark
testpaths = tests

View File

@ -1,6 +1,9 @@
import os
import sys
from pkg_resources import normalize_path
from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand
# Hack to silence atexit traceback in newer python versions
try:
@ -24,6 +27,65 @@ def get_version(version_tuple):
return ".".join(map(str, version_tuple))
class PyTest(TestCommand):
"""Will force pytest to search for tests inside the build directory
for 2to3 converted code (used by tox), instead of the current directory.
Required as long as we need 2to3
Known Limitation: https://tox.readthedocs.io/en/latest/example/pytest.html#known-issues-and-limitations
Source: https://www.hackzine.org/python-testing-with-pytest-and-2to3-plus-tox-and-travis-ci.html
"""
# https://pytest.readthedocs.io/en/2.7.3/goodpractises.html#integration-with-setuptools-test-commands
# Allows to provide pytest command arguments through the test runner command `python setup.py test`
# e.g: `python setup.py test -a "-k=test"`
user_options = [("pytest-args=", "a", "Arguments to pass to py.test")]
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = ""
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = ["tests"]
self.test_suite = True
def run_tests(self):
# import here, cause outside the eggs aren't loaded
from pkg_resources import _namespace_packages
import pytest
# Purge modules under test from sys.modules. The test loader will
# re-import them from the build location. Required when 2to3 is used
# with namespace packages.
if sys.version_info >= (3,) and getattr(self.distribution, "use_2to3", False):
print("Hack for 2to3", self.test_args)
module = self.test_args[-1].split(".")[0]
if module in _namespace_packages:
del_modules = []
if module in sys.modules:
del_modules.append(module)
module += "."
for name in sys.modules:
if name.startswith(module):
del_modules.append(name)
map(sys.modules.__delitem__, del_modules)
# Run on the build directory for 2to3-built code
# This will prevent the old 2.x code from being found
# by py.test discovery mechanism, that apparently
# ignores sys.path..
ei_cmd = self.get_finalized_command("egg_info")
self.test_args = [normalize_path(ei_cmd.egg_base)]
print(self.test_args, self.pytest_args)
cmd_args = self.test_args + ([self.pytest_args] if self.pytest_args else [])
print(cmd_args)
errno = pytest.main(cmd_args)
sys.exit(errno)
# Dirty hack to get version number from monogengine/__init__.py - we can't
# import it as it depends on PyMongo and PyMongo isn't installed until this
# file is read
@ -51,7 +113,7 @@ CLASSIFIERS = [
extra_opts = {
"packages": find_packages(exclude=["tests", "tests.*"]),
"tests_require": ["nose", "coverage==4.2", "blinker", "Pillow>=2.0.0"],
"tests_require": ["pytest<5.0", "coverage==4.2", "blinker", "Pillow>=2.0.0"],
}
if sys.version_info[0] == 3:
extra_opts["use_2to3"] = True
@ -79,6 +141,6 @@ setup(
platforms=["any"],
classifiers=CLASSIFIERS,
install_requires=["pymongo>=3.4", "six"],
test_suite="nose.collector",
cmdclass={"test": PyTest},
**extra_opts
)

9
tests/test_ci.py Normal file
View File

@ -0,0 +1,9 @@
def test_ci_placeholder():
# This empty test is used within the CI to
# setup the tox venv without running the test suite
# if we simply skip all test with pytest -k=wrong_pattern
# pytest command would return with exit_code=5 (i.e "no tests run")
# making travis fail
# this empty test is the recommended way to handle this
# as described in https://github.com/pytest-dev/pytest/issues/2393
pass

View File

@ -3,7 +3,7 @@ envlist = {py27,py35,pypy,pypy3}-{mg34,mg36}
[testenv]
commands =
python setup.py nosetests {posargs}
python setup.py test {posargs}
deps =
nose
mg34: pymongo>=3.4,<3.5