Merge pull request #2157 from bagerard/switch_pytest
Switch to pytest as runner
This commit is contained in:
commit
aa6ff8c84a
@ -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
|
||||
|
11
README.rst
11
README.rst
@ -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
|
||||
=========
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
11
setup.cfg
11
setup.cfg
@ -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
|
||||
|
69
setup.py
69
setup.py
@ -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
|
||||
)
|
||||
|
@ -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):
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
import math
|
||||
import itertools
|
||||
import math
|
||||
import re
|
||||
|
||||
from mongoengine import *
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
9
tests/test_ci.py
Normal 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
|
@ -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):
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
import unittest
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from mongoengine.base.utils import LazyRegexCompiler
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user