This attempts to fix CI which broke because of this test. Other warnings introduced in the future could break this test.
814 lines
27 KiB
Python
814 lines
27 KiB
Python
# -*- coding: utf-8 -*-
|
|
import os
|
|
import sys
|
|
|
|
import _pytest._code
|
|
import py
|
|
import pytest
|
|
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
|
|
|
|
|
|
class TestGeneralUsage:
|
|
def test_config_error(self, testdir):
|
|
testdir.makeconftest("""
|
|
def pytest_configure(config):
|
|
import pytest
|
|
raise pytest.UsageError("hello")
|
|
""")
|
|
result = testdir.runpytest(testdir.tmpdir)
|
|
assert result.ret != 0
|
|
result.stderr.fnmatch_lines([
|
|
'*ERROR: hello'
|
|
])
|
|
|
|
def test_root_conftest_syntax_error(self, testdir):
|
|
testdir.makepyfile(conftest="raise SyntaxError\n")
|
|
result = testdir.runpytest()
|
|
result.stderr.fnmatch_lines(["*raise SyntaxError*"])
|
|
assert result.ret != 0
|
|
|
|
def test_early_hook_error_issue38_1(self, testdir):
|
|
testdir.makeconftest("""
|
|
def pytest_sessionstart():
|
|
0 / 0
|
|
""")
|
|
result = testdir.runpytest(testdir.tmpdir)
|
|
assert result.ret != 0
|
|
# tracestyle is native by default for hook failures
|
|
result.stdout.fnmatch_lines([
|
|
'*INTERNALERROR*File*conftest.py*line 2*',
|
|
'*0 / 0*',
|
|
])
|
|
result = testdir.runpytest(testdir.tmpdir, "--fulltrace")
|
|
assert result.ret != 0
|
|
# tracestyle is native by default for hook failures
|
|
result.stdout.fnmatch_lines([
|
|
'*INTERNALERROR*def pytest_sessionstart():*',
|
|
'*INTERNALERROR*0 / 0*',
|
|
])
|
|
|
|
def test_early_hook_configure_error_issue38(self, testdir):
|
|
testdir.makeconftest("""
|
|
def pytest_configure():
|
|
0 / 0
|
|
""")
|
|
result = testdir.runpytest(testdir.tmpdir)
|
|
assert result.ret != 0
|
|
# here we get it on stderr
|
|
result.stderr.fnmatch_lines([
|
|
'*INTERNALERROR*File*conftest.py*line 2*',
|
|
'*0 / 0*',
|
|
])
|
|
|
|
def test_file_not_found(self, testdir):
|
|
result = testdir.runpytest("asd")
|
|
assert result.ret != 0
|
|
result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
|
|
|
|
def test_file_not_found_unconfigure_issue143(self, testdir):
|
|
testdir.makeconftest("""
|
|
def pytest_configure():
|
|
print("---configure")
|
|
def pytest_unconfigure():
|
|
print("---unconfigure")
|
|
""")
|
|
result = testdir.runpytest("-s", "asd")
|
|
assert result.ret == 4 # EXIT_USAGEERROR
|
|
result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
|
|
result.stdout.fnmatch_lines([
|
|
"*---configure",
|
|
"*---unconfigure",
|
|
])
|
|
|
|
|
|
def test_config_preparse_plugin_option(self, testdir):
|
|
testdir.makepyfile(pytest_xyz="""
|
|
def pytest_addoption(parser):
|
|
parser.addoption("--xyz", dest="xyz", action="store")
|
|
""")
|
|
testdir.makepyfile(test_one="""
|
|
def test_option(pytestconfig):
|
|
assert pytestconfig.option.xyz == "123"
|
|
""")
|
|
result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123", syspathinsert=True)
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
'*1 passed*',
|
|
])
|
|
|
|
def test_assertion_magic(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
def test_this():
|
|
x = 0
|
|
assert x
|
|
""")
|
|
result = testdir.runpytest(p)
|
|
result.stdout.fnmatch_lines([
|
|
"> assert x",
|
|
"E assert 0",
|
|
])
|
|
assert result.ret == 1
|
|
|
|
def test_nested_import_error(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
import import_fails
|
|
def test_this():
|
|
assert import_fails.a == 1
|
|
""")
|
|
testdir.makepyfile(import_fails="import does_not_work")
|
|
result = testdir.runpytest(p)
|
|
result.stdout.fnmatch_lines([
|
|
#XXX on jython this fails: "> import import_fails",
|
|
"ImportError while importing test module*",
|
|
"'No module named *does_not_work*",
|
|
])
|
|
assert result.ret == 2
|
|
|
|
def test_not_collectable_arguments(self, testdir):
|
|
p1 = testdir.makepyfile("")
|
|
p2 = testdir.makefile(".pyc", "123")
|
|
result = testdir.runpytest(p1, p2)
|
|
assert result.ret
|
|
result.stderr.fnmatch_lines([
|
|
"*ERROR: not found:*%s" %(p2.basename,)
|
|
])
|
|
|
|
def test_issue486_better_reporting_on_conftest_load_failure(self, testdir):
|
|
testdir.makepyfile("")
|
|
testdir.makeconftest("import qwerty")
|
|
result = testdir.runpytest("--help")
|
|
result.stdout.fnmatch_lines("""
|
|
*--version*
|
|
*warning*conftest.py*
|
|
""")
|
|
result = testdir.runpytest()
|
|
result.stderr.fnmatch_lines("""
|
|
*ERROR*could not load*conftest.py*
|
|
""")
|
|
|
|
|
|
def test_early_skip(self, testdir):
|
|
testdir.mkdir("xyz")
|
|
testdir.makeconftest("""
|
|
import pytest
|
|
def pytest_collect_directory():
|
|
pytest.skip("early")
|
|
""")
|
|
result = testdir.runpytest()
|
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
|
result.stdout.fnmatch_lines([
|
|
"*1 skip*"
|
|
])
|
|
|
|
def test_issue88_initial_file_multinodes(self, testdir):
|
|
testdir.makeconftest("""
|
|
import pytest
|
|
class MyFile(pytest.File):
|
|
def collect(self):
|
|
return [MyItem("hello", parent=self)]
|
|
def pytest_collect_file(path, parent):
|
|
return MyFile(path, parent)
|
|
class MyItem(pytest.Item):
|
|
pass
|
|
""")
|
|
p = testdir.makepyfile("def test_hello(): pass")
|
|
result = testdir.runpytest(p, "--collect-only")
|
|
result.stdout.fnmatch_lines([
|
|
"*MyFile*test_issue88*",
|
|
"*Module*test_issue88*",
|
|
])
|
|
|
|
def test_issue93_initialnode_importing_capturing(self, testdir):
|
|
testdir.makeconftest("""
|
|
import sys
|
|
print ("should not be seen")
|
|
sys.stderr.write("stder42\\n")
|
|
""")
|
|
result = testdir.runpytest()
|
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
|
assert "should not be seen" not in result.stdout.str()
|
|
assert "stderr42" not in result.stderr.str()
|
|
|
|
def test_conftest_printing_shows_if_error(self, testdir):
|
|
testdir.makeconftest("""
|
|
print ("should be seen")
|
|
assert 0
|
|
""")
|
|
result = testdir.runpytest()
|
|
assert result.ret != 0
|
|
assert "should be seen" in result.stdout.str()
|
|
|
|
@pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
|
|
reason="symlink not available on this platform")
|
|
def test_chdir(self, testdir):
|
|
testdir.tmpdir.join("py").mksymlinkto(py._pydir)
|
|
p = testdir.tmpdir.join("main.py")
|
|
p.write(_pytest._code.Source("""
|
|
import sys, os
|
|
sys.path.insert(0, '')
|
|
import py
|
|
print (py.__file__)
|
|
print (py.__path__)
|
|
os.chdir(os.path.dirname(os.getcwd()))
|
|
print (py.log)
|
|
"""))
|
|
result = testdir.runpython(p)
|
|
assert not result.ret
|
|
|
|
def test_issue109_sibling_conftests_not_loaded(self, testdir):
|
|
sub1 = testdir.tmpdir.mkdir("sub1")
|
|
sub2 = testdir.tmpdir.mkdir("sub2")
|
|
sub1.join("conftest.py").write("assert 0")
|
|
result = testdir.runpytest(sub2)
|
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
|
sub2.ensure("__init__.py")
|
|
p = sub2.ensure("test_hello.py")
|
|
result = testdir.runpytest(p)
|
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
|
result = testdir.runpytest(sub1)
|
|
assert result.ret == EXIT_USAGEERROR
|
|
|
|
def test_directory_skipped(self, testdir):
|
|
testdir.makeconftest("""
|
|
import pytest
|
|
def pytest_ignore_collect():
|
|
pytest.skip("intentional")
|
|
""")
|
|
testdir.makepyfile("def test_hello(): pass")
|
|
result = testdir.runpytest()
|
|
assert result.ret == EXIT_NOTESTSCOLLECTED
|
|
result.stdout.fnmatch_lines([
|
|
"*1 skipped*"
|
|
])
|
|
|
|
def test_multiple_items_per_collector_byid(self, testdir):
|
|
c = testdir.makeconftest("""
|
|
import pytest
|
|
class MyItem(pytest.Item):
|
|
def runtest(self):
|
|
pass
|
|
class MyCollector(pytest.File):
|
|
def collect(self):
|
|
return [MyItem(name="xyz", parent=self)]
|
|
def pytest_collect_file(path, parent):
|
|
if path.basename.startswith("conftest"):
|
|
return MyCollector(path, parent)
|
|
""")
|
|
result = testdir.runpytest(c.basename+"::"+"xyz")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*1 pass*",
|
|
])
|
|
|
|
def test_skip_on_generated_funcarg_id(self, testdir):
|
|
testdir.makeconftest("""
|
|
import pytest
|
|
def pytest_generate_tests(metafunc):
|
|
metafunc.addcall({'x': 3}, id='hello-123')
|
|
def pytest_runtest_setup(item):
|
|
print (item.keywords)
|
|
if 'hello-123' in item.keywords:
|
|
pytest.skip("hello")
|
|
assert 0
|
|
""")
|
|
p = testdir.makepyfile("""def test_func(x): pass""")
|
|
res = testdir.runpytest(p)
|
|
assert res.ret == 0
|
|
res.stdout.fnmatch_lines(["*1 skipped*"])
|
|
|
|
def test_direct_addressing_selects(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
def pytest_generate_tests(metafunc):
|
|
metafunc.addcall({'i': 1}, id="1")
|
|
metafunc.addcall({'i': 2}, id="2")
|
|
def test_func(i):
|
|
pass
|
|
""")
|
|
res = testdir.runpytest(p.basename + "::" + "test_func[1]")
|
|
assert res.ret == 0
|
|
res.stdout.fnmatch_lines(["*1 passed*"])
|
|
|
|
def test_direct_addressing_notfound(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
def test_func():
|
|
pass
|
|
""")
|
|
res = testdir.runpytest(p.basename + "::" + "test_notfound")
|
|
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
|
|
|
|
def test_initialization_error_issue49(self, testdir):
|
|
testdir.makeconftest("""
|
|
def pytest_configure():
|
|
x
|
|
""")
|
|
result = testdir.runpytest()
|
|
assert result.ret == 3 # internal error
|
|
result.stderr.fnmatch_lines([
|
|
"INTERNAL*pytest_configure*",
|
|
"INTERNAL*x*",
|
|
])
|
|
assert 'sessionstarttime' not in result.stderr.str()
|
|
|
|
@pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a'])
|
|
def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor):
|
|
testdir.makepyfile(test_fun="""
|
|
def test_a():
|
|
pass
|
|
def""")
|
|
result = testdir.runpytest(lookfor)
|
|
result.stdout.fnmatch_lines(['*SyntaxError*'])
|
|
if '::' in lookfor:
|
|
result.stderr.fnmatch_lines([
|
|
'*ERROR*',
|
|
])
|
|
assert result.ret == 4 # usage error only if item not found
|
|
|
|
def test_report_all_failed_collections_initargs(self, testdir):
|
|
testdir.makepyfile(test_a="def", test_b="def")
|
|
result = testdir.runpytest("test_a.py::a", "test_b.py::b")
|
|
result.stderr.fnmatch_lines([
|
|
"*ERROR*test_a.py::a*",
|
|
"*ERROR*test_b.py::b*",
|
|
])
|
|
|
|
def test_namespace_import_doesnt_confuse_import_hook(self, testdir):
|
|
# Ref #383. Python 3.3's namespace package messed with our import hooks
|
|
# Importing a module that didn't exist, even if the ImportError was
|
|
# gracefully handled, would make our test crash.
|
|
testdir.mkdir('not_a_package')
|
|
p = testdir.makepyfile("""
|
|
try:
|
|
from not_a_package import doesnt_exist
|
|
except ImportError:
|
|
# We handle the import error gracefully here
|
|
pass
|
|
|
|
def test_whatever():
|
|
pass
|
|
""")
|
|
res = testdir.runpytest(p.basename)
|
|
assert res.ret == 0
|
|
|
|
def test_unknown_option(self, testdir):
|
|
result = testdir.runpytest("--qwlkej")
|
|
result.stderr.fnmatch_lines("""
|
|
*unrecognized*
|
|
""")
|
|
|
|
def test_getsourcelines_error_issue553(self, testdir, monkeypatch):
|
|
monkeypatch.setattr("inspect.getsourcelines", None)
|
|
p = testdir.makepyfile("""
|
|
def raise_error(obj):
|
|
raise IOError('source code not available')
|
|
|
|
import inspect
|
|
inspect.getsourcelines = raise_error
|
|
|
|
def test_foo(invalid_fixture):
|
|
pass
|
|
""")
|
|
res = testdir.runpytest(p)
|
|
res.stdout.fnmatch_lines([
|
|
"*source code not available*",
|
|
"*fixture 'invalid_fixture' not found",
|
|
])
|
|
|
|
def test_plugins_given_as_strings(self, tmpdir, monkeypatch):
|
|
"""test that str values passed to main() as `plugins` arg
|
|
are interpreted as module names to be imported and registered.
|
|
#855.
|
|
"""
|
|
with pytest.raises(ImportError) as excinfo:
|
|
pytest.main([str(tmpdir)], plugins=['invalid.module'])
|
|
assert 'invalid' in str(excinfo.value)
|
|
|
|
p = tmpdir.join('test_test_plugins_given_as_strings.py')
|
|
p.write('def test_foo(): pass')
|
|
mod = py.std.types.ModuleType("myplugin")
|
|
monkeypatch.setitem(sys.modules, 'myplugin', mod)
|
|
assert pytest.main(args=[str(tmpdir)], plugins=['myplugin']) == 0
|
|
|
|
def test_parameterized_with_bytes_regex(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
import re
|
|
import pytest
|
|
@pytest.mark.parametrize('r', [re.compile(b'foo')])
|
|
def test_stuff(r):
|
|
pass
|
|
"""
|
|
)
|
|
res = testdir.runpytest(p)
|
|
res.stdout.fnmatch_lines([
|
|
'*1 passed*'
|
|
])
|
|
|
|
|
|
class TestInvocationVariants:
|
|
def test_earlyinit(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
import pytest
|
|
assert hasattr(pytest, 'mark')
|
|
""")
|
|
result = testdir.runpython(p)
|
|
assert result.ret == 0
|
|
|
|
@pytest.mark.xfail("sys.platform.startswith('java')")
|
|
def test_pydoc(self, testdir):
|
|
for name in ('py.test', 'pytest'):
|
|
result = testdir.runpython_c("import %s;help(%s)" % (name, name))
|
|
assert result.ret == 0
|
|
s = result.stdout.str()
|
|
assert 'MarkGenerator' in s
|
|
|
|
def test_import_star_py_dot_test(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
from py.test import *
|
|
#collect
|
|
#cmdline
|
|
#Item
|
|
#assert collect.Item is Item
|
|
#assert collect.Collector is Collector
|
|
main
|
|
skip
|
|
xfail
|
|
""")
|
|
result = testdir.runpython(p)
|
|
assert result.ret == 0
|
|
|
|
def test_import_star_pytest(self, testdir):
|
|
p = testdir.makepyfile("""
|
|
from pytest import *
|
|
#Item
|
|
#File
|
|
main
|
|
skip
|
|
xfail
|
|
""")
|
|
result = testdir.runpython(p)
|
|
assert result.ret == 0
|
|
|
|
def test_double_pytestcmdline(self, testdir):
|
|
p = testdir.makepyfile(run="""
|
|
import pytest
|
|
pytest.main()
|
|
pytest.main()
|
|
""")
|
|
testdir.makepyfile("""
|
|
def test_hello():
|
|
pass
|
|
""")
|
|
result = testdir.runpython(p)
|
|
result.stdout.fnmatch_lines([
|
|
"*1 passed*",
|
|
"*1 passed*",
|
|
])
|
|
|
|
def test_python_minus_m_invocation_ok(self, testdir):
|
|
p1 = testdir.makepyfile("def test_hello(): pass")
|
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
|
assert res.ret == 0
|
|
|
|
def test_python_minus_m_invocation_fail(self, testdir):
|
|
p1 = testdir.makepyfile("def test_fail(): 0/0")
|
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
|
assert res.ret == 1
|
|
|
|
def test_python_pytest_package(self, testdir):
|
|
p1 = testdir.makepyfile("def test_pass(): pass")
|
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
|
assert res.ret == 0
|
|
res.stdout.fnmatch_lines(["*1 passed*"])
|
|
|
|
def test_equivalence_pytest_pytest(self):
|
|
assert pytest.main == py.test.cmdline.main
|
|
|
|
def test_invoke_with_string(self, capsys):
|
|
retcode = pytest.main("-h")
|
|
assert not retcode
|
|
out, err = capsys.readouterr()
|
|
assert "--help" in out
|
|
pytest.raises(ValueError, lambda: pytest.main(0))
|
|
|
|
def test_invoke_with_path(self, tmpdir, capsys):
|
|
retcode = pytest.main(tmpdir)
|
|
assert retcode == EXIT_NOTESTSCOLLECTED
|
|
out, err = capsys.readouterr()
|
|
|
|
def test_invoke_plugin_api(self, testdir, capsys):
|
|
class MyPlugin:
|
|
def pytest_addoption(self, parser):
|
|
parser.addoption("--myopt")
|
|
|
|
pytest.main(["-h"], plugins=[MyPlugin()])
|
|
out, err = capsys.readouterr()
|
|
assert "--myopt" in out
|
|
|
|
def test_pyargs_importerror(self, testdir, monkeypatch):
|
|
monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
|
|
path = testdir.mkpydir("tpkg")
|
|
path.join("test_hello.py").write('raise ImportError')
|
|
|
|
result = testdir.runpytest_subprocess("--pyargs", "tpkg.test_hello")
|
|
assert result.ret != 0
|
|
|
|
result.stdout.fnmatch_lines([
|
|
"collected*0*items*/*1*errors"
|
|
])
|
|
|
|
def test_cmdline_python_package(self, testdir, monkeypatch):
|
|
monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
|
|
path = testdir.mkpydir("tpkg")
|
|
path.join("test_hello.py").write("def test_hello(): pass")
|
|
path.join("test_world.py").write("def test_world(): pass")
|
|
result = testdir.runpytest("--pyargs", "tpkg")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*2 passed*"
|
|
])
|
|
result = testdir.runpytest("--pyargs", "tpkg.test_hello")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*1 passed*"
|
|
])
|
|
|
|
def join_pythonpath(what):
|
|
cur = py.std.os.environ.get('PYTHONPATH')
|
|
if cur:
|
|
return str(what) + os.pathsep + cur
|
|
return what
|
|
empty_package = testdir.mkpydir("empty_package")
|
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
|
|
result = testdir.runpytest("--pyargs", ".")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*2 passed*"
|
|
])
|
|
|
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
|
|
result = testdir.runpytest("--pyargs", "tpkg.test_missing")
|
|
assert result.ret != 0
|
|
result.stderr.fnmatch_lines([
|
|
"*not*found*test_missing*",
|
|
])
|
|
|
|
def test_cmdline_python_namespace_package(self, testdir, monkeypatch):
|
|
"""
|
|
test --pyargs option with namespace packages (#1567)
|
|
"""
|
|
monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', raising=False)
|
|
|
|
search_path = []
|
|
for dirname in "hello", "world":
|
|
d = testdir.mkdir(dirname)
|
|
search_path.append(d)
|
|
ns = d.mkdir("ns_pkg")
|
|
ns.join("__init__.py").write(
|
|
"__import__('pkg_resources').declare_namespace(__name__)")
|
|
lib = ns.mkdir(dirname)
|
|
lib.ensure("__init__.py")
|
|
lib.join("test_{0}.py".format(dirname)). \
|
|
write("def test_{0}(): pass\n"
|
|
"def test_other():pass".format(dirname))
|
|
|
|
# The structure of the test directory is now:
|
|
# .
|
|
# ├── hello
|
|
# │ └── ns_pkg
|
|
# │ ├── __init__.py
|
|
# │ └── hello
|
|
# │ ├── __init__.py
|
|
# │ └── test_hello.py
|
|
# └── world
|
|
# └── ns_pkg
|
|
# ├── __init__.py
|
|
# └── world
|
|
# ├── __init__.py
|
|
# └── test_world.py
|
|
|
|
def join_pythonpath(*dirs):
|
|
cur = py.std.os.environ.get('PYTHONPATH')
|
|
if cur:
|
|
dirs += (cur,)
|
|
return os.pathsep.join(str(p) for p in dirs)
|
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(*search_path))
|
|
for p in search_path:
|
|
monkeypatch.syspath_prepend(p)
|
|
|
|
# mixed module and filenames:
|
|
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "world/ns_pkg")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*test_hello.py::test_hello*PASSED",
|
|
"*test_hello.py::test_other*PASSED",
|
|
"*test_world.py::test_world*PASSED",
|
|
"*test_world.py::test_other*PASSED",
|
|
"*4 passed*"
|
|
])
|
|
|
|
# specify tests within a module
|
|
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.world.test_world::test_other")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*test_world.py::test_other*PASSED",
|
|
"*1 passed*"
|
|
])
|
|
|
|
def test_cmdline_python_package_not_exists(self, testdir):
|
|
result = testdir.runpytest("--pyargs", "tpkgwhatv")
|
|
assert result.ret
|
|
result.stderr.fnmatch_lines([
|
|
"ERROR*file*or*package*not*found*",
|
|
])
|
|
|
|
@pytest.mark.xfail(reason="decide: feature or bug")
|
|
def test_noclass_discovery_if_not_testcase(self, testdir):
|
|
testpath = testdir.makepyfile("""
|
|
import unittest
|
|
class TestHello(object):
|
|
def test_hello(self):
|
|
assert self.attr
|
|
|
|
class RealTest(unittest.TestCase, TestHello):
|
|
attr = 42
|
|
""")
|
|
reprec = testdir.inline_run(testpath)
|
|
reprec.assertoutcome(passed=1)
|
|
|
|
def test_doctest_id(self, testdir):
|
|
testdir.makefile('.txt', """
|
|
>>> x=3
|
|
>>> x
|
|
4
|
|
""")
|
|
result = testdir.runpytest("-rf")
|
|
lines = result.stdout.str().splitlines()
|
|
for line in lines:
|
|
if line.startswith("FAIL "):
|
|
testid = line[5:].strip()
|
|
break
|
|
result = testdir.runpytest(testid, '-rf')
|
|
result.stdout.fnmatch_lines([
|
|
line,
|
|
"*1 failed*",
|
|
])
|
|
|
|
def test_core_backward_compatibility(self):
|
|
"""Test backward compatibility for get_plugin_manager function. See #787."""
|
|
import _pytest.config
|
|
assert type(_pytest.config.get_plugin_manager()) is _pytest.config.PytestPluginManager
|
|
|
|
|
|
def test_has_plugin(self, request):
|
|
"""Test hasplugin function of the plugin manager (#932)."""
|
|
assert request.config.pluginmanager.hasplugin('python')
|
|
|
|
|
|
class TestDurations:
|
|
source = """
|
|
import time
|
|
frag = 0.002
|
|
def test_something():
|
|
pass
|
|
def test_2():
|
|
time.sleep(frag*5)
|
|
def test_1():
|
|
time.sleep(frag)
|
|
def test_3():
|
|
time.sleep(frag*10)
|
|
"""
|
|
|
|
def test_calls(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("--durations=10")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines_random([
|
|
"*durations*",
|
|
"*call*test_3*",
|
|
"*call*test_2*",
|
|
"*call*test_1*",
|
|
])
|
|
|
|
def test_calls_show_2(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("--durations=2")
|
|
assert result.ret == 0
|
|
lines = result.stdout.get_lines_after("*slowest*durations*")
|
|
assert "4 passed" in lines[2]
|
|
|
|
def test_calls_showall(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("--durations=0")
|
|
assert result.ret == 0
|
|
for x in "123":
|
|
for y in 'call',: #'setup', 'call', 'teardown':
|
|
for line in result.stdout.lines:
|
|
if ("test_%s" % x) in line and y in line:
|
|
break
|
|
else:
|
|
raise AssertionError("not found %s %s" % (x,y))
|
|
|
|
def test_with_deselected(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("--durations=2", "-k test_1")
|
|
assert result.ret == 0
|
|
result.stdout.fnmatch_lines([
|
|
"*durations*",
|
|
"*call*test_1*",
|
|
])
|
|
|
|
def test_with_failing_collection(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
testdir.makepyfile(test_collecterror="""xyz""")
|
|
result = testdir.runpytest("--durations=2", "-k test_1")
|
|
assert result.ret == 2
|
|
result.stdout.fnmatch_lines([
|
|
"*Interrupted: 1 errors during collection*",
|
|
])
|
|
# Collection errors abort test execution, therefore no duration is
|
|
# output
|
|
assert "duration" not in result.stdout.str()
|
|
|
|
def test_with_not(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("-k not 1")
|
|
assert result.ret == 0
|
|
|
|
|
|
class TestDurationWithFixture:
|
|
source = """
|
|
import time
|
|
frag = 0.001
|
|
def setup_function(func):
|
|
time.sleep(frag * 3)
|
|
def test_1():
|
|
time.sleep(frag*2)
|
|
def test_2():
|
|
time.sleep(frag)
|
|
"""
|
|
def test_setup_function(self, testdir):
|
|
testdir.makepyfile(self.source)
|
|
result = testdir.runpytest("--durations=10")
|
|
assert result.ret == 0
|
|
|
|
result.stdout.fnmatch_lines_random("""
|
|
*durations*
|
|
* setup *test_1*
|
|
* call *test_1*
|
|
""")
|
|
|
|
|
|
def test_yield_tests_deprecation(testdir):
|
|
testdir.makepyfile("""
|
|
def func1(arg, arg2):
|
|
assert arg == arg2
|
|
def test_gen():
|
|
yield "m1", func1, 15, 3*5
|
|
yield "m2", func1, 42, 6*7
|
|
""")
|
|
result = testdir.runpytest('-ra')
|
|
result.stdout.fnmatch_lines([
|
|
'*yield tests are deprecated, and scheduled to be removed in pytest 4.0*',
|
|
'*2 passed*',
|
|
])
|
|
|
|
|
|
def test_funcarg_prefix_deprecation(testdir):
|
|
testdir.makepyfile("""
|
|
def pytest_funcarg__value():
|
|
return 10
|
|
|
|
def test_funcarg_prefix(value):
|
|
assert value == 10
|
|
""")
|
|
result = testdir.runpytest('-ra')
|
|
result.stdout.fnmatch_lines([
|
|
('WC1 None pytest_funcarg__value: '
|
|
'declaring fixtures using "pytest_funcarg__" prefix is deprecated '
|
|
'and scheduled to be removed in pytest 4.0. '
|
|
'Please remove the prefix and use the @pytest.fixture decorator instead.'),
|
|
'*1 passed*',
|
|
])
|
|
|
|
|
|
def test_str_args_deprecated(tmpdir, testdir):
|
|
"""Deprecate passing strings to pytest.main(). Scheduled for removal in pytest-4.0."""
|
|
warnings = []
|
|
|
|
class Collect:
|
|
def pytest_logwarning(self, message):
|
|
warnings.append(message)
|
|
|
|
ret = pytest.main("%s -x" % tmpdir, plugins=[Collect()])
|
|
testdir.delete_loaded_modules()
|
|
msg = ('passing a string to pytest.main() is deprecated, '
|
|
'pass a list of arguments instead.')
|
|
assert msg in warnings
|
|
assert ret == EXIT_NOTESTSCOLLECTED
|