Giter VIP home page Giter VIP logo

pytest's Introduction

pytest


image

image

image

Code coverage Status

image

pre-commit.ci status

image

Documentation Status

Discord

Libera chat

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries.

An example of a simple test:

# content of test_sample.py
def inc(x):
    return x + 1


def test_answer():
    assert inc(3) == 5

To execute it:

$ pytest
============================= test session starts =============================
collected 1 items

test_sample.py F

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

    def test_answer():
>       assert inc(3) == 5
E       assert 4 == 5
E        +  where 4 = inc(3)

test_sample.py:5: AssertionError
========================== 1 failed in 0.04 seconds ===========================

Due to pytest's detailed assertion introspection, only plain assert statements are used. See getting-started for more examples.

Features

  • Detailed info on failing assert statements (no need to remember self.assert* names)
  • Auto-discovery of test modules and functions
  • Modular fixtures for managing small or parametrized long-lived test resources
  • Can run unittest (or trial) test suites out of the box
  • Python 3.8+ or PyPy3
  • Rich plugin architecture, with over 1300+ external plugins and thriving community

Documentation

For full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.

Bugs/Requests

Please use the GitHub issue tracker to submit bugs or request features.

Changelog

Consult the Changelog page for fixes and enhancements of each version.

Support pytest

Open Collective is an online funding platform for open and transparent communities. It provides tools to raise money and share your finances in full transparency.

It is the platform of choice for individuals and companies that want to make one-time or monthly donations directly to the project.

See more details in the pytest collective.

pytest for enterprise

Available as part of the Tidelift Subscription.

The maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.

Learn more.

Security

pytest has never been associated with a security vulnerability, but in any case, to report a security vulnerability please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

License

Copyright Holger Krekel and others, 2004.

Distributed under the terms of the MIT license, pytest is free and open source software.

pytest's People

Contributors

altendky avatar andras-tim avatar asottile avatar benjaminp avatar bluetech avatar blueyed avatar bubenkoff avatar dependabot[bot] avatar feuillemorte avatar flub avatar github-actions[bot] avatar gnikonorov avatar graingert avatar hackebrot avatar hpk42 avatar hugovk avatar jaraco avatar jeffreyrack avatar jurko-gospodnetic avatar kalekundert avatar nicoddemus avatar pfctdayelise avatar pierre-sassoulas avatar pre-commit-ci[bot] avatar pytestbot avatar ronnypfannschmidt avatar symonk avatar the-compiler avatar twmr avatar zac-hd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pytest's Issues

TypeError when module under test or function under test is named 'test'

Originally reported by: Jason R. Coombs (BitBucket: jaraco, GitHub: jaraco)


I encountered an issue (during test collection) where I get a type error when the test function is named test. The error occurs on Linux and Windows. Here's a simple example to reproduce:

jaraco@shinobi:~/projects/foo$ ls -R
.:
mymod  test

./mymod:
__init__.py  __init__.pyc  test.py  test.pyc

./test:
test.py  test.pyc
jaraco@shinobi:~/projects/foo$ cat mymod/test.py
class test(object): pass
jaraco@shinobi:~/projects/foo$ cat test/test.py
from mymod.test import test
jaraco@shinobi:~/projects/foo$ PYTHONPATH=. py.test test/test.py
============================= test session starts ==============================
platform linux2 -- Python 2.7.1 -- pytest-2.0.2
collected 0 items / 1 errors 

==================================== ERRORS ====================================
________________________ ERROR collecting test/test.py _________________________
../../lib/python2.7/inspect.py:749: in getargs
>           raise TypeError('{!r} is not a code object'.format(co))
E           TypeError: <class 'mymod.test.test'> is not a code object
=========================== 1 error in 0.04 seconds ============================

pytest_assertrepr_compare produces an in-line exception on python3

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


When a failed string comparison assertion is encountered pytest-2.0.1 (do not know about earlier versions) will report a seemingly unrelated error about 'invalid slice indices'.

Example:

def test():
    assert "One" == "Two

Output:

========================== test session starts =========================
platform win32 -- Python 3.2.0 -- pytest-2.0.1
collected 1 items

aaa.py F

=============================== FAILURES ===============================
_________________________________ test _________________________________

    def test():
>       assert "One" == "Two"
E       assert <[TypeError("slice indices must be integers or None or
have an __index__ method") raised in repr()] SafeRepr object at
0x10206f0>
== ...
E         - One
E         + Two

aaa.py:2: AssertionError
======================= 1 failed in 0.14 seconds =======================

I was wondering if it would be possible to get a 'better' assertion failure message in this 'typical' use case.

Everything tested on Windows XP with Python 3.2 rc3.

Hope this helps.

Best regards,
Jurko Gospodnetić


Can not enter PDB debugger when file contains the copyright '©' character.

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


I just noticed that when you tell py.test to enter PDB (py.test --pdb) on test failure and your failing test function contains the copyright '©' character py.test reports a looooong list of 'INTERNALERROR>' lines seemingly caused by some failed code-page conversion attempt.

Tested on Windows XP SP3 with Python 3.2 rc3.

It does the same whether the script is stored in ASCII (using the '# -- coding: CP1250 --' encoding declaration comment as its first line) or UTF-8 format.

Here is an example (store it as UTF-8 to reproduce):

def test_xxx():
    a = "©"
    assert 1 == 0

and then run the tests using 'py.test --pdb'.

You'll get lots of INTERNALERROR> lines ending with something like this:

INTERNALERROR>
INTERNALERROR> self = <encodings.cp852.IncrementalEncoder object at 0x00AF1C30>, input = '        a = "ę"\n', final = False
INTERNALERROR>
INTERNALERROR>     def encode(self, input, final=False):
INTERNALERROR> >       return codecs.charmap_encode(input,self.errors,encoding_map)[0]
INTERNALERROR> E   UnicodeEncodeError: 'charmap' codec can't encode character '\xa9' in position 13: character maps to <undefined>
INTERNALERROR>
INTERNALERROR> final      = False
INTERNALERROR> input      = '        a = "ę"\n'
INTERNALERROR> self       = <encodings.cp852.IncrementalEncoder object at 0x00AF1C30>
INTERNALERROR>
INTERNALERROR> C:\Program Files\Python\Python32\lib\encodings\cp852.py:19: UnicodeEncodeError

The code gets reported correctly when simply running the tests without the --pdb option. It does not display the copyright character correctly (attempts a code-page conversion to some code table (852?) not having this character) but that does not really matter. The important thing is that the tests run, report their success/failure status correctly and the copyright character is always converted to the same character and so can be easily identified by the user if needed.

The problem does not occur if the copyright character is used outside the failing test function (most likely related to whether it is included inside py.test's smart stack trace report). For example, the following code enters PDB as expected:

a = "©"
def test_xxx():
    assert 1 == 0

The whole issue is by no means a show-stopper and is easily manually avoided now I know what is triggering it but it would be nicer if it did not exist at all. :-)

Hope this helps.

Best regards,
Jurko Gospodnetić

P.S.
Heh, I wasn't actively trying to 'break stuff'. I was writing a class to model some copyright information so this character was a 'natural thing' to use here. :-)


assert failure inside doctest doesn't prettyprint

Originally reported by: BitBucket: wtanksleyjr, GitHub: wtanksleyjr


Asserts inside doctests don't parse correctly; they instead produce an error that points to the wrong line. It looks like the backtrace is getting confused.

It may be possible to fix this specific error by finding a bug in our doctest code; but it may also be possible to handle the general case where the backtracking information doesn't lead into the test code. When that happens, it would be ideal to show an error message that points to the last line of test code run, even if the location isn't in the backtrace.

I've attached doc.py to demonstrate the assert problem.


adding hooks for controlling instances of tests

Originally reported by: BitBucket: ddandd, GitHub: ddandd


adding pytest_collect_instances(class_item), that will return the test instances of a test_class and each test on an instance will have the same instance object (self)
It should be used when writing long and complicated generated tests, it'll allow calling a setup_instance method that would be able to get funcargs, or calling the init (that will require to add a pytest_collect_can_initialize_class or a similar hook)


time reported as zero in XML JUnit output

Originally reported by: BitBucket: luked2, GitHub: luked2


I created the following test:

import time
def test_bar():
    time.sleep(2)

When I run the test:

% py.test --junitxml=out.xml

the resulting XML shows the overall time correctly, but the time for each individual test always comes up as zero:

<?xml version="1.0" encoding="utf-8"?><testsuite name="" errors="0" failures="0" skips="0" tests="1" time="2.013" >
<testcase classname="test_foo" name="test_bar" time="0"></testcase></testsuite>

Internal error with py.test -n 4 --boxed (with xdist)

Originally reported by: Andreas Kloeckner (BitBucket: inducer, GitHub: inducer)


gw0 initializing / gw1 initializing / gw2 initializing / gw3 initializing
gw0 collecting / gw1 initializing / gw2 initializing / gw3 initializing  
gw0 collecting / gw1 collecting / gw2 initializing / gw3 initializing  
gw0 collecting / gw1 collecting / gw2 collecting / gw3 initializing  
gw0 collecting / gw1 collecting / gw2 collecting / gw3 collecting  
gw0 collecting / gw1 collecting / gw2 collecting / gw3 ready     
gw0 collecting / gw1 ready / gw2 collecting / gw3 ready     
gw0 ready / gw1 ready / gw2 collecting / gw3 ready     
gw0 ready / gw1 ready / gw2 ready / gw3 ready     
gw0 ready / gw1 ready / gw2 ready / gw3 [108]
gw0 [108] / gw1 ready / gw2 ready / gw3 [108]
gw0 [108] / gw1 ready / gw2 [108] / gw3 [108]
gw0 [108] / gw1 [108] / gw2 [108] / gw3 [108]
scheduling tests via LoadScheduling
INTERNALERROR> config = <_pytest.config.Config object at 0x11e99d0>
INTERNALERROR> 
INTERNALERROR>     def pytest_cmdline_main(config):
INTERNALERROR>         """ default command line protocol for initialization, session,
INTERNALERROR>         running tests and reporting. """
INTERNALERROR>         session = Session(config)
INTERNALERROR>         session.exitstatus = EXIT_OK
INTERNALERROR>         try:
INTERNALERROR>             config.pluginmanager.do_configure(config)
INTERNALERROR>             config.hook.pytest_sessionstart(session=session)
INTERNALERROR>             config.hook.pytest_collection(session=session)
INTERNALERROR> >           config.hook.pytest_runtestloop(session=session)
INTERNALERROR> 
INTERNALERROR> config     = <_pytest.config.Config object at 0x11e99d0>
INTERNALERROR> session    = <Session 'run-2011-02-08-1926'>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/_pytest/main.py:65: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <HookCaller 'pytest_runtestloop'>
INTERNALERROR> 
INTERNALERROR>     def __call__(self, **kwargs):
INTERNALERROR>         methods = self.hookrelay._pm.listattr(self.name)
INTERNALERROR> >       return self._docall(methods, kwargs)
INTERNALERROR> 
INTERNALERROR> kwargs     = {'session': <Session 'run-2011-02-08-1926'>}
INTERNALERROR> methods    = [<function pytest_runtestloop at 0x1314500>, <bound method DSession.pytest_runtestloop of <xdist.dsession.DSession instance at 0x161e8c0>>]
INTERNALERROR> self       = <HookCaller 'pytest_runtestloop'>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/_pytest/core.py:389: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <HookCaller 'pytest_runtestloop'>
INTERNALERROR> methods = [<function pytest_runtestloop at 0x1314500>, <bound method DSession.pytest_runtestloop of <xdist.dsession.DSession instance at 0x161e8c0>>]
INTERNALERROR> kwargs = {'session': <Session 'run-2011-02-08-1926'>}
INTERNALERROR> 
INTERNALERROR>     def _docall(self, methods, kwargs):
INTERNALERROR>         self.trace(self.name, kwargs)
INTERNALERROR>         self.trace.root.indent += 1
INTERNALERROR>         mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
INTERNALERROR>         try:
INTERNALERROR> >           res = mc.execute()
INTERNALERROR> 
INTERNALERROR> kwargs     = {'session': <Session 'run-2011-02-08-1926'>}
INTERNALERROR> mc         = <MultiCall 0 results, 1 meths, kwargs={'session': <Session 'run-2011-02-08-1926'>}>
INTERNALERROR> methods    = [<function pytest_runtestloop at 0x1314500>, <bound method DSession.pytest_runtestloop of <xdist.dsession.DSession instance at 0x161e8c0>>]
INTERNALERROR> self       = <HookCaller 'pytest_runtestloop'>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/_pytest/core.py:400: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <MultiCall 0 results, 1 meths, kwargs={'session': <Session 'run-2011-02-08-1926'>}>
INTERNALERROR> 
INTERNALERROR>     def execute(self):
INTERNALERROR>         while self.methods:
INTERNALERROR>             method = self.methods.pop()
INTERNALERROR>             kwargs = self.getkwargs(method)
INTERNALERROR> >           res = method(**kwargs)
INTERNALERROR> 
INTERNALERROR> kwargs     = {}
INTERNALERROR> method     = <bound method DSession.pytest_runtestloop of <xdist.dsession.DSession instance at 0x161e8c0>>
INTERNALERROR> self       = <MultiCall 0 results, 1 meths, kwargs={'session': <Session 'run-2011-02-08-1926'>}>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/_pytest/core.py:324: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> 
INTERNALERROR>     def pytest_runtestloop(self):
INTERNALERROR>         numnodes = len(self.nodemanager.specs)
INTERNALERROR>         dist = self.config.getvalue("dist")
INTERNALERROR>         if dist == "load":
INTERNALERROR>             self.sched = LoadScheduling(numnodes, log=self.log)
INTERNALERROR>         elif dist == "each":
INTERNALERROR>             self.sched = EachScheduling(numnodes, log=self.log)
INTERNALERROR>         else:
INTERNALERROR>             assert 0, dist
INTERNALERROR>         self.shouldstop = False
INTERNALERROR>         self.session_finished = False
INTERNALERROR>         while not self.session_finished:
INTERNALERROR> >           self.loop_once()
INTERNALERROR> 
INTERNALERROR> dist       = 'load'
INTERNALERROR> numnodes   = 4
INTERNALERROR> self       = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/xdist/dsession.py:204: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> 
INTERNALERROR>     def loop_once(self):
INTERNALERROR>         """ process one callback from one of the slaves. """
INTERNALERROR>         while 1:
INTERNALERROR>             try:
INTERNALERROR>                 eventcall = self.queue.get(timeout=2.0)
INTERNALERROR>                 break
INTERNALERROR>             except queue.Empty:
INTERNALERROR>                 continue
INTERNALERROR>         callname, kwargs = eventcall
INTERNALERROR>         assert callname, kwargs
INTERNALERROR>         method = "slave_" + callname
INTERNALERROR>         call = getattr(self, method)
INTERNALERROR>         self.log("calling method: %s(**%s)" % (method, kwargs))
INTERNALERROR> >       call(**kwargs)
INTERNALERROR> 
INTERNALERROR> call       = <bound method DSession.slave_testreport of <xdist.dsession.DSession instance at 0x161e8c0>>
INTERNALERROR> callname   = 'testreport'
INTERNALERROR> eventcall  = ('testreport', {'node': <SlaveController gw3>, 'rep': <TestReport 'pytools/test/test_data_table.py::test_len' when='call' outcome='passed'>})
INTERNALERROR> kwargs     = {'node': <SlaveController gw3>, 'rep': <TestReport 'pytools/test/test_data_table.py::test_len' when='call' outcome='passed'>}
INTERNALERROR> method     = 'slave_testreport'
INTERNALERROR> self       = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/xdist/dsession.py:222: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> node = <SlaveController gw3>
INTERNALERROR> rep = <TestReport 'pytools/test/test_data_table.py::test_len' when='call' outcome='passed'>
INTERNALERROR> 
INTERNALERROR>     def slave_testreport(self, node, rep):
INTERNALERROR>         if rep.when in ("setup", "call"):
INTERNALERROR> >           self.sched.remove_item(node, rep.nodeid)
INTERNALERROR> 
INTERNALERROR> node       = <SlaveController gw3>
INTERNALERROR> rep        = <TestReport 'pytools/test/test_data_table.py::test_len' when='call' outcome='passed'>
INTERNALERROR> self       = <xdist.dsession.DSession instance at 0x161e8c0>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/xdist/dsession.py:282: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <xdist.dsession.LoadScheduling instance at 0x169c758>
INTERNALERROR> node = <SlaveController gw3>, item = 'pytools/test/test_data_table.py::test_len'
INTERNALERROR> 
INTERNALERROR>     def remove_item(self, node, item):
INTERNALERROR>         if item not in self.item2nodes:
INTERNALERROR>             raise AssertionError(item, self.item2nodes)
INTERNALERROR>         nodes = self.item2nodes[item]
INTERNALERROR>         if node in nodes: # the node might have gone down already
INTERNALERROR>             nodes.remove(node)
INTERNALERROR>         #if not nodes:
INTERNALERROR>         #    del self.item2nodes[item]
INTERNALERROR>         pending = self.node2pending[node]
INTERNALERROR> >       pending.remove(item)
INTERNALERROR> E       ValueError: list.remove(x): x not in list
INTERNALERROR> 
INTERNALERROR> item       = 'pytools/test/test_data_table.py::test_len'
INTERNALERROR> node       = <SlaveController gw3>
INTERNALERROR> nodes      = []
INTERNALERROR> pending    = ['pytools/test/test_data_table.py::test_sort', 'pytools/test/test_math_stuff.py::test_variance', 'pymbolic/test/test_p...yublas/test/test_pyublas.py::test_vec_slice_noncontig_inplace', 'pyublas/test/test_pyublas.py::test_matrix_slice', ...]
INTERNALERROR> self       = <xdist.dsession.LoadScheduling instance at 0x169c758>
INTERNALERROR> 
INTERNALERROR> env/lib/python2.6/site-packages/xdist/dsession.py:103: ValueError

better reporting for erroring xfail expressions

Originally reported by: BitBucket: spacey, GitHub: spacey


The following should work, and I do believe it worked for me until recently (haven't run this test in about a month):

#!/usr/local/bin/python
import pyodbc
import pytest
class TestQueries(object):
    @pytest.mark.xfail("pyodbc.version < 2.1.8")  
    # @pytest.mark.xfail
    def test_insert_cnchar_cnvarchar(self, setup):
        """
        Until pyodbc is upgraded to 2.1.8, this test will fail to match.
        """
        pass
def pytest_funcarg__setup(request):
    c = request.config
    if not hasattr(c, 'ds'):
        print "Setting up the request config"
        c.DSN = 'DATABASE'
        c.initial_database = 'sandbox'
        c.use_gssapi = True
        c.ds = pyodbc.connect("DSN={0};UID=;PWD=".format(c.DSN))
        c.cursor = c.ds.cursor()
    return c

Now it exits with a stack trace like so:

[...]
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR>
INTERNALERROR> self = <_pytest.skipping.MarkEvaluator instance at 0xe57488>
INTERNALERROR>
INTERNALERROR>     def istrue(self):
INTERNALERROR>         if self.holder:
INTERNALERROR>             d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
INTERNALERROR>             if self.holder.args:
INTERNALERROR>                 self.result = False
INTERNALERROR>                 for expr in self.holder.args:
INTERNALERROR>                     self.expr = expr
INTERNALERROR>                     if isinstance(expr, str):
INTERNALERROR> >                       result = cached_eval(self.item.config, expr, d)
INTERNALERROR>
INTERNALERROR> d          = {'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'AssertionError': <class 'py._code.assertion...nfig object at 0xb0b650>, 'os': <module 'os' from '/u/nortonp/lib/python2.6/os.pyc'>, 'sys': <module 'sys' (built-in)>}
INTERNALERROR> expr       = 'pyodbc.version < 2.1.8'
INTERNALERROR> self       = <_pytest.skipping.MarkEvaluator instance at 0xe57488>
INTERNALERROR>
INTERNALERROR> ../../lib/python2.6/site-packages/_pytest/skipping.py:43:
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR>
INTERNALERROR> config = <_pytest.config.Config object at 0xb0b650>, expr = 'pyodbc.version < 2.1.8'
INTERNALERROR> d = {'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'AssertionError': <class 'py._code.assertion...nfig object at 0xb0b650>, 'os': <module 'os' from '/u/nortonp/lib/python2.6/os.pyc'>, 'sys': <module 'sys' (built-in)>}
INTERNALERROR>
INTERNALERROR>     def cached_eval(config, expr, d):
INTERNALERROR>         if not hasattr(config, '_evalcache'):
INTERNALERROR>             config._evalcache = {}
INTERNALERROR>         try:
INTERNALERROR>             return config._evalcache[expr]
INTERNALERROR>         except KeyError:
INTERNALERROR>             #import sys
INTERNALERROR>             #print >>sys.stderr, ("cache-miss: %r" % expr)
INTERNALERROR> >           config._evalcache[expr] = x = eval(expr, d)
INTERNALERROR> E             File "<string>", line 1
INTERNALERROR> E               pyodbc.version < 2.1.8
INTERNALERROR> E                                    ^
INTERNALERROR> E           SyntaxError: unexpected EOF while parsing
INTERNALERROR>
INTERNALERROR> config     = <_pytest.config.Config object at 0xb0b650>
INTERNALERROR> d          = {'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'AssertionError': <class 'py._code.assertion...nfig object at 0xb0b650>, 'os': <module 'os' from '/u/nortonp/lib/python2.6/os.pyc'>, 'sys': <module 'sys' (built-in)>}
INTERNALERROR> expr       = 'pyodbc.version < 2.1.8'
INTERNALERROR>
INTERNALERROR> ../../lib/python2.6/site-packages/_pytest/skipping.py:182: SyntaxError

Working around this involves this ugly hack:

    @pytest.mark.xfail("'{0}' < '{1}'".format(pyodbc.version, str('2.1.8')))  

Thanks.


assert reinterpretation fails for some code layouts

Originally reported by: Ronny Pfannschmidt (BitBucket: RonnyPfannschmidt, GitHub: RonnyPfannschmidt)


the code example is

#!python

def test_assert():
    result = None
    assert result == [
        (None, [ 'some text\n', 'more text\n']),
    ]

the given output is

$ py.test test_assert.py 
============================= test session starts ==============================
platform linux2 -- Python 2.6.6 -- pytest-2.0.0dev0
test path 1: test_assert.py

test_assert.py F

=================================== FAILURES ===================================
_________________________________ test_assert __________________________________

    def test_assert():
        result = None
        assert result == [
>           (None, [ 'some text\n', 'more text\n']),
E           AssertionError: (assertion failed, but when it was re-run for printing intermediate values, it did not fail.  Suggestions: compute assert expression before the assert or use --no-assert)

test_assert.py:5: AssertionError
=========================== 1 failed in 0.20 seconds ===========================

Add a pytest option to not reinterpret exceptions in hooks

Originally reported by: Vyacheslav Rafalskiy (BitBucket: s4g, GitHub: s4g)


In some use cases, especially in functional testing, the pytest_configure(), pytest_sessionstart() and other hooks can be loaded with heavy setup code, which can fail in many different ways. If exceptions in such code are reinterpreted, as is the case in pytest 2.0.2, the important pre-formatted messages and traces are lost, or at least disfigured by long listings with every line prepended with 'INTERNALERROR>'.

It is desirable to be able to avoid such reinterpretation with a command-line option or other means.

Presently, I use the following monkey-patch as a workaround:

#!python

import sys, _pytest.core

def _notify_exception(self, excinfo):
    excrepr = excinfo.getrepr(style='native')
    sys.stderr.write(excrepr)

_pytest.core.PluginManager.notify_exception = _notify_exception

ValueError: I/O operation on closed file

Originally reported by: Alfredo Deza (BitBucket: alfredodeza, GitHub: alfredodeza)


There is a problem with the logging module and py.test

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1472, in shutdown
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1472, in shutdown
    h.flush()
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 740, in flush
    self.stream.flush()
    h.flush()
ValueError: I/O operation on closed file

It seems that if it runs with the '-s' flag it doesn't do this anymore.


Parse fails for triple quotes in assert

Originally reported by: Henrik Vendelbo (BitBucket: thepian, GitHub: thepian)


I have a test run for a PyPy builtin module that asserts a multiline string.

assert text == """
...
""" % info

Running the test fails in this form parsing the test source, but when separating the expected string into a variable avoids the failure.

Failure output:
http://pastebin.com/LuiQjh96

The test:
https://bitbucket.org/thepian/meshed/src/a2ad762bbf05/pypy/module/installation/test/test_execute.py


assert has strange behavior with numpy arrays

Originally reported by: Anonymous


import numpy as np

def test_array():
assert not(any(np.array([0, -1]) < 0))

I have this file as test3.py
If I run this with
py.test test3.py

I get the following output
$ py.test test3.py
============================= test session starts ==============================
platform linux2 -- Python 2.6.6 -- pytest-2.0.0
collected 1 items

test3.py F

=================================== FAILURES ===================================
__________________________________ test_array __________________________________

self = AssertionError()

def __init__(self, *args):
    BuiltinAssertionError.__init__(self, *args)
    if args:
        try:
            self.msg = str(args[0])
        except py.builtin._sysex:
            raise
        except:
            self.msg = "<[broken __repr__] %s at %0xd>" %(
                args[0].__class__, id(args[0]))
    else:
        f = py.code.Frame(sys._getframe(1))
        try:
            source = f.code.fullsource
            if source is not None:
                try:
                    source = source.getstatement(f.lineno, assertion=True)
                except IndexError:
                    source = None
                else:
                    source = str(source.deindent()).strip()
        except py.error.ENOENT:
            source = None
            # this can also occur during reinterpretation, when the
            # co_filename is set to "<run>".
        if source:
          self.msg = reinterpret(source, f, should_fail=True)

/usr/local/lib/python2.6/dist-packages/py/_code/assertion.py:79:


source = 'assert not(any(np.array([0, -1]) < 0))'
frame = <py._code.code.Frame object at 0x96208cc>, should_fail = True

def interpret(source, frame, should_fail=False):
    mod = ast.parse(source)
    visitor = DebugInterpreter(frame)
    try:
      visitor.visit(mod)

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:48:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
node = <_ast.Module object at 0x96788ac>

def visit(self, node):
    """Visit a node."""
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
  return visitor(node)

/usr/lib/python2.6/ast.py:231:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
mod = <_ast.Module object at 0x96788ac>

def visit_Module(self, mod):
    for stmt in mod.body:
      self.visit(stmt)

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:146:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
node = <_ast.Assert object at 0x967872c>

def visit(self, node):
    """Visit a node."""
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
  return visitor(node)

/usr/lib/python2.6/ast.py:231:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
assrt = <_ast.Assert object at 0x967872c>

def visit_Assert(self, assrt):
  test_explanation, test_result = self.visit(assrt.test)

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:319:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
node = <_ast.UnaryOp object at 0x96785ac>

def visit(self, node):
    """Visit a node."""
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
  return visitor(node)

/usr/lib/python2.6/ast.py:231:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
unary = <_ast.UnaryOp object at 0x96785ac>

def visit_UnaryOp(self, unary):
    pattern = unary_map[unary.op.__class__]
  operand_explanation, operand_result = self.visit(unary.operand)

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:202:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
node = <_ast.Call object at 0x96789cc>

def visit(self, node):
    """Visit a node."""
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
  return visitor(node)

/usr/lib/python2.6/ast.py:231:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
call = <_ast.Call object at 0x96789cc>

def visit_Call(self, call):
    func_explanation, func = self.visit(call.func)
    arg_explanations = []
    ns = {"__exprinfo_func" : func}
    arguments = []
    for arg in call.args:
      arg_explanation, arg_result = self.visit(arg)

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:232:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
node = <_ast.Compare object at 0x9678a0c>

def visit(self, node):
    """Visit a node."""
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
  return visitor(node)

/usr/lib/python2.6/ast.py:231:


self = <py._code._assertionnew.DebugInterpreter object at 0x9678a4c>
comp = <_ast.Compare object at 0x9678a0c>

def visit_Compare(self, comp):
    left = comp.left
    left_explanation, left_result = self.visit(left)
    for op, next_op in zip(comp.ops, comp.comparators):
        next_explanation, next_result = self.visit(next_op)
        op_symbol = operator_map[op.__class__]
        explanation = "%s %s %s" % (left_explanation, op_symbol,
                                    next_explanation)
        source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
        co = self._compile(source)
        try:
            result = self.frame.eval(co, __exprinfo_left=left_result,
                                     __exprinfo_right=next_result)
        except Exception:
            raise Failure(explanation)
      if not result:

E ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

/usr/local/lib/python2.6/dist-packages/py/_code/_assertionnew.py:177: ValueError
=========================== 1 failed in 0.23 seconds ===========================
$


Plugins specified with -h are not loaded when using multiprocessing with xdist

Originally reported by: Yoann Roman (BitBucket: silentsound, GitHub: silentsound)


I have a custom py.test plugin in a package. When I load it with py.test -h package.plugin, it loads fine. When I use py.test -h package.plugin -n 4, the main session loads it, but the plugin isn't loaded by the separate 4 processes running the tests.

Is that expected behavior?


teardown_module() is not called when the documentation says it is.

Originally reported by: Jeff Stearns (BitBucket: jps11, GitHub: jps11)


http://pytest.org/xunit_setup.html#module-level-setup-teardown says "//If you have multiple test functions and test classes in a single module you can optionally implement the following fixture methods which will usually be called once for all the functions://".

#!python

def setup_module(module):
    """ setup up any state specific to the execution
        of the given module.
    """

def teardown_module(module):
    """ teardown any state that was previously setup
        with a setup_module method.
    """

I assume that "//will usually be called//" means "//will be called in pairs unless prevented by catastrophic failure//".

But this is easily disproven by the following test file. teardown_module() is not called. It should be.

#!python

import py.test  # version 2.0.1

def setup_module(mod):
    print('@setup_module')

def teardown_module(mod):
    '''Sadly, py.test 2.0.1 does NOT invoke this function if a test fails.
    '''
    print('@teardown_module')

def test_divide():
    0/0



--------------- Captured stdout -----------
@setup_module

UnboundLocalError: local variable 'end' referenced before assignment

Originally reported by: BitBucket: blep, GitHub: blep


I'm not sure what is going on, but I started to get the error below. The full stack and tests are attached.

Environment: Python 3.2b2, Windows XPSP3, py.test 2.0

C:\Python32\lib\site-packages\py-1.4.0-py3.2.egg\py_code\source.py:142: in getstatementrange

  return start, end

E UnboundLocalError: local variable 'end' referenced before assignment


Print traceback on DocTest Exception

Originally reported by: BitBucket: pasdavoine, GitHub: pasdavoine


Running a doctest with say :

#!python

>>> import foo

If some file in the import chain has an error (eg. importError) pytest will print :

UNEXPECTED EXCEPTION: ImportError('cannot import name bar',)

But I won't know where 'bar' is imported. I need the traceback.

So here is a patch in order for pytest to print the traceback. For example output would be :

#!python

016   >>> import foo
UNEXPECTED EXCEPTION: Traceback (most recent call last):

  File "/usr/lib/python2.6/doctest.py", line 1253, in __run
    compileflags, 1) in test.globs

  File "<doctest test_baz.txt[0]>", line 1, in <module>

  File "/path/to/code/foo/__init__.py", line 8, in <module>
    from baz import x

  File "/path/to/code/foo/baz.py", line 10, in <module>
    from bar import so_important

ImportError: No module named bar

addcall does not allow binding of keyword args in parametrized test

Originally reported by: BitBucket: blep, GitHub: blep


When calling metafunc.addcall in pytest_generate_tests and providing keyword args with default value, addcall fails with a message such as:

bug\pytest_generator_kwargs.py:15: in pytest_generate_tests
>               metafunc.addcall( funcargs=kwargs )
C:\Python32\lib\site-packages\pytest-2.0.3-py3.2.egg\_pytest\python.py:550: in addcall
>                   pytest.fail("funcarg %r not used in this %r function." % (name, self.function))
E                   Failed: funcarg 'dbo_class' not used in this function.

Code example to reproduce the issue:

#!python

META_DBO_SCENARIOS = [
    dict( dbo_class=int,
          key_properties=['id'],
          value_properties=['content', 'name']
          )
    ]

def pytest_generate_tests(metafunc):
    if 'meta_dbo_iter' in metafunc.funcargnames:
        for scenario in META_DBO_SCENARIOS:
            kwargs = dict(meta_dbo_iter=None) # dummy parameter
            kwargs.update( scenario )
            metafunc.addcall( funcargs=kwargs )

def test_meta_dbo( meta_dbo_iter, dbo_class=None,
                   key_names=(), value_names=(),
                   auto_id=None ):
    """Checks the properties meta-data of a dbo class.
    """
    # ...

pytest + xdist not playing well (INTERNALLERROR)

Originally reported by: Alfredo Deza (BitBucket: alfredodeza, GitHub: alfredodeza)


Hi, I am trying to use pytest-xdist with the latest pytest (2.0.1dev5) and getting a huge INTERNALERROR traceback.

These are the versions I have currently installed:

  • py 1.4.0
  • pytest 2.0.1.dev5
  • pytest-xdist 1.6.dev2
  • execnet 1.0.9

The complete traceback from running py.test -n2

========================================================= test session starts =========================================================
platform darwin -- Python 2.6.1 -- pytest-2.0.1.dev5
gw0 IINTERNALERROR> config = <_pytest.config.Config object at 0x1032fefd0>
INTERNALERROR> 
INTERNALERROR>     def pytest_cmdline_main(config):
INTERNALERROR>         """ default command line protocol for initialization, session,
INTERNALERROR>         running tests and reporting. """
INTERNALERROR>         session = Session(config)
INTERNALERROR>         session.exitstatus = EXIT_OK
INTERNALERROR>         try:
INTERNALERROR>             config.pluginmanager.do_configure(config)
INTERNALERROR> >           config.hook.pytest_sessionstart(session=session)
INTERNALERROR> 
INTERNALERROR> config     = <_pytest.config.Config object at 0x1032fefd0>
INTERNALERROR> session    = <Session 'quid'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/main.py:63: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <HookCaller 'pytest_sessionstart'>
INTERNALERROR> 
INTERNALERROR>     def __call__(self, **kwargs):
INTERNALERROR>         methods = self.hookrelay._pm.listattr(self.name)
INTERNALERROR> >       return self._docall(methods, kwargs)
INTERNALERROR> 
INTERNALERROR> kwargs     = {'session': <Session 'quid'>}
INTERNALERROR> methods    = [<bound method DSession.pytest_sessionstart of <xdist.dsession.DSession instance at 0x10395b440>>, <bound method TerminalReporter.pytest_sessionstart of <_pytest.terminal.TerminalReporter instance at 0x103868dd0>>]
INTERNALERROR> self       = <HookCaller 'pytest_sessionstart'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/core.py:390: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <HookCaller 'pytest_sessionstart'>
INTERNALERROR> methods = [<bound method DSession.pytest_sessionstart of <xdist.dsession.DSession instance at 0x10395b440>>, <bound method TerminalReporter.pytest_sessionstart of <_pytest.terminal.TerminalReporter instance at 0x103868dd0>>]
INTERNALERROR> kwargs = {'session': <Session 'quid'>}
INTERNALERROR> 
INTERNALERROR>     def _docall(self, methods, kwargs):
INTERNALERROR>         self.trace(self.name, kwargs)
INTERNALERROR>         self.trace.root.indent += 1
INTERNALERROR>         mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
INTERNALERROR>         try:
INTERNALERROR> >           res = mc.execute()
INTERNALERROR> 
INTERNALERROR> kwargs     = {'session': <Session 'quid'>}
INTERNALERROR> mc         = <MultiCall 0 results, 0 meths, kwargs={'session': <Session 'quid'>}>
INTERNALERROR> methods    = [<bound method DSession.pytest_sessionstart of <xdist.dsession.DSession instance at 0x10395b440>>, <bound method TerminalReporter.pytest_sessionstart of <_pytest.terminal.TerminalReporter instance at 0x103868dd0>>]
INTERNALERROR> self       = <HookCaller 'pytest_sessionstart'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/core.py:401: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <MultiCall 0 results, 0 meths, kwargs={'session': <Session 'quid'>}>
INTERNALERROR> 
INTERNALERROR>     def execute(self):
INTERNALERROR>         while self.methods:
INTERNALERROR>             method = self.methods.pop()
INTERNALERROR>             kwargs = self.getkwargs(method)
INTERNALERROR> >           res = method(**kwargs)
INTERNALERROR> 
INTERNALERROR> kwargs     = {'session': <Session 'quid'>}
INTERNALERROR> method     = <bound method DSession.pytest_sessionstart of <xdist.dsession.DSession instance at 0x10395b440>>
INTERNALERROR> res        = None
INTERNALERROR> self       = <MultiCall 0 results, 0 meths, kwargs={'session': <Session 'quid'>}>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/core.py:322: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <xdist.dsession.DSession instance at 0x10395b440>, session = <Session 'quid'>
INTERNALERROR> 
INTERNALERROR>     @pytest.mark.trylast
INTERNALERROR>     def pytest_sessionstart(self, session):
INTERNALERROR>         self.nodemanager = NodeManager(self.config)
INTERNALERROR> >       self.nodemanager.setup_nodes(putevent=self.queue.put)
INTERNALERROR> 
INTERNALERROR> self       = <xdist.dsession.DSession instance at 0x10395b440>
INTERNALERROR> session    = <Session 'quid'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/xdist/dsession.py:180: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <xdist.slavemanage.NodeManager object at 0x1039cee50>
INTERNALERROR> putevent = <bound method Queue.put of <Queue.Queue instance at 0x103959908>>
INTERNALERROR> 
INTERNALERROR>     def setup_nodes(self, putevent):
INTERNALERROR> >       self.makegateways()
INTERNALERROR> 
INTERNALERROR> putevent   = <bound method Queue.put of <Queue.Queue instance at 0x103959908>>
INTERNALERROR> self       = <xdist.slavemanage.NodeManager object at 0x1039cee50>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/xdist/slavemanage.py:50: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <xdist.slavemanage.NodeManager object at 0x1039cee50>
INTERNALERROR> 
INTERNALERROR>     def makegateways(self):
INTERNALERROR>         assert not list(self.group)
INTERNALERROR>         self.config.hook.pytest_xdist_setupnodes(config=self.config,
INTERNALERROR>             specs=self.specs)
INTERNALERROR>         for spec in self.specs:
INTERNALERROR> >           gw = self.group.makegateway(spec)
INTERNALERROR> 
INTERNALERROR> self       = <xdist.slavemanage.NodeManager object at 0x1039cee50>
INTERNALERROR> spec       = <XSpec '1'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/xdist/slavemanage.py:46: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
INTERNALERROR> 
INTERNALERROR> self = <Group []>, spec = <XSpec '1'>
INTERNALERROR> 
INTERNALERROR>     def makegateway(self, spec=None):
INTERNALERROR>         """create and configure a gateway to a Python interpreter.
INTERNALERROR>             The ``spec`` string encodes the target gateway type
INTERNALERROR>             and configuration information. The general format is::
INTERNALERROR>     
INTERNALERROR>                 key1=value1//key2=value2//...
INTERNALERROR>     
INTERNALERROR>             If you leave out the ``=value`` part a True value is assumed.
INTERNALERROR>             Valid types: ``popen``, ``ssh=hostname``, ``socket=host:port``.
INTERNALERROR>             Valid configuration::
INTERNALERROR>     
INTERNALERROR>                 id=<string>     specifies the gateway id
INTERNALERROR>                 python=<path>   specifies which python interpreter to execute
INTERNALERROR>                 chdir=<path>    specifies to which directory to change
INTERNALERROR>                 nice=<path>     specifies process priority of new process
INTERNALERROR>                 env:NAME=value  specifies a remote environment variable setting.
INTERNALERROR>     
INTERNALERROR>             If no spec is given, self.defaultspec is used.
INTERNALERROR>             """
INTERNALERROR>         if not spec:
INTERNALERROR>             spec = self.defaultspec
INTERNALERROR>         if not isinstance(spec, XSpec):
INTERNALERROR>             spec = XSpec(spec)
INTERNALERROR>         self.allocate_id(spec)
INTERNALERROR>         if spec.popen:
INTERNALERROR>             gw = gateway.PopenGateway(python=spec.python, id=spec.id)
INTERNALERROR>         elif spec.ssh:
INTERNALERROR>             gw = gateway.SshGateway(spec.ssh, remotepython=spec.python,
INTERNALERROR>                                     ssh_config=spec.ssh_config, id=spec.id)
INTERNALERROR>         elif spec.socket:
INTERNALERROR>             assert not spec.python, (
INTERNALERROR>                 "socket: specifying python executables not yet supported")
INTERNALERROR>             from execnet.gateway_socket import SocketGateway
INTERNALERROR>             gateway_id = spec.installvia
INTERNALERROR>             if gateway_id:
INTERNALERROR>                 viagw = self[gateway_id]
INTERNALERROR>                 gw = SocketGateway.new_remote(viagw, id=spec.id)
INTERNALERROR>             else:
INTERNALERROR>                 host, port = spec.socket.split(":")
INTERNALERROR>                 gw = SocketGateway(host, port, id=spec.id)
INTERNALERROR>         else:
INTERNALERROR> >           raise ValueError("no gateway type found for %r" % (spec._spec,))
INTERNALERROR> E           ValueError: no gateway type found for '1'
INTERNALERROR> 
INTERNALERROR> self       = <Group []>
INTERNALERROR> spec       = <XSpec '1'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/execnet/multi.py:94: ValueError

==========================================================  in 0.11 seconds ==================

'tmpdir' test function argument does not work with Python 3.2 on Windows XP

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


This is actually a py.py bug report but since it directly breaks such a useful and visible feature as the 'tmpdir' test function argument in py.test I decided to report it here instead.

If you try using the 'tmpdir' test function argument on Windows XP with Python 3.2 you will get the following error during the test setup:

____________________________ ERROR at setup of test_xxx ____________________________

cls = <class 'py._path.local.LocalPath'>, prefix = 'pytest-', rootdir = local('c:\\docume~1\\jurko\\locals~1\\temp'), keep = 3
lock_timeout = 172800

    def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
                          lock_timeout = 172800):   # two days
        """ return unique directory with a number greater than the current
                maximum one.  The number is assumed to start directly after prefix.
                if keep is true directories with a number less than (maxnum-keep)
                will be removed.
            """
        if rootdir is None:
...
        src  = str(udir)
        dest = src[:src.rfind('-')] + '-' + username
        try:
            os.unlink(dest)
        except OSError:
            pass
        try:
>           os.symlink(src, dest)
E           NotImplementedError: CreateSymbolicLinkW not found

C:\Python\Python32\lib\site-packages\py-1.4.1-py3.2.egg\py\_path\local.py:751: NotImplementedError

The error seems to be caused by the fact that the Python 3.2 nt builtin module implementation added support for creating symbolic links in newer Windows OS versions. So, while in Python 3.1 calling nt.symlink() raised an AttributeError. In Python 3.2 it may work or it may raise NotImplementedError depending on the exact Windows OS version.

Here's a doc-string for the Python 3.2 nt.symlink:

>>> help(os.symlink)
Help on built-in function symlink in module nt:

symlink(...)
    symlink(src, dst, target_is_directory=False)

    Create a symbolic link pointing to src named dst.
    target_is_directory is required if the target is to be interpreted as
    a directory.
    This function requires Windows 6.0 or greater, and raises a
    NotImplementedError otherwise.

The fix seems to be simple (had to use it locally to get my tests working again here :-)) - just add NotImplementedError to the list of ignored exceptions on your os/nt.symlink() calls with a comment about Python 3.2+ raising this exception on older Windows OS versions.

Hope this helps.

Best regards,
Jurko Gospodnetić


set.py install fails when trying to install py

Originally reported by: Senthil Kumaran (BitBucket: orsenthil, GitHub: orsenthil)


I cloned pytest from the repo and try to install it using setup.py install command.

#!python

Searching for py>1.4.1
Reading http://pypi.python.org/simple/py/
Reading http://codespeak.net/py
Reading http://pypi.python.org/simple/py/XXX
Reading http://pylib.org
Reading http://codespeak.net/py/0.9.2/download.html
No local packages or download links found for py>1.4.1
Best match: None
Traceback (most recent call last):
 ...
AttributeError: 'NoneType' object has no attribute 'clone'

Select tests according to their mark

Originally reported by: David Burns (BitBucket: AutomatedTester, GitHub: AutomatedTester)


Currently the only way to sort through tests is with the -k option. Unfortunately this also looks at the method name which can run tests you don't want/expect.

For example

#!python



@pytest.mark.staging
def test_omg_dont_run_on_prod(self):
    pass

@pytest.mark.prod
def test_basics_still_work(self):
    pass


py.test -k prod #Runs the tests above even though the first one is marked as staging

It would be great if we could add a -m option that only looks at the marks.

so if I did py.test -m prod only the second test would be run.


offer download for offline documentation

Originally reported by: Anonymous


It would be great if there were downloadable documentation to use offline.

Offline documentation is valuable, not only to work when not connected or in a slow connection, but also when the current version is not the one used in a project.

Also, it is not uncommon that to build documentation for package X you must have specific versions of Sphinx, Docutilts, Pygment,..., and sometimes access to certain OSes (makefile, path assumptions, ...)

By example, for the current pytest (2.0.2), trying to render the docs from the src package in windows, with sphinx 1.0.7, docutils 0.7, I got

C:__pytest\pytest-2.0.2\doc>make.bat html
Running Sphinx v1.0.7

Exception occurred:
File "C:__pytest\pytest-2.0.2\doc\conf.py", line 55, in
assert py.path.local().relto(py.path.local(pytest.file).dirpath().dirpat
h())
...


AttributeError: 'Session' object has no attribute '_setupstate'

Originally reported by: Ralf Schmitt (BitBucket: schmir, GitHub: schmir)


Running py.test inside a directory, only containing conftest.py with the following contents:

def pytest_configure(config):

    import no_such_module

I get the following error

[py27]  ~/pytest-internal-error/ % py.test
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/main.py", line 62, in wrap_session
INTERNALERROR>     config.pluginmanager.do_configure(config)
INTERNALERROR>   File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 260, in do_configure
INTERNALERROR>     config.hook.pytest_configure(config=self._config)
INTERNALERROR>   File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 412, in __call__
INTERNALERROR>     return self._docall(methods, kwargs)
INTERNALERROR>   File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 423, in _docall
INTERNALERROR>     res = mc.execute()
INTERNALERROR>   File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 341, in execute
INTERNALERROR>     res = method(**kwargs)
INTERNALERROR>   File "/home/ralf/pytest-internal-error/conftest.py", line 2, in pytest_configure
INTERNALERROR>     import no_such_module
INTERNALERROR> ImportError: No module named no_such_module
INTERNALERROR> 
Traceback (most recent call last):
  File "/home/ralf/local/bin/py.test", line 9, in <module>
    load_entry_point('pytest==2.1.0.dev3', 'console_scripts', 'py.test')()
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 458, in main
    exitstatus = hook.pytest_cmdline_main(config=config)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 412, in __call__
    return self._docall(methods, kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 423, in _docall
    res = mc.execute()
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 341, in execute
    res = method(**kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/main.py", line 85, in pytest_cmdline_main
    return wrap_session(config, _main)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/main.py", line 80, in wrap_session
    exitstatus=session.exitstatus)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 412, in __call__
    return self._docall(methods, kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 423, in _docall
    res = mc.execute()
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 341, in execute
    res = method(**kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/runner.py", line 22, in pytest_sessionfinish
    rep = hook.pytest__teardown_final(session=session)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 412, in __call__
    return self._docall(methods, kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 423, in _docall
    res = mc.execute()
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 341, in execute
    res = method(**kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/capture.py", line 171, in pytest__teardown_final
    rep = __multicall__.execute()
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/core.py", line 341, in execute
    res = method(**kwargs)
  File "/home/ralf/local/lib/python2.7/site-packages/pytest-2.1.0.dev3-py2.7.egg/_pytest/runner.py", line 56, in pytest__teardown_final
    call = CallInfo(session._setupstate.teardown_all, when="teardown")
AttributeError: 'Session' object has no attribute '_setupstate'

Apply (framework/application) configuration

Originally reported by: Alfredo Deza (BitBucket: alfredodeza, GitHub: alfredodeza)


We are currently faced with the current problem: our web application needs to be configured with a specific test configuration but there is no way to tell py.test about it.

There are a few approaches to solve this problem, and for the most part, the solution points to write a plugin that can load/remember what configuration does the application need when running py.test

Writing a plugin is perfectly acceptable. However, this becomes cumbersome when different frameworks or applications that use different components are used (e.g. app1 uses Turbogears app2 uses Django).

Does it resonate with you to implement a way to tell py.test about a callable that would be in charge of loading a configuration? This is basically what our plugins do already, but it would take the load of writing a very similar plugin for different apps off the app itself.

Writing a small callable that is in charge of slapping the config so py.test knows about it would be trivial (or rather, more trivial than writing a plugin).

As a reference, we looked at how Pylons provides a plugin for a different test runner to solve this very same issue [0]

[0] http://wiki.pylonshq.com/display/pylonsdocs/Unit+Testing


Overhead per test function call too large.

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


pytest seems to have large overhead per test function call.

To demonstrate the effect try running the attached test script with its 'all_in_one' parameter set to:

  • True - to do all its work in a single test function call
  • False - to split its work over multiple test function calls

In my test run I got the following times with 1000 assertions:

  • all_in_one = True ... 0.03 seconds.

  • all_in_one = False ... 5.44 seconds.

    Hope this helps.

    Best regards,
    Jurko Gospodnetić


pytest slow on printing Tracebacks for large functions

Originally reported by: Torsten Landschoff (BitBucket: bluehorn, GitHub: bluehorn)


Hi Holger.

One of my unit tests is suddenly failing - for some reason it goes into a loop and does not come back. So I stop it using Ctrl-C, which leaves me at the prompt again. But I do not get a backtrace.

The test runner just tells me that there was a KeyboardInterrupt (which I knew already), but I am in the dark where the test was spinning.

Wouldn't it make more sense to get the backtrace displayed?

Thanks, Torsten


Avoid null-characters in junitxml output

Originally reported by: Floris Bruynooghe (BitBucket: flub, GitHub: flub)


It appears that at least Jenkins' XML parser does not like null-characters to appear in the JUnit XML file. To avoid this I've created a patch which simply removes any null characters from the XML file written by junitxml.

https://bitbucket.org/flub/pytest-queue/src/tip/junitxml_nullchar

If there is a consensus that this is indeed a bug in pytest and the correct way to fix I can commit this.


Can not run a .pyc/.pyo test script with a missing .py file.

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


This is a really minor issue opened as a followup to the original issue <<issue 20>>.

As it was stated there, using

    import pytest
    pytest.main(['--pyargs', __name__])

to make a test script 'self runnable' does not work when used on a compiled .pyc/.pyo file unless you have a corresponding source .py file available.
The error message displayed to the user is clear.

I also tested running a .pyc/.pyo test script using py.test directly and that does not seem to work either and the error message is both unclear and slightly misformatted:

    C:\Workplace>py.test xxx_test.cpython-32.pyc
    ========================== test session starts ==========================
    platform win32 -- Python 3.2.0 -- pytest-2.0.1
    collecting 0 itemsERROR: not found: C:\Workplace\xxx_test.cpython-32.pyc
    (no name 'C:\\Workplace\\xxx_test.cpython-32.pyc' in any of [])

Tested on Windows XP using Python 3.2rc2.

Hope this helps.

Best regards,
Jurko Gospodnetić


len(list) should be summarized in most cases

Originally reported by: BitBucket: wtanksleyjr, GitHub: wtanksleyjr


I have some code which runs:

assert len(mylist) == 2 *** *** 10

When this fails, py.test prints out something like:

  • len([something, more, else, thing, bla, ...]) == (2 *** *** 10)

The problem is that it's impossible to tell exactly why the assert is failing -- the whole list can't reasonably be printed, and truncating the list loses the information that actually matters.

If a list inside a len is truncated, it would make sense to either display another level of simplification OR to print only the length (since you can't display the whole list).


INTERNALERROR on Wrapper

Originally reported by: Alfredo Deza (BitBucket: alfredodeza, GitHub: alfredodeza)


Hi,

I am currently writing a wrapper for py.test that is able to load and
set some environment configurations we need.

I am using pytest-2.0.0 and doing something like this::

import sys
import pytest

pytest.cmdline.main(sys.argv)

Which works perfectly fine... until it finds a failed test and tries to
print the information.

With no arguments passed it shows this::

INTERNALERROR> 
INTERNALERROR> self = <TestCaseFunction 'test_schedule_create'>, excinfo = <ExceptionInfo AppError tblen=4>, outerr = None
INTERNALERROR> 
INTERNALERROR>     def repr_failure(self, excinfo, outerr=None):
INTERNALERROR>         assert outerr is None, "XXX outerr usage is deprecated"
INTERNALERROR>         return self._repr_failure_py(excinfo,
INTERNALERROR> >           style=self.config.option.tbstyle)
INTERNALERROR> 
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> outerr     = None
INTERNALERROR> self       = <TestCaseFunction 'test_schedule_create'>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/python.py:356: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <TestCaseFunction 'test_schedule_create'>, excinfo = <ExceptionInfo AppError tblen=4>, style = 'long'
INTERNALERROR> 
INTERNALERROR>     def _repr_failure_py(self, excinfo, style="long"):
INTERNALERROR>         if excinfo.errisinstance(FuncargRequest.LookupError):
INTERNALERROR>             fspath, lineno, msg = self.reportinfo()
INTERNALERROR>             lines, _ = inspect.getsourcelines(self.obj)
INTERNALERROR>             for i, line in enumerate(lines):
INTERNALERROR>                 if line.strip().startswith('def'):
INTERNALERROR>                     return FuncargLookupErrorRepr(fspath, lineno,
INTERNALERROR>             lines[:i+1], str(excinfo.value))
INTERNALERROR>         if excinfo.errisinstance(pytest.fail.Exception):
INTERNALERROR>             if not excinfo.value.pytrace:
INTERNALERROR>                 return str(excinfo.value)
INTERNALERROR>         return super(FunctionMixin, self)._repr_failure_py(excinfo,
INTERNALERROR> >           style=style)
INTERNALERROR> 
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> self       = <TestCaseFunction 'test_schedule_create'>
INTERNALERROR> style      = 'long'
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/python.py:351: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <TestCaseFunction 'test_schedule_create'>, excinfo = <ExceptionInfo AppError tblen=4>, style = 'long'
INTERNALERROR> 
INTERNALERROR>     def _repr_failure_py(self, excinfo, style=None):
INTERNALERROR>         if self.config.option.fulltrace:
INTERNALERROR>             style="long"
INTERNALERROR>         else:
INTERNALERROR>             self._prunetraceback(excinfo)
INTERNALERROR>         # XXX should excinfo.getrepr record all data and toterminal()
INTERNALERROR>         # process it?
INTERNALERROR>         if style is None:
INTERNALERROR>             if self.config.option.tbstyle == "short":
INTERNALERROR>                 style = "short"
INTERNALERROR>             else:
INTERNALERROR>                 style = "long"
INTERNALERROR>         return excinfo.getrepr(funcargs=True,
INTERNALERROR>                                showlocals=self.config.option.showlocals,
INTERNALERROR> >                              style=style)
INTERNALERROR> 
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> self       = <TestCaseFunction 'test_schedule_create'>
INTERNALERROR> style      = 'long'
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/_pytest/session.py:250: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <ExceptionInfo AppError tblen=4>, showlocals = False, style = 'long', abspath = False, tbfilter = True
INTERNALERROR> funcargs = True
INTERNALERROR> 
INTERNALERROR>     def getrepr(self, showlocals=False, style="long",
INTERNALERROR>             abspath=False, tbfilter=True, funcargs=False):
INTERNALERROR>         """ return str()able representation of this exception info.
INTERNALERROR>                 showlocals: show locals per traceback entry
INTERNALERROR>                 style: long|short|no|native traceback style
INTERNALERROR>                 tbfilter: hide entries (where __tracebackhide__ is true)
INTERNALERROR>             """
INTERNALERROR>         if style == 'native':
INTERNALERROR>             import traceback
INTERNALERROR>             return ''.join(traceback.format_exception(
INTERNALERROR>                 self.type,
INTERNALERROR>                 self.value,
INTERNALERROR>                 self.traceback[0]._rawentry,
INTERNALERROR>                 ))
INTERNALERROR>     
INTERNALERROR>         fmt = FormattedExcinfo(showlocals=showlocals, style=style,
INTERNALERROR>             abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
INTERNALERROR> >       return fmt.repr_excinfo(self)
INTERNALERROR> 
INTERNALERROR> abspath    = False
INTERNALERROR> fmt        = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> funcargs   = True
INTERNALERROR> self       = <ExceptionInfo AppError tblen=4>
INTERNALERROR> showlocals = False
INTERNALERROR> style      = 'long'
INTERNALERROR> tbfilter   = True
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:371: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <py._code.code.FormattedExcinfo object at 0x1040a48d0>, excinfo = <ExceptionInfo AppError tblen=4>
INTERNALERROR> 
INTERNALERROR>     def repr_excinfo(self, excinfo):
INTERNALERROR> >       reprtraceback = self.repr_traceback(excinfo)
INTERNALERROR> 
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> self       = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:544: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <py._code.code.FormattedExcinfo object at 0x1040a48d0>, excinfo = <ExceptionInfo AppError tblen=4>
INTERNALERROR> 
INTERNALERROR>     def repr_traceback(self, excinfo):
INTERNALERROR>         traceback = excinfo.traceback
INTERNALERROR>         if self.tbfilter:
INTERNALERROR>             traceback = traceback.filter()
INTERNALERROR>         recursionindex = None
INTERNALERROR>         if excinfo.errisinstance(RuntimeError):
INTERNALERROR>             recursionindex = traceback.recursionindex()
INTERNALERROR>         last = traceback[-1]
INTERNALERROR>         entries = []
INTERNALERROR>         extraline = None
INTERNALERROR>         for index, entry in enumerate(traceback):
INTERNALERROR>             einfo = (last == entry) and excinfo or None
INTERNALERROR> >           reprentry = self.repr_traceback_entry(entry, einfo)
INTERNALERROR> 
INTERNALERROR> einfo      = <ExceptionInfo AppError tblen=4>
INTERNALERROR> entries    = [<py._code.code.ReprEntry instance at 1040bde60>, <py._code.code.ReprEntry instance at 1040bd758>, <py._code.code.ReprEntry instance at 103d0b878>]
INTERNALERROR> entry      = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> extraline  = None
INTERNALERROR> index      = 3
INTERNALERROR> last       = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> recursionindex = None
INTERNALERROR> reprentry  = <py._code.code.ReprEntry instance at 103d0b878>
INTERNALERROR> self       = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> traceback  = [<TracebackEntry /opt/shootq/quid/quid/tests/test_schedules.py:282>, <Tracebac...<TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>]
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:536: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> entry = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> excinfo = <ExceptionInfo AppError tblen=4>
INTERNALERROR> 
INTERNALERROR>     def repr_traceback_entry(self, entry, excinfo=None):
INTERNALERROR>         # excinfo is not None if this is the last tb entry
INTERNALERROR> >       source = self._getentrysource(entry)
INTERNALERROR> 
INTERNALERROR> entry      = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> excinfo    = <ExceptionInfo AppError tblen=4>
INTERNALERROR> self       = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:487: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> entry = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> 
INTERNALERROR>     def _getentrysource(self, entry):
INTERNALERROR> >       source = entry.getsource()
INTERNALERROR> 
INTERNALERROR> entry      = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> self       = <py._code.code.FormattedExcinfo object at 0x1040a48d0>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:413: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> 
INTERNALERROR>     def getsource(self):
INTERNALERROR>         """ return failing source code. """
INTERNALERROR>         source = self.frame.code.fullsource
INTERNALERROR>         if source is None:
INTERNALERROR>             return None
INTERNALERROR>         start = self.getfirstlinesource()
INTERNALERROR>         end = self.lineno
INTERNALERROR>         try:
INTERNALERROR>             _, end = source.getstatementrange(end)
INTERNALERROR>         except IndexError:
INTERNALERROR>             end = self.lineno + 1
INTERNALERROR>         # heuristic to stop displaying source on e.g.
INTERNALERROR>         #   if something:  # assume this causes a NameError
INTERNALERROR>         #      # _this_ lines and the one
INTERNALERROR>                #        below we don't want from entry.getsource()
INTERNALERROR>         for i in range(self.lineno, end):
INTERNALERROR> >           if source[i].rstrip().endswith(':'):
INTERNALERROR> 
INTERNALERROR> end        = 191
INTERNALERROR> i          = 190
INTERNALERROR> self       = <TracebackEntry build/bdist.macosx-10.6-universal/egg/webtest/__init__.py:191>
INTERNALERROR> source     = <py._code.source.Source object at 0x1040a0b90>
INTERNALERROR> start      = 157
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/code.py:179: 
INTERNALERROR> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
INTERNALERROR> 
INTERNALERROR> self = <py._code.source.Source object at 0x1040a0b90>, key = 190
INTERNALERROR> 
INTERNALERROR>     def __getitem__(self, key):
INTERNALERROR>         if isinstance(key, int):
INTERNALERROR> >           return self.lines[key]
INTERNALERROR> E           IndexError: list index out of range
INTERNALERROR> 
INTERNALERROR> key        = 190
INTERNALERROR> self       = <py._code.source.Source object at 0x1040a0b90>
INTERNALERROR> 
INTERNALERROR> ../../quidenv/lib/python2.6/site-packages/py/_code/source.py:55: IndexError

If I try an do "--no-capture" or "-s" I also get this traceback::

Traceback (most recent call last):
  File "/opt/shootq/quidenv/bin/teja", line 9, in <module>
    load_entry_point('teja==0.0.1', 'console_scripts', 'teja')()
  File "/opt/shootq/quid/teja/teja/__init__.py", line 169, in main_
    main()
  File "/opt/shootq/quid/teja/teja/__init__.py", line 52, in __init__
    self.parseArgs(argv)
  File "/opt/shootq/quid/teja/teja/__init__.py", line 126, in parseArgs
    tests.run()
  File "/opt/shootq/quid/teja/teja/runners.py", line 32, in run
    self.pytest()
  File "/opt/shootq/quid/teja/teja/runners.py", line 44, in pytest
    pytest.cmdline.main(self.argv)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 452, in main
    exitstatus = hook.pytest_cmdline_main(config=config)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 406, in __call__
    return self._docall(methods, kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 417, in _docall
    res = mc.execute()
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 338, in execute
    res = method(**kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/session.py", line 81, in pytest_cmdline_main
    exitstatus=session.exitstatus)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 406, in __call__
    return self._docall(methods, kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 417, in _docall
    res = mc.execute()
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 338, in execute
    res = method(**kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/terminal.py", line 280, in pytest_sessionfinish
    __multicall__.execute()
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 338, in execute
    res = method(**kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/runner.py", line 24, in pytest_sessionfinish
    rep = hook.pytest__teardown_final(session=session)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 406, in __call__
    return self._docall(methods, kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 417, in _docall
    res = mc.execute()
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/core.py", line 338, in execute
    res = method(**kwargs)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/capture.py", line 161, in pytest__teardown_final
    self.resumecapture(method)
  File "/opt/shootq/quidenv/lib/python2.6/site-packages/_pytest/capture.py", line 89, in resumecapture
    (self._capturing,))
ValueError: cannot resume, already capturing with 'no'

Running a test module as a script.

Originally reported by: Jurko Gospodnetić (BitBucket: jurko, GitHub: jurko)


I am trying to make my test modules runnable directly as scripts (e.g. python xxx.py) or as a python module (python -m xxx). Everything being done with Python 3.2.rc1 on Windows XP.

The closest I got so far is to add something like this to my test scripts:

    if __name__ == "__main__":
        import pytest
        pytest.main([__file__])

However, this does not work in all the cases.

Imagine the following scenario (I have attached files modeling this exact scenario so it can be more easily reproduced):

  • package module ppp
  • test module xxx.py contained inside package ppp

In it I can do the following:

  • 'python xxx.py' from the ppp folder
  • 'python -m xxx' from the ppp folder
  • 'python ppp\xxx.py' from the ppp's parent folder

but trying this:

  • 'python -m ppp.xxx' from the ppp's parent folder

causes the following error:

import file mismatch:
imported module 'ppp.xxx' has this __file__ attribute:
  ppp\xxx.py
which is not the same as the test file we want to collect:
  C:\Workplace\ppp\xxx.py
HINT: use a unique basename for your test file modules

Is there a better way to do get this functionality or is it something that is not supposed to be supported or is it something that needs fixing?

The error itself is reported from deep inside the py.py library and so far I have not been able to find a quick-fix for it.

Many thanks and best regards,
Jurko Gospodnetić


Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.