Skip to content

Commit a57b482

Browse files
authored
Merge pull request #496 from MongoEngine/independency_tests
Added: Tests to check correct work without extra install options, or part of them
2 parents 9da7440 + 47f4664 commit a57b482

File tree

6 files changed

+77
-29
lines changed

6 files changed

+77
-29
lines changed

.github/workflows/coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
with:
3838
mongodb-version: ${{ matrix.mongodb-version }}
3939
- name: Test build
40-
run: "nox -s latest --python ${{ matrix.python }} -- --cov-report=xml --cov-report=html"
40+
run: "nox -s 'latest-${{ matrix.python }}(wtf=True, toolbar=True)' -- --cov-report=xml --cov-report=html"
4141
- name: Send coverage report to codecov
4242
uses: codecov/codecov-action@v3
4343
with:

noxfile.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,33 @@
1111
db_version = "5.0"
1212

1313

14-
def base_install(session, flask, mongoengine):
14+
def base_install(session, flask, mongoengine, toolbar, wtf):
1515
"""Create basic environment setup for tests and linting."""
16+
session.run("python", "-m", "pip", "install", "--upgrade", "pip")
17+
session.run("python", "-m", "pip", "install", "setuptools_scm[toml]>=6.3.1")
18+
19+
if toolbar and wtf:
20+
extra = "wtf,toolbar,"
21+
elif toolbar:
22+
extra = "toolbar,"
23+
elif wtf:
24+
extra = "wtf,"
25+
else:
26+
extra = ""
27+
1628
if flask == "==1.1.4":
17-
session.run("python", "-m", "pip", "install", "--upgrade", "pip")
18-
session.run("python", "-m", "pip", "install", "setuptools_scm[toml]>=6.3.1")
1929
session.install(
2030
f"Flask{flask}",
2131
f"mongoengine{mongoengine}",
2232
"-e",
23-
".[wtf,toolbar,legacy,legacy-dev]",
33+
f".[{extra}legacy,legacy-dev]",
2434
)
2535
else:
26-
session.run("python", "-m", "pip", "install", "--upgrade", "pip")
27-
session.run("python", "-m", "pip", "install", "setuptools_scm[toml]>=6.3.1")
2836
session.install(
2937
f"Flask{flask}",
3038
f"mongoengine{mongoengine}",
3139
"-e",
32-
".[wtf,toolbar,dev]",
40+
f".[{extra}dev]",
3341
)
3442
return session
3543

@@ -44,9 +52,11 @@ def lint(session):
4452
@nox.session(python=["3.7", "3.8", "3.9", "3.10", "pypy3.7"])
4553
@nox.parametrize("flask", ["==1.1.4", "==2.0.3", ">=2.1.2"])
4654
@nox.parametrize("mongoengine", ["==0.21.0", "==0.22.1", "==0.23.1", ">=0.24.1"])
47-
def ci_cd_tests(session, flask, mongoengine):
55+
@nox.parametrize("toolbar", [True, False])
56+
@nox.parametrize("wtf", [True, False])
57+
def ci_cd_tests(session, flask, mongoengine, toolbar, wtf):
4858
"""Run test suite with pytest into ci_cd (no docker)."""
49-
session = base_install(session, flask, mongoengine)
59+
session = base_install(session, flask, mongoengine, toolbar, wtf)
5060
session.run("pytest", *session.posargs)
5161

5262

@@ -71,18 +81,22 @@ def _run_in_docker(session):
7181
@nox.session(python=["3.7", "3.8", "3.9", "3.10", "pypy3.7"])
7282
@nox.parametrize("flask", ["==1.1.4", "==2.0.3", ">=2.1.2"])
7383
@nox.parametrize("mongoengine", ["==0.21.0", "==0.22.1", "==0.23.1", ">=0.24.1"])
74-
def full_tests(session, flask, mongoengine):
84+
@nox.parametrize("toolbar", [True, False])
85+
@nox.parametrize("wtf", [True, False])
86+
def full_tests(session, flask, mongoengine, toolbar, wtf):
7587
"""Run tests locally with docker and complete support matrix."""
76-
session = base_install(session, flask, mongoengine)
88+
session = base_install(session, flask, mongoengine, toolbar, wtf)
7789
_run_in_docker(session)
7890

7991

8092
@nox.session(python=["3.7", "3.8", "3.9", "3.10", "pypy3.7"])
81-
def latest(session):
93+
@nox.parametrize("toolbar", [True, False])
94+
@nox.parametrize("wtf", [True, False])
95+
def latest(session, toolbar, wtf):
8296
"""Run minimum tests for checking minimum code quality."""
8397
flask = ">=2.1.2"
8498
mongoengine = ">=0.24.1"
85-
session = base_install(session, flask, mongoengine)
99+
session = base_install(session, flask, mongoengine, toolbar, wtf)
86100
if session.interactive:
87101
_run_in_docker(session)
88102
else:

tests/test_db_fields.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@
55
import pytest
66
from mongoengine import fields as base_fields
77
from pytest_mock import MockerFixture
8-
from wtforms import validators as wtf_validators_
98

109
from flask_mongoengine import db_fields, documents
1110

11+
try:
12+
from wtforms import validators as wtf_validators_
13+
14+
wtforms_not_installed = False
15+
except ImportError:
16+
wtf_validators_ = None
17+
wtforms_not_installed = True
18+
1219

1320
@pytest.fixture
1421
def local_app(app):
@@ -44,6 +51,7 @@ class Model(request.param):
4451

4552
return Model
4653

54+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
4755
def test__get_fields_names__is_called_by_to_wtf_form_call(
4856
self, TempDocument, mocker: MockerFixture
4957
):
@@ -79,6 +87,7 @@ def test__to_wtf_form__is_called_by_mixin_child_model(
7987
TempDocument.to_wtf_form()
8088
to_wtf_spy.assert_called_once()
8189

90+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
8291
def test__to_wtf_form__logs_error(self, caplog, TempDocument):
8392
TempDocument.to_wtf_form()
8493

@@ -225,6 +234,7 @@ def test__wtf_field_class__return__user_provided_value__if_set(self):
225234

226235
assert issubclass(field.wtf_field_class, str)
227236

237+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
228238
@pytest.mark.parametrize(
229239
["user_dict", "expected_result"],
230240
[
@@ -245,6 +255,7 @@ def test__wtf_field_options__overwrite_generated_options_with_user_provided(
245255
field = db_fields.WtfFieldMixin(wtf_options=user_dict)
246256
assert field.wtf_field_options == expected_result
247257

258+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
248259
def test__wtf_generated_options__correctly_retrieve_label_from_parent_class(self):
249260
"""Test based on base class for all fields."""
250261
default_call = self.WTFieldBaseMRO()
@@ -254,6 +265,7 @@ def test__wtf_generated_options__correctly_retrieve_label_from_parent_class(self
254265
assert default_call.wtf_generated_options["label"] == "set not by init"
255266
assert with_option_call.wtf_generated_options["label"] == "fake"
256267

268+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
257269
def test__wtf_generated_options__correctly_retrieve_description_from_parent_class(
258270
self,
259271
):
@@ -263,13 +275,15 @@ def test__wtf_generated_options__correctly_retrieve_description_from_parent_clas
263275
assert default_call.wtf_generated_options["description"] == ""
264276
assert with_option_call.wtf_generated_options["description"] == "fake"
265277

278+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
266279
def test__wtf_generated_options__correctly_retrieve_default_from_parent_class(self):
267280
default_call = self.WTFieldBaseMRO()
268281
with_option_call = self.WTFieldBaseMRO(default="fake")
269282

270283
assert default_call.wtf_generated_options["default"] is None
271284
assert with_option_call.wtf_generated_options["default"] == "fake"
272285

286+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
273287
def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class__and__add_optional_validator__if_field_not_required(
274288
self,
275289
):
@@ -286,6 +300,7 @@ def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class
286300
wtf_validators_.Optional,
287301
)
288302

303+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
289304
def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class__and__add_required__if_field_required(
290305
self,
291306
):
@@ -302,13 +317,15 @@ def test__wtf_generated_options__correctly_retrieve_validators_from_parent_class
302317
wtf_validators_.InputRequired,
303318
)
304319

320+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
305321
def test__wtf_generated_options__correctly_retrieve_filters_from_parent_class(self):
306322
default_call = self.WTFieldBaseMRO()
307323
with_option_call = self.WTFieldBaseMRO(wtf_filters=[str, list])
308324

309325
assert default_call.wtf_generated_options["filters"] == []
310326
assert with_option_call.wtf_generated_options["filters"] == [str, list]
311327

328+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
312329
def test__wtf_generated_options__correctly_handle_choices_settings(self):
313330
default_call = self.WTFieldBaseMRO(choices=[1, 2])
314331
with_option_call = self.WTFieldBaseMRO(choices=[1, 2], wtf_choices_coerce=list)
@@ -318,6 +335,7 @@ def test__wtf_generated_options__correctly_handle_choices_settings(self):
318335
assert with_option_call.wtf_generated_options["choices"] == [1, 2]
319336
assert with_option_call.wtf_generated_options["coerce"] is list
320337

338+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
321339
def test__to_wtf_field__does_not_modify_anything_if_options_not_provided(self):
322340
# Setting base validators to exclude patching of .wtf_generated_options()
323341
field = self.WTFieldBaseMRO(wtf_options={"validators": ["ignore"]})
@@ -328,6 +346,7 @@ def test__to_wtf_field__does_not_modify_anything_if_options_not_provided(self):
328346

329347
field.DEFAULT_WTF_FIELD.assert_called_with(**field_options)
330348

349+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
331350
def test__to_wtf_field__update_field_class_if_related_option_provided(self):
332351
# Setting base validators to exclude patching of .wtf_generated_options()
333352
will_be_called = Mock()
@@ -340,6 +359,7 @@ def test__to_wtf_field__update_field_class_if_related_option_provided(self):
340359
will_not_be_called.assert_not_called()
341360
will_be_called.assert_called_with(**field_options)
342361

362+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
343363
def test__to_wtf_field__update_field_kwargs_if_related_option_provided(self):
344364
# Setting base validators to exclude patching of .wtf_generated_options()
345365
will_be_called = Mock()

tests/test_db_fields_import_protection.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
"""Testing independency from WTForms."""
2+
import pytest
3+
4+
try:
5+
import wtforms
6+
7+
wtforms_not_installed = False
8+
except ImportError:
9+
wtforms = None
10+
wtforms_not_installed = True
211

312

413
class TestImportProtection:
514
def test__when_wtforms_available__import_use_its_data(self):
615
from flask_mongoengine import db_fields
716

8-
assert db_fields.wtf_fields is not None
9-
assert db_fields.wtf_validators_ is not None
17+
assert db_fields is not None
1018

11-
def test__core_class_imported_without_error(self, monkeypatch):
12-
monkeypatch.setattr("flask_mongoengine.decorators.wtf_installed", False)
19+
def test__core_class_imported_without_error(self):
1320
from flask_mongoengine import MongoEngine
1421

1522
db = MongoEngine()
1623
assert db is not None
1724

25+
@pytest.mark.skipif(condition=wtforms_not_installed, reason="No WTF CI/CD chain")
1826
def test__wtf_required_decorator__when_wtf_installed(self):
1927
from flask_mongoengine.decorators import wtf_required
2028

tests/test_debug_panel.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@
99
import pymongo
1010
import pytest
1111
from flask import Flask
12-
from flask_debugtoolbar import DebugToolbarExtension
13-
from flask_debugtoolbar.panels import DebugPanel
14-
from jinja2 import ChoiceLoader, DictLoader
15-
from pymongo import monitoring
16-
from pymongo.errors import OperationFailure
17-
from pytest_mock import MockerFixture
18-
19-
from flask_mongoengine.panels import (
12+
13+
flask_debugtoolbar = pytest.importorskip("flask_debugtoolbar")
14+
15+
from flask_debugtoolbar import DebugToolbarExtension # noqa
16+
from flask_debugtoolbar.panels import DebugPanel # noqa
17+
from jinja2 import ChoiceLoader, DictLoader # noqa
18+
from pymongo import monitoring # noqa
19+
from pymongo.errors import OperationFailure # noqa
20+
from pytest_mock import MockerFixture # noqa
21+
22+
from flask_mongoengine.panels import ( # noqa
2023
MongoCommandLogger,
2124
MongoDebugPanel,
2225
_maybe_patch_jinja_loader,

tests/test_forms.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import bson
55
import flask
66
import pytest
7-
import wtforms
87
from mongoengine import NotUniqueError, queryset_manager
98
from werkzeug.datastructures import MultiDict
109

11-
from flask_mongoengine.wtf.orm import model_form
10+
try:
11+
from flask_mongoengine.wtf.orm import model_form
12+
except ImportError:
13+
model_form = None
14+
wtforms = pytest.importorskip("wtforms")
1215

1316

1417
def test_binaryfield(app, db):

0 commit comments

Comments
 (0)