diff --git a/doc/assert.txt b/doc/assert.txt index 7d1c21da3..191cd1a66 100644 --- a/doc/assert.txt +++ b/doc/assert.txt @@ -39,23 +39,6 @@ assertion fails you will see the value of ``x``:: test_assert1.py:5: AssertionError ========================= 1 failed in 0.02 seconds ========================= -Reporting details about the failing assertion is achieved by re-evaluating -the assert expression and recording the intermediate values. - -Note: If evaluating the assert expression has side effects you may get a -warning that the intermediate values could not be determined safely. A -common example of this issue is an assertion which reads from a file:: - - assert f.read() != '...' - -If this assertion fails then the re-evaluation will probably succeed! -This is because ``f.read()`` will return an empty string when it is -called the second time during the re-evaluation. However, it is -easy to rewrite the assertion and avoid any trouble:: - - content = f.read() - assert content != '...' - assertions about expected exceptions ------------------------------------------ @@ -137,6 +120,46 @@ Special comparisons are done for a number of cases: See the :ref:`reporting demo ` for many more examples. + +Assertion debugging details +--------------------------- + +Reporting details about the failing assertion is achieved either by rewriting +assert statements before they are run or re-evaluating the assert expression and +recording the intermediate values. Which technique is used depends on the +location of the assert, py.test's configuration, and Python version being used +to run py.test. + +By default, if the Python version is greater than or equal to 2.6, py.test +rewrites assert statements in test modules. Rewritten assert statements put +debugging information into the assertion failure message. Note py.test only +rewrites test modules directly discovered by its test collection process, so +asserts in supporting modules will not be rewritten. + +If an assert statement has not been rewritten or the Python version is less than +2.6, py.test falls back on assert reinterpretation. In assert reinterpretation, +py.test walks the frame of the function containing the assert statement to +discover sub-expression results of the failing assert statement. You can force +py.test to always use assertion reinterpretation by passing the +``--assertmode=old`` option. + +Assert reinterpretation has a caveat not present with assert rewriting: If +evaluating the assert expression has side effects you may get a warning that the +intermediate values could not be determined safely. A common example of this +issue is an assertion which reads from a file:: + + assert f.read() != '...' + +If this assertion fails then the re-evaluation will probably succeed! +This is because ``f.read()`` will return an empty string when it is +called the second time during the re-evaluation. However, it is +easy to rewrite the assertion and avoid any trouble:: + + content = f.read() + assert content != '...' + +All assert debugging can be turned off by passing ``--assertmode=off``. + .. Defining your own comparison ---------------------------------------------- diff --git a/doc/faq.txt b/doc/faq.txt index 0b76dab26..916d0c001 100644 --- a/doc/faq.txt +++ b/doc/faq.txt @@ -47,13 +47,17 @@ customizable testing frameworks for Python. However, ``py.test`` still uses many metaprogramming techniques and reading its source is thus likely not something for Python beginners. -A second "magic" issue arguably the assert statement re-intepreation: -When an ``assert`` statement fails, py.test re-interprets the expression -to show intermediate values if a test fails. If your expression -has side effects (better to avoid them anyway!) the intermediate values -may not be the same, obfuscating the initial error (this is also -explained at the command line if it happens). -``py.test --no-assert`` turns off assert re-interpretation. +A second "magic" issue arguably the assert statement debugging feature. When +loading test modules py.test rewrites the source code of assert statements. When +a rewritten assert statement fails, its error message has more information than +the original. py.test has a second assert debugging technique. When an +``assert`` statement that was missed by the rewriter fails, py.test +re-interprets the expression to show intermediate values if a test fails. This +second technique suffers from caveat that the rewriting does not: If your +expression has side effects (better to avoid them anyway!) the intermediate +values may not be the same, confusing the reinterpreter and obfuscating the +initial error (this is also explained at the command line if it happens). +You can turn off all assertion debugging with ``py.test --assertmode=off``. .. _`py namespaces`: index.html .. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py