Skip to content

Commit bcf79f6

Browse files
authored
Merge pull request #397 from MongoEngine/pytest
Tests refactoring. Moving to pytest engine
2 parents de60f4a + 60b47e4 commit bcf79f6

15 files changed

+944
-928
lines changed

README.rst

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ You can install this package using pypi: ``pip install flask-mongoengine``
2626
Tests
2727
=====
2828
To run the test suite, ensure you are running a local copy of Flask-MongoEngine
29-
and run: ``python setup.py nosetests``.
29+
and simply run: ``pytest``.
3030

3131
To run the test suite on every supported versions of Python, PyPy and MongoEngine you can use ``tox``.
3232
Ensure tox and each supported Python, PyPy versions are installed in your environment:
@@ -38,11 +38,7 @@ Ensure tox and each supported Python, PyPy versions are installed in your enviro
3838
# Run the test suites
3939
$ tox
4040
41-
To run a single or selected test suits, use the nosetest convention. E.g.
42-
43-
.. code-block:: shell
44-
45-
$ python setup.py nosetests --tests tests/example_test.py:ExampleTestClass.example_test_method
41+
To run a single or selected test suits, use pytest `-k` option.
4642

4743
Contributing
4844
============

requirements-dev.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ black
55
pre-commit
66
pytest
77
pytest-cov
8-
nose

setup.cfg

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,10 @@
1-
[nosetests]
2-
rednose = 1
3-
verbosity = 2
4-
detailed-errors = 1
5-
cover-erase = 1
6-
cover-branches = 1
7-
cover-package = flask_mongoengine
8-
tests = tests
9-
101
[tool:pytest]
112
addopts = --cov=flask_mongoengine --cov-config=setup.cfg
123
testpaths = tests
134
env_override_existing_values = 1
14-
filterwarnings =
15-
ignore::UserWarning
16-
ignore::DeprecationWarning
17-
ignore::PendingDeprecationWarning
185

196
[flake8]
207
ignore=E501,F403,F405,I201,W503,E203
21-
max-line-length = 90
8+
max-line-length=90
229
exclude=build,dist,docs,examples,venv,.tox,.eggs
2310
max-complexity=17

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_version(version_tuple):
3232
version_line = list(filter(lambda l: l.startswith("VERSION"), open(init)))[0]
3333
version = get_version(eval(version_line.split("=")[-1]))
3434

35-
test_requirements = ["coverage", "nose", "pytest", "pytest-cov"]
35+
test_requirements = ["coverage", "pytest", "pytest-cov"]
3636

3737
setup(
3838
name="flask-mongoengine",

tests/__init__.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +0,0 @@
1-
import unittest
2-
3-
import flask
4-
import mongoengine
5-
6-
7-
class FlaskMongoEngineTestCase(unittest.TestCase):
8-
"""Parent class of all test cases"""
9-
10-
def setUp(self):
11-
self.app = flask.Flask(__name__)
12-
self.app.config["MONGODB_DB"] = "test_db"
13-
self.app.config["TESTING"] = True
14-
self.ctx = self.app.app_context()
15-
self.ctx.push()
16-
# Mongoengine keep a global state of the connections that must be
17-
# reset before each test.
18-
# Given it doesn't expose any method to get the list of registered
19-
# connections, we have to do the cleaning by hand...
20-
mongoengine.connection._connection_settings.clear()
21-
mongoengine.connection._connections.clear()
22-
mongoengine.connection._dbs.clear()
23-
24-
def tearDown(self):
25-
self.ctx.pop()

tests/conftest.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from datetime import datetime
2+
3+
import mongoengine
4+
import pytest
5+
from flask import Flask
6+
7+
from flask_mongoengine import MongoEngine
8+
9+
10+
@pytest.fixture()
11+
def app():
12+
app = Flask(__name__)
13+
app.config["TESTING"] = True
14+
app.config["WTF_CSRF_ENABLED"] = False
15+
16+
with app.app_context():
17+
yield app
18+
19+
mongoengine.connection.disconnect_all()
20+
21+
22+
@pytest.fixture()
23+
def db(app):
24+
app.config["MONGODB_HOST"] = "mongodb://localhost:27017/flask_mongoengine_test_db"
25+
test_db = MongoEngine(app)
26+
db_name = test_db.connection.get_database("flask_mongoengine_test_db").name
27+
28+
if not db_name.endswith("_test_db"):
29+
raise RuntimeError(
30+
f"DATABASE_URL must point to testing db, not to master db ({db_name})"
31+
)
32+
33+
# Clear database before tests, for cases when some test failed before.
34+
test_db.connection.drop_database(db_name)
35+
36+
yield test_db
37+
38+
# Clear database after tests, for graceful exit.
39+
test_db.connection.drop_database(db_name)
40+
41+
42+
@pytest.fixture()
43+
def todo(db):
44+
class Todo(db.Document):
45+
title = mongoengine.StringField(max_length=60)
46+
text = mongoengine.StringField()
47+
done = mongoengine.BooleanField(default=False)
48+
pub_date = mongoengine.DateTimeField(default=datetime.utcnow)
49+
comments = mongoengine.ListField(mongoengine.StringField())
50+
comment_count = mongoengine.IntField()
51+
52+
return Todo

tests/test_base.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Tests for base MongoEngine class."""
2+
from flask_mongoengine import MongoEngine
3+
import pytest
4+
5+
6+
def test_mongoengine_class__should_raise_type_error__if_config_not_dict():
7+
"""MongoEngine will handle None values, but will pass anything else as app."""
8+
input_value = "Not dict type"
9+
with pytest.raises(TypeError) as error:
10+
MongoEngine(input_value)
11+
assert str(error.value) == "Invalid Flask application instance"
12+
13+
14+
@pytest.mark.parametrize("input_value", [None, "Not dict type"])
15+
def test_init_app__should_raise_type_error__if_config_not_dict(input_value):
16+
db = MongoEngine()
17+
with pytest.raises(TypeError) as error:
18+
db.init_app(input_value)
19+
assert str(error.value) == "Invalid Flask application instance"

tests/test_basic_app.py

Lines changed: 32 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,45 @@
1-
import datetime
2-
31
import flask
2+
import pytest
43
from bson import ObjectId
54

6-
from flask_mongoengine import MongoEngine
7-
from tests import FlaskMongoEngineTestCase
8-
9-
10-
class BasicAppTestCase(FlaskMongoEngineTestCase):
11-
def setUp(self):
12-
super(BasicAppTestCase, self).setUp()
13-
db = MongoEngine()
14-
15-
class Todo(db.Document):
16-
title = db.StringField(max_length=60)
17-
text = db.StringField()
18-
done = db.BooleanField(default=False)
19-
pub_date = db.DateTimeField(default=datetime.datetime.now)
20-
21-
db.init_app(self.app)
22-
23-
Todo.drop_collection()
24-
self.Todo = Todo
25-
26-
@self.app.route("/")
27-
def index():
28-
return "\n".join(x.title for x in self.Todo.objects)
295

30-
@self.app.route("/add", methods=["POST"])
31-
def add():
32-
form = flask.request.form
33-
todo = self.Todo(title=form["title"], text=form["text"])
34-
todo.save()
35-
return "added"
6+
@pytest.fixture(autouse=True)
7+
def setup_endpoints(app, todo):
8+
Todo = todo
369

37-
@self.app.route("/show/<id>/")
38-
def show(id):
39-
todo = self.Todo.objects.get_or_404(id=id)
40-
return "\n".join([todo.title, todo.text])
10+
@app.route("/")
11+
def index():
12+
return "\n".join(x.title for x in Todo.objects)
4113

42-
self.db = db
14+
@app.route("/add", methods=["POST"])
15+
def add():
16+
form = flask.request.form
17+
todo = Todo(title=form["title"], text=form["text"])
18+
todo.save()
19+
return "added"
4320

44-
def test_connection_default(self):
45-
self.app.config["MONGODB_SETTINGS"] = {}
46-
self.app.config["TESTING"] = True
21+
@app.route("/show/<id>/")
22+
def show(id):
23+
todo = Todo.objects.get_or_404(id=id)
24+
return "\n".join([todo.title, todo.text])
4725

48-
db = MongoEngine()
49-
# Disconnect to drop connection from setup.
50-
db.disconnect()
51-
db.init_app(self.app)
5226

53-
def test_with_id(self):
54-
c = self.app.test_client()
55-
resp = c.get("/show/%s/" % ObjectId())
56-
self.assertEqual(resp.status_code, 404)
27+
def test_with_id(app, todo):
28+
Todo = todo
29+
client = app.test_client()
30+
response = client.get("/show/%s/" % ObjectId())
31+
assert response.status_code == 404
5732

58-
c.post("/add", data={"title": "First Item", "text": "The text"})
33+
client.post("/add", data={"title": "First Item", "text": "The text"})
5934

60-
resp = c.get("/show/%s/" % self.Todo.objects.first_or_404().id)
61-
self.assertEqual(resp.status_code, 200)
62-
self.assertEqual(resp.data.decode("utf-8"), "First Item\nThe text")
35+
response = client.get("/show/%s/" % Todo.objects.first_or_404().id)
36+
assert response.status_code == 200
37+
assert response.data.decode("utf-8") == "First Item\nThe text"
6338

64-
def test_basic_insert(self):
65-
c = self.app.test_client()
66-
c.post("/add", data={"title": "First Item", "text": "The text"})
67-
c.post("/add", data={"title": "2nd Item", "text": "The text"})
68-
rv = c.get("/")
69-
self.assertEqual(rv.data.decode("utf-8"), "First Item\n2nd Item")
7039

71-
def test_request_context(self):
72-
with self.app.test_request_context():
73-
todo = self.Todo(title="Test", text="test")
74-
todo.save()
75-
self.assertEqual(self.Todo.objects.count(), 1)
40+
def test_basic_insert(app):
41+
client = app.test_client()
42+
client.post("/add", data={"title": "First Item", "text": "The text"})
43+
client.post("/add", data={"title": "2nd Item", "text": "The text"})
44+
response = client.get("/")
45+
assert response.data.decode("utf-8") == "First Item\n2nd Item"

0 commit comments

Comments
 (0)