From 010fe7549400cc97284fe23b90a32f23f5b3ffb3 Mon Sep 17 00:00:00 2001 From: Adam Chainz Date: Sat, 5 Nov 2016 15:06:24 +0100 Subject: [PATCH 1/5] Test checks are run --- tests/test_fixtures.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index 10ceac35c..7b9107ceb 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -222,6 +222,26 @@ def test_set_non_existent(settings): ]) +class TestChecks: + + def test_checks_are_run(self, django_testdir): + django_testdir.create_app_file(""" + from django.core.checks import Error, register + + @register + def fail(app_configs, **kwargs): + return [Error('My failure message', id='test.001')] + """, '__init__.py') + django_testdir.makepyfile(""" + def test_simple(): + assert True + """) + + result = django_testdir.runpytest_subprocess('-s') + result.stderr.fnmatch_lines(['*My failure message*']) + assert result.ret != 0 + + class TestLiveServer: def test_url(self, live_server): assert live_server.url == force_text(live_server) From 1f75bf7f08f6a4e89506e7e163e8dd53089f8891 Mon Sep 17 00:00:00 2001 From: Adam Chainz Date: Sat, 5 Nov 2016 15:48:34 +0100 Subject: [PATCH 2/5] Run checks as part of database setup --- pytest_django/fixtures.py | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index 0a0b1ec26..f124fd128 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -3,6 +3,8 @@ from __future__ import with_statement import os +import sys +from contextlib import contextmanager import pytest @@ -97,6 +99,9 @@ def django_db_setup( **setup_databases_args ) + if get_django_version() < (1, 11): + run_check(request) + def teardown_database(): with django_db_blocker.unblock(): teardown_databases( @@ -108,6 +113,42 @@ def teardown_database(): request.addfinalizer(teardown_database) +def run_check(request): + from django.core.management import call_command + from django.core.management.base import SystemCheckError + + # Only run once per process + if getattr(run_check, 'did_fail', False): + return + + with disable_input_capture(request): + try: + call_command('check') + except SystemCheckError as ex: + run_check.did_fail = True + + if hasattr(request.config, 'slaveinput'): + # Kill the xdist test process horribly + # N.B. 'shouldstop' maybe be obeyed properly in later as hinted at in + # https://github.com/pytest-dev/pytest-xdist/commit/e8fa73719662d1be5074a0750329fe0c35583484 + print(ex.args[0]) + sys.exit(1) + else: + request.session.exitstatus = 1 + request.session.shouldstop = True + raise + + +@contextmanager +def disable_input_capture(request): + capmanager = request.config.pluginmanager.getplugin('capturemanager') + capmanager.suspendcapture() + try: + yield + finally: + capmanager.resumecapture() + + def _django_db_fixture_helper(transactional, request, django_db_blocker): if is_django_unittest(request): return From 3bd72f02dda18b0b78bb0b3b06373e83f1037fe1 Mon Sep 17 00:00:00 2001 From: Adam Chainz Date: Sat, 3 Dec 2016 16:58:59 +0000 Subject: [PATCH 3/5] Output at the end --- pytest_django/fixtures.py | 41 ++++++++++++++++++----------------- pytest_django/plugin.py | 8 +++++++ tests/test_fixtures.py | 45 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 23 deletions(-) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index f124fd128..864f5d1fd 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -5,6 +5,7 @@ import os import sys from contextlib import contextmanager +from io import BytesIO import pytest @@ -99,8 +100,7 @@ def django_db_setup( **setup_databases_args ) - if get_django_version() < (1, 11): - run_check(request) + run_checks(request) def teardown_database(): with django_db_blocker.unblock(): @@ -113,30 +113,31 @@ def teardown_database(): request.addfinalizer(teardown_database) -def run_check(request): +def run_checks(request): from django.core.management import call_command from django.core.management.base import SystemCheckError # Only run once per process - if getattr(run_check, 'did_fail', False): + if getattr(run_checks, 'ran', False): return + run_checks.ran = True - with disable_input_capture(request): - try: - call_command('check') - except SystemCheckError as ex: - run_check.did_fail = True - - if hasattr(request.config, 'slaveinput'): - # Kill the xdist test process horribly - # N.B. 'shouldstop' maybe be obeyed properly in later as hinted at in - # https://github.com/pytest-dev/pytest-xdist/commit/e8fa73719662d1be5074a0750329fe0c35583484 - print(ex.args[0]) - sys.exit(1) - else: - request.session.exitstatus = 1 - request.session.shouldstop = True - raise + out = BytesIO() + try: + call_command('check', out=out, err=out) + except SystemCheckError as ex: + run_checks.exc = ex + + if hasattr(request.config, 'slaveinput'): + # Kill the xdist test process horribly + # N.B. 'shouldstop' may be obeyed properly in the future as hinted at in + # https://github.com/pytest-dev/pytest-xdist/commit/e8fa73719662d1be5074a0750329fe0c35583484 + print(ex.args[0]) + sys.exit(1) + else: + # Ensure we get the EXIT_TESTSFAILED exit code + request.session.testsfailed += 1 + request.session.shouldstop = True @contextmanager diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 1585c6983..71eb72d30 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -31,6 +31,7 @@ from .fixtures import django_username_field # noqa from .fixtures import live_server # noqa from .fixtures import rf # noqa +from .fixtures import run_checks # noqa from .fixtures import settings # noqa from .fixtures import transactional_db # noqa from .pytest_compat import getfixturevalue @@ -329,6 +330,13 @@ def pytest_runtest_setup(item): _disable_class_methods(cls) +def pytest_terminal_summary(terminalreporter, exitstatus): + check_exc = getattr(run_checks, 'exc', None) + if check_exc: + terminalreporter.write('\n') + terminalreporter.write(str(check_exc)) + + @pytest.fixture(autouse=True, scope='session') def django_test_environment(request): """ diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index 7b9107ceb..26a2e687f 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -222,24 +222,63 @@ def test_set_non_existent(settings): ]) +@pytest.mark.django_project(extra_settings=""" + INSTALLED_APPS = ['tpkg.app'] +""") class TestChecks: def test_checks_are_run(self, django_testdir): django_testdir.create_app_file(""" from django.core.checks import Error, register - @register + @register() + def succeed(app_configs, **kwargs): + succeed.did_run = True + return [] + """, '__init__.py') + django_testdir.makepyfile(""" + from tpkg.app import succeed + + def test_simple(db): + assert getattr(succeed, 'did_run', None) is True + """) + + result = django_testdir.runpytest_subprocess('-s') + assert result.ret == 0 + + def test_failing_checks_fail_tests(self, django_testdir): + django_testdir.create_app_file(""" + from django.core.checks import Error, register + + @register() def fail(app_configs, **kwargs): return [Error('My failure message', id='test.001')] """, '__init__.py') django_testdir.makepyfile(""" - def test_simple(): + def test_simple(db): assert True """) result = django_testdir.runpytest_subprocess('-s') - result.stderr.fnmatch_lines(['*My failure message*']) assert result.ret != 0 + result.stdout.fnmatch_lines(['*My failure message*']) + + def test_failing_checks_fail_tests_on_xdist(self, django_testdir): + django_testdir.create_app_file(""" + from django.core.checks import Error, register + + @register() + def fail(app_configs, **kwargs): + return [Error('My failure message', id='test.001')] + """, '__init__.py') + django_testdir.makepyfile(""" + def test_simple(db): + assert True + """) + + result = django_testdir.runpytest_subprocess('-s', '-n2') + assert result.ret != 0 + result.stdout.fnmatch_lines(['*My failure message*']) class TestLiveServer: From 182f0bae042eb8014cefa36f2471c6c7902c41f0 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 27 May 2018 11:27:02 +0200 Subject: [PATCH 4/5] output actually stored --- pytest_django/fixtures.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index 864f5d1fd..c10001854 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -5,12 +5,10 @@ import os import sys from contextlib import contextmanager -from io import BytesIO +from io import StringIO import pytest -from contextlib import contextmanager - from . import live_server_helper from .django_compat import is_django_unittest @@ -122,9 +120,9 @@ def run_checks(request): return run_checks.ran = True - out = BytesIO() + out = StringIO() try: - call_command('check', out=out, err=out) + call_command('check', stdout=out, stderr=out) except SystemCheckError as ex: run_checks.exc = ex @@ -140,16 +138,6 @@ def run_checks(request): request.session.shouldstop = True -@contextmanager -def disable_input_capture(request): - capmanager = request.config.pluginmanager.getplugin('capturemanager') - capmanager.suspendcapture() - try: - yield - finally: - capmanager.resumecapture() - - def _django_db_fixture_helper(transactional, request, django_db_blocker): if is_django_unittest(request): return From 7aa1ea03ea595ddcc151db807dba515e81063dab Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 27 May 2018 12:07:40 +0200 Subject: [PATCH 5/5] Store temporary variables on config rather than function --- pytest_django/fixtures.py | 12 +++++++----- pytest_django/plugin.py | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index c10001854..b545a0a91 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -115,22 +115,24 @@ def run_checks(request): from django.core.management import call_command from django.core.management.base import SystemCheckError + config = request.config + # Only run once per process - if getattr(run_checks, 'ran', False): + if getattr(config, '_pytest_django_checks_ran', False): return - run_checks.ran = True + config._pytest_django_checks_ran = True out = StringIO() try: call_command('check', stdout=out, stderr=out) - except SystemCheckError as ex: - run_checks.exc = ex + except SystemCheckError as exc: + config._pytest_django_checks_exc = exc if hasattr(request.config, 'slaveinput'): # Kill the xdist test process horribly # N.B. 'shouldstop' may be obeyed properly in the future as hinted at in # https://github.com/pytest-dev/pytest-xdist/commit/e8fa73719662d1be5074a0750329fe0c35583484 - print(ex.args[0]) + print(exc.args[0]) sys.exit(1) else: # Ensure we get the EXIT_TESTSFAILED exit code diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 71eb72d30..6a99a40ca 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -331,7 +331,8 @@ def pytest_runtest_setup(item): def pytest_terminal_summary(terminalreporter, exitstatus): - check_exc = getattr(run_checks, 'exc', None) + config = terminalreporter.config + check_exc = getattr(config, '_pytest_django_checks_exc', None) if check_exc: terminalreporter.write('\n') terminalreporter.write(str(check_exc))