diff --git a/CHANGELOG b/CHANGELOG index fa8673018..5da150183 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ Changes between 2.0.0 and 2.0.1.dev1 ---------------------------------------------- +- improve behaviour/warnings when running on top of "python -OO" + (assertions and docstrings are turned off, leading to potential + false positives) - introduce a pytest_cmdline_processargs(args) hook to allow dynamic computation of command line arguments. This fixes a regression because py.test prior to 2.0 diff --git a/_pytest/assertion.py b/_pytest/assertion.py index 71d26ab1c..9c7143bb8 100644 --- a/_pytest/assertion.py +++ b/_pytest/assertion.py @@ -17,8 +17,8 @@ def pytest_configure(config): # turn call the hooks defined here as part of the # DebugInterpreter. config._monkeypatch = m = monkeypatch() + warn_about_missing_assertion() if not config.getvalue("noassert") and not config.getvalue("nomagic"): - warn_about_missing_assertion() def callbinrepr(op, left, right): hook_result = config.hook.pytest_assertrepr_compare( config=config, op=op, left=left, right=right) @@ -38,9 +38,8 @@ def warn_about_missing_assertion(): except AssertionError: pass else: - py.std.warnings.warn("Assertions are turned off!" - " (are you using python -O?)") - + sys.stderr.write("WARNING: failing tests may report as passing because " + "assertions are turned off! (are you using python -O?)\n") # Provide basestring in python3 try: diff --git a/_pytest/core.py b/_pytest/core.py index 5c202e28d..aae7c1c6e 100644 --- a/_pytest/core.py +++ b/_pytest/core.py @@ -362,9 +362,6 @@ class HookRelay: added = False for name, method in vars(hookspecs).items(): if name.startswith(prefix): - if not method.__doc__: - raise ValueError("docstring required for hook %r, in %r" - % (method, hookspecs)) firstresult = getattr(method, 'firstresult', False) hc = HookCaller(self, name, firstresult=firstresult) setattr(self, name, hc) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index d05d9e189..a53afe7fc 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -218,6 +218,12 @@ class TestGeneralUsage: assert res.ret res.stderr.fnmatch_lines(["*ERROR*not found*"]) + def test_docstring_on_hookspec(self): + from _pytest import hookspec + for name, value in vars(hookspec).items(): + if name.startswith("pytest_"): + assert value.__doc__, "no docstring for %s" % name + class TestInvocationVariants: def test_earlyinit(self, testdir): p = testdir.makepyfile(""" diff --git a/testing/test_assertion.py b/testing/test_assertion.py index e153f6546..b4c74b0de 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -201,3 +201,14 @@ def test_traceback_failure(testdir): "*test_traceback_failure.py:4: AssertionError" ]) +@pytest.mark.skipif("sys.version_info < (2,5)") +def test_warn_missing(testdir): + p1 = testdir.makepyfile("") + result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h") + result.stderr.fnmatch_lines([ + "*WARNING*assertion*", + ]) + result = testdir.run(sys.executable, "-OO", "-m", "pytest", "--no-assert") + result.stderr.fnmatch_lines([ + "*WARNING*assertion*", + ]) diff --git a/testing/test_core.py b/testing/test_core.py index 3bcf681af..76721974e 100644 --- a/testing/test_core.py +++ b/testing/test_core.py @@ -319,25 +319,6 @@ class TestPytestPluginInteractions: res = config.hook.pytest_myhook(xyz=10) assert res == [11] - def test_addhooks_docstring_error(self, testdir): - newhooks = testdir.makepyfile(newhooks=""" - class A: # no pytest_ prefix - pass - def pytest_myhook(xyz): - pass - """) - conf = testdir.makeconftest(""" - import sys ; sys.path.insert(0, '.') - import newhooks - def pytest_addhooks(pluginmanager): - pluginmanager.addhooks(newhooks) - """) - res = testdir.runpytest() - assert res.ret != 0 - res.stderr.fnmatch_lines([ - "*docstring*pytest_myhook*newhooks*" - ]) - def test_addhooks_nohooks(self, testdir): conf = testdir.makeconftest(""" import sys