Merge pull request #2157 from bagerard/switch_pytest

Switch to pytest as runner
This commit is contained in:
Bastien Gérard 2019-10-31 22:50:39 +01:00 committed by GitHub
commit aa6ff8c84a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 123 additions and 53 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
# tox dryrun to setup the tox venv (we run a mock test).
- 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,13 +76,13 @@ 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/') -- -a "--cov=mongoengine"
# 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
# code in a separate dir and runs tests on that.
after_success:
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then coveralls --verbose; else echo "coveralls only sent for py27"; fi
notifications:
irc: irc.freenode.org#mongoengine

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

@ -19,6 +19,7 @@ Development
- From now on keyword arguments (e.g. ``Doc(field_name=value)``) are required.
- Fix updating/modifying/deleting/reloading a document that's sharded by a field with ``db_field`` specified. #2125
- ``ListField`` now accepts an optional ``max_length`` parameter. #2110
- Switch from nosetest to pytest as test runner #2114
- The codebase is now formatted using ``black``. #2109
- In bulk write insert, the detailed error message would raise in exception.

View File

@ -11,7 +11,8 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
import os
import sys
import sphinx_rtd_theme

View File

@ -247,8 +247,8 @@ class query_counter(object):
- self._ctx_query_counter
)
self._ctx_query_counter += (
1
) # Account for the query we just issued to gather the information
1 # Account for the query we just issued to gather the information
)
return count

View File

@ -1193,9 +1193,7 @@ class BaseQuerySet(object):
validate_read_preference("read_preference", read_preference)
queryset = self.clone()
queryset._read_preference = read_preference
queryset._cursor_obj = (
None
) # we need to re-create the cursor object whenever we apply read_preference
queryset._cursor_obj = None # we need to re-create the cursor object whenever we apply read_preference
return queryset
def scalar(self, *fields):

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,62 @@ 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 argument through the test runner command `python setup.py test`
# e.g: `python setup.py test -a "-k=test"`
# This only works for 1 argument though
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):
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)]
cmd_args = self.test_args + ([self.pytest_args] if self.pytest_args else [])
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 +110,13 @@ 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",
"pytest-cov",
"coverage<5.0", # recent coverage switched to sqlite format for the .coverage file which isn't handled properly by coveralls
"blinker",
"Pillow>=2.0.0",
],
}
if sys.version_info[0] == 3:
extra_opts["use_2to3"] = True
@ -79,6 +144,6 @@ setup(
platforms=["any"],
classifiers=CLASSIFIERS,
install_requires=["pymongo>=3.4", "six"],
test_suite="nose.collector",
cmdclass={"test": PyTest},
**extra_opts
)

View File

@ -1615,7 +1615,7 @@ class TestInstance(MongoDBTestCase):
self.assertEqual(person.active, False)
def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop_embedded_doc(
self
self,
):
# Refers to Issue #1685
class EmbeddedChildModel(EmbeddedDocument):
@ -1629,7 +1629,7 @@ class TestInstance(MongoDBTestCase):
self.assertEqual(changed_fields, [])
def test__get_changed_fields_same_ids_reference_field_does_not_enters_infinite_loop_different_doc(
self
self,
):
# Refers to Issue #1685
class User(Document):

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import datetime
import math
import itertools
import math
import re
from mongoengine import *

View File

@ -1,17 +1,15 @@
# -*- coding: utf-8 -*-
from mongoengine import (
Document,
StringField,
ValidationError,
EmbeddedDocument,
EmbeddedDocumentField,
InvalidQueryError,
LookUpError,
IntField,
GenericEmbeddedDocumentField,
IntField,
InvalidQueryError,
ListField,
EmbeddedDocumentListField,
ReferenceField,
LookUpError,
StringField,
ValidationError,
)
from tests.utils import MongoDBTestCase

View File

@ -79,7 +79,7 @@ class TestField(MongoDBTestCase):
self.assertEqual(data_to_be_saved, ["age", "created", "day", "name", "userid"])
def test_custom_field_validation_raise_deprecated_error_when_validation_return_something(
self
self,
):
# Covers introduction of a breaking change in the validation parameter (0.18)
def _not_empty(z):
@ -202,7 +202,7 @@ class TestField(MongoDBTestCase):
self.assertEqual(data_to_be_saved, ["age", "created", "userid"])
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_strict_doc(
self
self,
):
"""List field with default can be set to the empty list (strict)"""
# Issue #1733
@ -216,7 +216,7 @@ class TestField(MongoDBTestCase):
self.assertEqual(reloaded.x, [])
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_dyn_doc(
self
self,
):
"""List field with default can be set to the empty list (dynamic)"""
# Issue #1733
@ -1245,7 +1245,7 @@ class TestField(MongoDBTestCase):
self.assertEqual(a.b.c.txt, "hi")
def test_embedded_document_field_cant_reference_using_a_str_if_it_does_not_exist_yet(
self
self,
):
raise SkipTest(
"Using a string reference in an EmbeddedDocumentField does not work if the class isnt registerd yet"

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from bson import SON, DBRef
from bson import DBRef, SON
from mongoengine import *

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

@ -1,7 +1,7 @@
import unittest
from mongoengine.common import _import_class
from mongoengine import Document
from mongoengine.common import _import_class
class TestCommon(unittest.TestCase):

View File

@ -168,7 +168,7 @@ class ConnectionTest(unittest.TestCase):
)
def test_connect_fails_if_similar_connection_settings_arent_defined_the_same_way(
self
self,
):
"""Intended to keep the detecton function simple but robust"""
db_name = "mongoenginetest"

View File

@ -3,11 +3,11 @@ import unittest
from mongoengine import *
from mongoengine.connection import get_db
from mongoengine.context_managers import (
switch_db,
switch_collection,
no_sub_classes,
no_dereference,
no_sub_classes,
query_counter,
switch_collection,
switch_db,
)
from mongoengine.pymongo_support import count_documents

View File

@ -2,7 +2,7 @@ import unittest
from six import iterkeys
from mongoengine import Document
from mongoengine.base.datastructures import StrictDict, BaseList, BaseDict
from mongoengine.base.datastructures import BaseDict, BaseList, StrictDict
class DocumentStub(object):
@ -20,8 +20,8 @@ class TestBaseDict(unittest.TestCase):
fake_doc = DocumentStub()
base_list = BaseDict(dict_items, instance=None, name="my_name")
base_list._instance = (
fake_doc
) # hack to inject the mock, it does not work in the constructor
fake_doc # hack to inject the mock, it does not work in the constructor
)
return base_list
def test___init___(self):
@ -156,8 +156,8 @@ class TestBaseList(unittest.TestCase):
fake_doc = DocumentStub()
base_list = BaseList(list_items, instance=None, name="my_name")
base_list._instance = (
fake_doc
) # hack to inject the mock, it does not work in the constructor
fake_doc # hack to inject the mock, it does not work in the constructor
)
return base_list
def test___init___(self):

View File

@ -1,7 +1,7 @@
import unittest
from pymongo import ReadPreference
from pymongo import MongoClient
from pymongo import ReadPreference
import mongoengine
from mongoengine.connection import ConnectionFailure

View File

@ -1,5 +1,5 @@
import unittest
import re
import unittest
from mongoengine.base.utils import LazyRegexCompiler

View File

@ -4,7 +4,7 @@ import unittest
from nose.plugins.skip import SkipTest
from mongoengine import connect
from mongoengine.connection import get_db, disconnect_all
from mongoengine.connection import disconnect_all, get_db
from mongoengine.mongodb_support import get_mongodb_version

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