import pytest, py, sys from _pytest import python as funcargs from _pytest.python import FuncargLookupError class TestModule: def test_failing_import(self, testdir): modcol = testdir.getmodulecol("import alksdjalskdjalkjals") pytest.raises(ImportError, modcol.collect) pytest.raises(ImportError, modcol.collect) def test_import_duplicate(self, testdir): a = testdir.mkdir("a") b = testdir.mkdir("b") p = a.ensure("test_whatever.py") p.pyimport() del py.std.sys.modules['test_whatever'] b.ensure("test_whatever.py") result = testdir.runpytest() result.stdout.fnmatch_lines([ "*import*mismatch*", "*imported*test_whatever*", "*%s*" % a.join("test_whatever.py"), "*not the same*", "*%s*" % b.join("test_whatever.py"), "*HINT*", ]) def test_syntax_error_in_module(self, testdir): modcol = testdir.getmodulecol("this is a syntax error") pytest.raises(modcol.CollectError, modcol.collect) pytest.raises(modcol.CollectError, modcol.collect) def test_module_considers_pluginmanager_at_import(self, testdir): modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") pytest.raises(ImportError, "modcol.obj") class TestClass: def test_class_with_init_not_collected(self, testdir): modcol = testdir.getmodulecol(""" class TestClass1: def __init__(self): pass class TestClass2(object): def __init__(self): pass """) l = modcol.collect() assert len(l) == 0 def test_class_subclassobject(self, testdir): testdir.getmodulecol(""" class test(object): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*collected 0*", ]) def test_setup_teardown_class_as_classmethod(self, testdir): testdir.makepyfile(test_mod1=""" class TestClassMethod: @classmethod def setup_class(cls): pass def test_1(self): pass @classmethod def teardown_class(cls): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*1 passed*", ]) class TestGenerator: def test_generative_functions(self, testdir): modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 def test_gen(): yield func1, 17, 3*5 yield func1, 42, 6*7 """) colitems = modcol.collect() assert len(colitems) == 1 gencol = colitems[0] assert isinstance(gencol, pytest.Generator) gencolitems = gencol.collect() assert len(gencolitems) == 2 assert isinstance(gencolitems[0], pytest.Function) assert isinstance(gencolitems[1], pytest.Function) assert gencolitems[0].name == '[0]' assert gencolitems[0].obj.__name__ == 'func1' def test_generative_methods(self, testdir): modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 class TestGenMethods: def test_gen(self): yield func1, 17, 3*5 yield func1, 42, 6*7 """) gencol = modcol.collect()[0].collect()[0].collect()[0] assert isinstance(gencol, pytest.Generator) gencolitems = gencol.collect() assert len(gencolitems) == 2 assert isinstance(gencolitems[0], pytest.Function) assert isinstance(gencolitems[1], pytest.Function) assert gencolitems[0].name == '[0]' assert gencolitems[0].obj.__name__ == 'func1' def test_generative_functions_with_explicit_names(self, testdir): modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 def test_gen(): yield "seventeen", func1, 17, 3*5 yield "fortytwo", func1, 42, 6*7 """) colitems = modcol.collect() assert len(colitems) == 1 gencol = colitems[0] assert isinstance(gencol, pytest.Generator) gencolitems = gencol.collect() assert len(gencolitems) == 2 assert isinstance(gencolitems[0], pytest.Function) assert isinstance(gencolitems[1], pytest.Function) assert gencolitems[0].name == "['seventeen']" assert gencolitems[0].obj.__name__ == 'func1' assert gencolitems[1].name == "['fortytwo']" assert gencolitems[1].obj.__name__ == 'func1' def test_generative_functions_unique_explicit_names(self, testdir): # generative modcol = testdir.getmodulecol(""" def func(): pass def test_gen(): yield "name", func yield "name", func """) colitems = modcol.collect() assert len(colitems) == 1 gencol = colitems[0] assert isinstance(gencol, pytest.Generator) pytest.raises(ValueError, "gencol.collect()") def test_generative_methods_with_explicit_names(self, testdir): modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 class TestGenMethods: def test_gen(self): yield "m1", func1, 17, 3*5 yield "m2", func1, 42, 6*7 """) gencol = modcol.collect()[0].collect()[0].collect()[0] assert isinstance(gencol, pytest.Generator) gencolitems = gencol.collect() assert len(gencolitems) == 2 assert isinstance(gencolitems[0], pytest.Function) assert isinstance(gencolitems[1], pytest.Function) assert gencolitems[0].name == "['m1']" assert gencolitems[0].obj.__name__ == 'func1' assert gencolitems[1].name == "['m2']" assert gencolitems[1].obj.__name__ == 'func1' def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir): o = testdir.makepyfile(""" def test_generative_order_of_execution(): import py, pytest test_list = [] expected_list = list(range(6)) def list_append(item): test_list.append(item) def assert_order_of_execution(): py.builtin.print_('expected order', expected_list) py.builtin.print_('but got ', test_list) assert test_list == expected_list for i in expected_list: yield list_append, i yield assert_order_of_execution """) reprec = testdir.inline_run(o) passed, skipped, failed = reprec.countoutcomes() assert passed == 7 assert not skipped and not failed def test_order_of_execution_generator_different_codeline(self, testdir): o = testdir.makepyfile(""" def test_generative_tests_different_codeline(): import py, pytest test_list = [] expected_list = list(range(3)) def list_append_2(): test_list.append(2) def list_append_1(): test_list.append(1) def list_append_0(): test_list.append(0) def assert_order_of_execution(): py.builtin.print_('expected order', expected_list) py.builtin.print_('but got ', test_list) assert test_list == expected_list yield list_append_0 yield list_append_1 yield list_append_2 yield assert_order_of_execution """) reprec = testdir.inline_run(o) passed, skipped, failed = reprec.countoutcomes() assert passed == 4 assert not skipped and not failed def test_setupstate_is_preserved_134(self, testdir): # yield-based tests are messy wrt to setupstate because # during collection they already invoke setup functions # and then again when they are run. For now, we want to make sure # that the old 1.3.4 behaviour is preserved such that all # yielded functions all share the same "self" instance that # has been used during collection. o = testdir.makepyfile(""" setuplist = [] class TestClass: def setup_method(self, func): #print "setup_method", self, func setuplist.append(self) self.init = 42 def teardown_method(self, func): self.init = None def test_func1(self): pass def test_func2(self): yield self.func2 yield self.func2 def func2(self): assert self.init def test_setuplist(): # once for test_func2 during collection # once for test_func1 during test run # once for test_func2 during test run #print setuplist assert len(setuplist) == 3, len(setuplist) assert setuplist[0] == setuplist[2], setuplist assert setuplist[1] != setuplist[2], setuplist """) reprec = testdir.inline_run(o, '-v') passed, skipped, failed = reprec.countoutcomes() assert passed == 4 assert not skipped and not failed class TestFunction: def test_getmodulecollector(self, testdir): item = testdir.getitem("def test_func(): pass") modcol = item.getparent(pytest.Module) assert isinstance(modcol, pytest.Module) assert hasattr(modcol.obj, 'test_func') def test_function_equality(self, testdir, tmpdir): config = testdir.parseconfigure() session = testdir.Session(config) def func1(): pass def func2(): pass f1 = pytest.Function(name="name", config=config, args=(1,), callobj=func1, session=session) f2 = pytest.Function(name="name",config=config, args=(1,), callobj=func2, session=session) assert not f1 == f2 assert f1 != f2 f3 = pytest.Function(name="name", config=config, args=(1,2), callobj=func2, session=session) assert not f3 == f2 assert f3 != f2 assert not f3 == f1 assert f3 != f1 f1_b = pytest.Function(name="name", config=config, args=(1,), callobj=func1, session=session) assert f1 == f1_b assert not f1 != f1_b def test_function_equality_with_callspec(self, testdir, tmpdir): items = testdir.getitems(""" import pytest @pytest.mark.parametrize('arg', [1,2]) def test_function(arg): pass """) assert items[0] != items[1] assert not (items[0] == items[1]) def test_pyfunc_call(self, testdir): item = testdir.getitem("def test_func(): raise ValueError") config = item.config class MyPlugin1: def pytest_pyfunc_call(self, pyfuncitem): raise ValueError class MyPlugin2: def pytest_pyfunc_call(self, pyfuncitem): return True config.pluginmanager.register(MyPlugin1()) config.pluginmanager.register(MyPlugin2()) config.hook.pytest_pyfunc_call(pyfuncitem=item) class TestSorting: def test_check_equality(self, testdir): modcol = testdir.getmodulecol(""" def test_pass(): pass def test_fail(): assert 0 """) fn1 = testdir.collect_by_name(modcol, "test_pass") assert isinstance(fn1, pytest.Function) fn2 = testdir.collect_by_name(modcol, "test_pass") assert isinstance(fn2, pytest.Function) assert fn1 == fn2 assert fn1 != modcol if py.std.sys.version_info < (3, 0): assert cmp(fn1, fn2) == 0 assert hash(fn1) == hash(fn2) fn3 = testdir.collect_by_name(modcol, "test_fail") assert isinstance(fn3, pytest.Function) assert not (fn1 == fn3) assert fn1 != fn3 for fn in fn1,fn2,fn3: assert fn != 3 assert fn != modcol assert fn != [1,2,3] assert [1,2,3] != fn assert modcol != fn def test_allow_sane_sorting_for_decorators(self, testdir): modcol = testdir.getmodulecol(""" def dec(f): g = lambda: f(2) g.place_as = f return g def test_b(y): pass test_b = dec(test_b) def test_a(y): pass test_a = dec(test_a) """) colitems = modcol.collect() assert len(colitems) == 2 assert [item.name for item in colitems] == ['test_b', 'test_a'] class TestConftestCustomization: def test_pytest_pycollect_module(self, testdir): testdir.makeconftest(""" import pytest class MyModule(pytest.Module): pass def pytest_pycollect_makemodule(path, parent): if path.basename == "test_xyz.py": return MyModule(path, parent) """) testdir.makepyfile("def test_some(): pass") testdir.makepyfile(test_xyz="def test_func(): pass") result = testdir.runpytest("--collectonly") result.stdout.fnmatch_lines([ "* 3 def test_traceback_error_during_import(self, testdir): testdir.makepyfile(""" x = 1 x = 2 x = 17 asd """) result = testdir.runpytest() assert result.ret != 0 out = result.stdout.str() assert "x = 1" not in out assert "x = 2" not in out result.stdout.fnmatch_lines([ ">*asd*", "E*NameError*", ]) result = testdir.runpytest("--fulltrace") out = result.stdout.str() assert "x = 1" in out assert "x = 2" in out result.stdout.fnmatch_lines([ ">*asd*", "E*NameError*", ]) def test_getfuncargnames(): def f(): pass assert not funcargs.getfuncargnames(f) def g(arg): pass assert funcargs.getfuncargnames(g) == ['arg'] def h(arg1, arg2="hello"): pass assert funcargs.getfuncargnames(h) == ['arg1'] def h(arg1, arg2, arg3="hello"): pass assert funcargs.getfuncargnames(h) == ['arg1', 'arg2'] class A: def f(self, arg1, arg2="hello"): pass assert funcargs.getfuncargnames(A().f) == ['arg1'] if sys.version_info < (3,0): assert funcargs.getfuncargnames(A.f) == ['arg1'] class TestFillFuncArgs: def test_fillfuncargs_exposed(self): # used by oejskit assert pytest._fillfuncargs == funcargs.fillfuncargs def test_funcarg_lookupfails(self, testdir): testdir.makepyfile(""" def pytest_funcarg__xyzsomething(request): return 42 def test_func(some): pass """) result = testdir.runpytest() # "--collectonly") assert result.ret != 0 result.stdout.fnmatch_lines([ "*def test_func(some)*", "*LookupError*", "*xyzsomething*", ]) def test_funcarg_basic(self, testdir): item = testdir.getitem(""" def pytest_funcarg__some(request): return request.function.__name__ def pytest_funcarg__other(request): return 42 def test_func(some, other): pass """) funcargs.fillfuncargs(item) assert len(item.funcargs) == 2 assert item.funcargs['some'] == "test_func" assert item.funcargs['other'] == 42 def test_funcarg_lookup_modulelevel(self, testdir): modcol = testdir.getmodulecol(""" def pytest_funcarg__something(request): return request.function.__name__ class TestClass: def test_method(self, something): pass def test_func(something): pass """) item1, item2 = testdir.genitems([modcol]) funcargs.fillfuncargs(item1) assert item1.funcargs['something'] == "test_method" funcargs.fillfuncargs(item2) assert item2.funcargs['something'] == "test_func" def test_funcarg_lookup_classlevel(self, testdir): p = testdir.makepyfile(""" class TestClass: def pytest_funcarg__something(self, request): return request.instance def test_method(self, something): assert something is self """) result = testdir.runpytest(p) result.stdout.fnmatch_lines([ "*1 passed*" ]) class TestRequest: def test_request_attributes(self, testdir): item = testdir.getitem(""" def pytest_funcarg__something(request): pass def test_func(something): pass """) req = funcargs.FuncargRequest(item) assert req.function == item.obj assert req.keywords is item.keywords assert hasattr(req.module, 'test_func') assert req.cls is None assert req.function.__name__ == "test_func" assert req.config == item.config assert repr(req).find(req.function.__name__) != -1 def test_request_attributes_method(self, testdir): item, = testdir.getitems(""" class TestB: def pytest_funcarg__something(self, request): return 1 def test_func(self, something): pass """) req = item._request assert req.cls.__name__ == "TestB" assert req.instance.__class__ == req.cls def XXXtest_request_contains_funcarg_name2factory(self, testdir): modcol = testdir.getmodulecol(""" def pytest_funcarg__something(request): pass class TestClass: def test_method(self, something): pass """) item1, = testdir.genitems([modcol]) assert item1.name == "test_method" name2factory = funcargs.FuncargRequest(item1)._name2factory assert len(name2factory) == 1 assert name2factory[0].__name__ == "pytest_funcarg__something" def test_getfuncargvalue_recursive(self, testdir): testdir.makeconftest(""" def pytest_funcarg__something(request): return 1 """) item = testdir.makepyfile(""" def pytest_funcarg__something(request): return request.getfuncargvalue("something") + 1 def test_func(something): assert something == 2 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_getfuncargvalue(self, testdir): item = testdir.getitem(""" l = [2] def pytest_funcarg__something(request): return 1 def pytest_funcarg__other(request): return l.pop() def test_func(something): pass """) req = item._request pytest.raises(FuncargLookupError, req.getfuncargvalue, "notexists") val = req.getfuncargvalue("something") assert val == 1 val = req.getfuncargvalue("something") assert val == 1 val2 = req.getfuncargvalue("other") assert val2 == 2 val2 = req.getfuncargvalue("other") # see about caching assert val2 == 2 pytest._fillfuncargs(item) assert item.funcargs == {'something': 1} #assert item.funcargs == {'something': 1, "other": 2} def test_request_addfinalizer(self, testdir): item = testdir.getitem(""" teardownlist = [] def pytest_funcarg__something(request): request.addfinalizer(lambda: teardownlist.append(1)) def test_func(something): pass """) item.session._setupstate.prepare(item) pytest._fillfuncargs(item) # successively check finalization calls teardownlist = item.getparent(pytest.Module).obj.teardownlist ss = item.session._setupstate assert not teardownlist ss.teardown_exact(item, None) print(ss.stack) assert teardownlist == [1] def test_request_addfinalizer_partial_setup_failure(self, testdir): p = testdir.makepyfile(""" l = [] def pytest_funcarg__something(request): request.addfinalizer(lambda: l.append(None)) def test_func(something, missingarg): pass def test_second(): assert len(l) == 1 """) result = testdir.runpytest(p) result.stdout.fnmatch_lines([ "*1 error*" # XXX the whole module collection fails ]) def test_request_getmodulepath(self, testdir): modcol = testdir.getmodulecol("def test_somefunc(): pass") item, = testdir.genitems([modcol]) req = funcargs.FuncargRequest(item) assert req.fspath == modcol.fspath def test_applymarker(testdir): item1,item2 = testdir.getitems(""" def pytest_funcarg__something(request): pass class TestClass: def test_func1(self, something): pass def test_func2(self, something): pass """) req1 = funcargs.FuncargRequest(item1) assert 'xfail' not in item1.keywords req1.applymarker(pytest.mark.xfail) assert 'xfail' in item1.keywords assert 'skipif' not in item1.keywords req1.applymarker(pytest.mark.skipif) assert 'skipif' in item1.keywords pytest.raises(ValueError, "req1.applymarker(42)") class TestRequestCachedSetup: def test_request_cachedsetup_defaultmodule(self, testdir): reprec = testdir.inline_runsource(""" mysetup = ["hello",].pop def pytest_funcarg__something(request): return request.cached_setup(mysetup, scope="module") def test_func1(something): assert something == "hello" class TestClass: def test_func1a(self, something): assert something == "hello" """) reprec.assertoutcome(passed=2) def test_request_cachedsetup_class(self, testdir): reprec = testdir.inline_runsource(""" mysetup = ["hello", "hello2"].pop def pytest_funcarg__something(request): return request.cached_setup(mysetup, scope="class") def test_func1(something): assert something == "hello2" def test_func2(something): assert something == "hello2" class TestClass: def test_func1a(self, something): assert something == "hello" def test_func2b(self, something): assert something == "hello" """) reprec.assertoutcome(passed=4) def test_request_cachedsetup_extrakey(self, testdir): item1 = testdir.getitem("def test_func(): pass") req1 = funcargs.FuncargRequest(item1) l = ["hello", "world"] def setup(): return l.pop() ret1 = req1.cached_setup(setup, extrakey=1) ret2 = req1.cached_setup(setup, extrakey=2) assert ret2 == "hello" assert ret1 == "world" ret1b = req1.cached_setup(setup, extrakey=1) ret2b = req1.cached_setup(setup, extrakey=2) assert ret1 == ret1b assert ret2 == ret2b def test_request_cachedsetup_cache_deletion(self, testdir): item1 = testdir.getitem("def test_func(): pass") req1 = funcargs.FuncargRequest(item1) l = [] def setup(): l.append("setup") def teardown(val): l.append("teardown") ret1 = req1.cached_setup(setup, teardown, scope="function") assert l == ['setup'] # artificial call of finalizer setupstate = req1._pyfuncitem.session._setupstate setupstate._callfinalizers(item1) assert l == ["setup", "teardown"] ret2 = req1.cached_setup(setup, teardown, scope="function") assert l == ["setup", "teardown", "setup"] setupstate._callfinalizers(item1) assert l == ["setup", "teardown", "setup", "teardown"] def test_request_cached_setup_two_args(self, testdir): testdir.makepyfile(""" def pytest_funcarg__arg1(request): return request.cached_setup(lambda: 42) def pytest_funcarg__arg2(request): return request.cached_setup(lambda: 17) def test_two_different_setups(arg1, arg2): assert arg1 != arg2 """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ "*1 passed*" ]) def test_request_cached_setup_getfuncargvalue(self, testdir): testdir.makepyfile(""" def pytest_funcarg__arg1(request): arg1 = request.getfuncargvalue("arg2") return request.cached_setup(lambda: arg1 + 1) def pytest_funcarg__arg2(request): return request.cached_setup(lambda: 10) def test_two_funcarg(arg1): assert arg1 == 11 """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ "*1 passed*" ]) def test_request_cached_setup_functional(self, testdir): testdir.makepyfile(test_0=""" l = [] def pytest_funcarg__something(request): val = request.cached_setup(fsetup, fteardown) return val def fsetup(mycache=[1]): l.append(mycache.pop()) return l def fteardown(something): l.remove(something[0]) l.append(2) def test_list_once(something): assert something == [1] def test_list_twice(something): assert something == [1] """) testdir.makepyfile(test_1=""" import test_0 # should have run already def test_check_test0_has_teardown_correct(): assert test_0.l == [2] """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ "*3 passed*" ]) class TestMetafunc: def test_no_funcargs(self, testdir): def function(): pass metafunc = funcargs.Metafunc(function) assert not metafunc.funcargnames repr(metafunc._calls) def test_function_basic(self): def func(arg1, arg2="qwe"): pass metafunc = funcargs.Metafunc(func) assert len(metafunc.funcargnames) == 1 assert 'arg1' in metafunc.funcargnames assert metafunc.function is func assert metafunc.cls is None def test_addcall_no_args(self): def func(arg1): pass metafunc = funcargs.Metafunc(func) metafunc.addcall() assert len(metafunc._calls) == 1 call = metafunc._calls[0] assert call.id == "0" assert not hasattr(call, 'param') def test_addcall_id(self): def func(arg1): pass metafunc = funcargs.Metafunc(func) pytest.raises(ValueError, "metafunc.addcall(id=None)") metafunc.addcall(id=1) pytest.raises(ValueError, "metafunc.addcall(id=1)") pytest.raises(ValueError, "metafunc.addcall(id='1')") metafunc.addcall(id=2) assert len(metafunc._calls) == 2 assert metafunc._calls[0].id == "1" assert metafunc._calls[1].id == "2" def test_addcall_param(self): def func(arg1): pass metafunc = funcargs.Metafunc(func) class obj: pass metafunc.addcall(param=obj) metafunc.addcall(param=obj) metafunc.addcall(param=1) assert len(metafunc._calls) == 3 assert metafunc._calls[0].getparam("arg1") == obj assert metafunc._calls[1].getparam("arg1") == obj assert metafunc._calls[2].getparam("arg1") == 1 def test_addcall_funcargs(self): def func(x): pass metafunc = funcargs.Metafunc(func) class obj: pass metafunc.addcall(funcargs={"x": 2}) metafunc.addcall(funcargs={"x": 3}) pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})") assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == {'x': 2} assert metafunc._calls[1].funcargs == {'x': 3} assert not hasattr(metafunc._calls[1], 'param') def test_parametrize_error(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) metafunc.parametrize("x", [1,2]) pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6])) metafunc.parametrize("y", [1,2]) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) def test_parametrize_and_id(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) metafunc.parametrize("x", [1,2], ids=['basic', 'advanced']) metafunc.parametrize("y", ["abc", "def"]) ids = [x.id for x in metafunc._calls] assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"] def test_parametrize_with_userobjects(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) class A: pass metafunc.parametrize("x", [A(), A()]) metafunc.parametrize("y", list("ab")) assert metafunc._calls[0].id == ".0-a" assert metafunc._calls[1].id == ".0-b" assert metafunc._calls[2].id == ".1-a" assert metafunc._calls[3].id == ".1-b" def test_addcall_and_parametrize(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) metafunc.addcall({'x': 1}) metafunc.parametrize('y', [2,3]) assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == {'x': 1, 'y': 2} assert metafunc._calls[1].funcargs == {'x': 1, 'y': 3} assert metafunc._calls[0].id == "0-2" assert metafunc._calls[1].id == "0-3" def test_parametrize_indirect(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) metafunc.parametrize('x', [1], indirect=True) metafunc.parametrize('y', [2,3], indirect=True) metafunc.parametrize('unnamed', [1], indirect=True) assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == {} assert metafunc._calls[1].funcargs == {} assert metafunc._calls[0].params == dict(x=1,y=2, unnamed=1) assert metafunc._calls[1].params == dict(x=1,y=3, unnamed=1) def test_addcalls_and_parametrize_indirect(self): def func(x, y): pass metafunc = funcargs.Metafunc(func) metafunc.addcall(param="123") metafunc.parametrize('x', [1], indirect=True) metafunc.parametrize('y', [2,3], indirect=True) assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == {} assert metafunc._calls[1].funcargs == {} assert metafunc._calls[0].params == dict(x=1,y=2) assert metafunc._calls[1].params == dict(x=1,y=3) def test_parametrize_functional(self, testdir): testdir.makepyfile(""" def pytest_generate_tests(metafunc): assert "test_parametrize_functional" in metafunc.parentid metafunc.parametrize('x', [1,2], indirect=True) metafunc.parametrize('y', [2]) def pytest_funcarg__x(request): return request.param * 10 def pytest_funcarg__y(request): return request.param def test_simple(x,y): assert x in (10,20) assert y == 2 """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ "*test_simple*1-2*", "*test_simple*2-2*", "*2 passed*", ]) def test_parametrize_onearg(self): metafunc = funcargs.Metafunc(lambda x: None) metafunc.parametrize("x", [1,2]) assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == dict(x=1) assert metafunc._calls[0].id == "1" assert metafunc._calls[1].funcargs == dict(x=2) assert metafunc._calls[1].id == "2" def test_parametrize_onearg_indirect(self): metafunc = funcargs.Metafunc(lambda x: None) metafunc.parametrize("x", [1,2], indirect=True) assert metafunc._calls[0].params == dict(x=1) assert metafunc._calls[0].id == "1" assert metafunc._calls[1].params == dict(x=2) assert metafunc._calls[1].id == "2" def test_parametrize_twoargs(self): metafunc = funcargs.Metafunc(lambda x,y: None) metafunc.parametrize(("x", "y"), [(1,2), (3,4)]) assert len(metafunc._calls) == 2 assert metafunc._calls[0].funcargs == dict(x=1, y=2) assert metafunc._calls[0].id == "1-2" assert metafunc._calls[1].funcargs == dict(x=3, y=4) assert metafunc._calls[1].id == "3-4" def test_parametrize_multiple_times(self, testdir): testdir.makepyfile(""" import pytest pytestmark = pytest.mark.parametrize("x", [1,2]) def test_func(x): assert 0, x class TestClass: pytestmark = pytest.mark.parametrize("y", [3,4]) def test_meth(self, x, y): assert 0, x """) result = testdir.runpytest() assert result.ret == 1 result.stdout.fnmatch_lines([ "*6 fail*", ]) class TestMetafuncFunctional: def test_attributes(self, testdir): p = testdir.makepyfile(""" # assumes that generate/provide runs in the same process import py, pytest def pytest_generate_tests(metafunc): metafunc.addcall(param=metafunc) def pytest_funcarg__metafunc(request): assert request._pyfuncitem._genid == "0" return request.param def test_function(metafunc, pytestconfig): assert metafunc.config == pytestconfig assert metafunc.module.__name__ == __name__ assert metafunc.function == test_function assert metafunc.cls is None class TestClass: def test_method(self, metafunc, pytestconfig): assert metafunc.config == pytestconfig assert metafunc.module.__name__ == __name__ if py.std.sys.version_info > (3, 0): unbound = TestClass.test_method else: unbound = TestClass.test_method.im_func # XXX actually have an unbound test function here? assert metafunc.function == unbound assert metafunc.cls == TestClass """) result = testdir.runpytest(p, "-v") result.stdout.fnmatch_lines([ "*2 passed in*", ]) def test_addcall_with_two_funcargs_generators(self, testdir): testdir.makeconftest(""" def pytest_generate_tests(metafunc): assert "arg1" in metafunc.funcargnames metafunc.addcall(funcargs=dict(arg1=1, arg2=2)) """) p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.addcall(funcargs=dict(arg1=1, arg2=1)) class TestClass: def test_myfunc(self, arg1, arg2): assert arg1 == arg2 """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_myfunc*0*PASS*", "*test_myfunc*1*FAIL*", "*1 failed, 1 passed*" ]) def test_two_functions(self, testdir): p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.addcall(param=10) metafunc.addcall(param=20) def pytest_funcarg__arg1(request): return request.param def test_func1(arg1): assert arg1 == 10 def test_func2(arg1): assert arg1 in (10, 20) """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_func1*0*PASS*", "*test_func1*1*FAIL*", "*test_func2*PASS*", "*1 failed, 3 passed*" ]) def test_noself_in_method(self, testdir): p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): assert 'xyz' not in metafunc.funcargnames class TestHello: def test_hello(xyz): pass """) result = testdir.runpytest(p) result.stdout.fnmatch_lines([ "*1 pass*", ]) def test_generate_plugin_and_module(self, testdir): testdir.makeconftest(""" def pytest_generate_tests(metafunc): assert "arg1" in metafunc.funcargnames metafunc.addcall(id="world", param=(2,100)) """) p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.addcall(param=(1,1), id="hello") def pytest_funcarg__arg1(request): return request.param[0] def pytest_funcarg__arg2(request): return request.param[1] class TestClass: def test_myfunc(self, arg1, arg2): assert arg1 == arg2 """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_myfunc*hello*PASS*", "*test_myfunc*world*FAIL*", "*1 failed, 1 passed*" ]) def test_generate_tests_in_class(self, testdir): p = testdir.makepyfile(""" class TestClass: def pytest_generate_tests(self, metafunc): metafunc.addcall(funcargs={'hello': 'world'}, id="hello") def test_myfunc(self, hello): assert hello == "world" """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_myfunc*hello*PASS*", "*1 passed*" ]) def test_two_functions_not_same_instance(self, testdir): p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.addcall({'arg1': 10}) metafunc.addcall({'arg1': 20}) class TestClass: def test_func(self, arg1): assert not hasattr(self, 'x') self.x = 1 """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*", ]) def test_issue28_setup_method_in_generate_tests(self, testdir): p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.addcall({'arg1': 1}) class TestClass: def test_method(self, arg1): assert arg1 == self.val def setup_method(self, func): self.val = 1 """) result = testdir.runpytest(p) result.stdout.fnmatch_lines([ "*1 pass*", ]) def test_parametrize_functional2(self, testdir): testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.parametrize("arg1", [1,2]) metafunc.parametrize("arg2", [4,5]) def test_hello(arg1, arg2): assert 0, (arg1, arg2) """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*(1, 4)*", "*(1, 5)*", "*(2, 4)*", "*(2, 5)*", "*4 failed*", ]) def test_parametrize_and_inner_getfuncargvalue(self, testdir): p = testdir.makepyfile(""" def pytest_generate_tests(metafunc): metafunc.parametrize("arg1", [1], indirect=True) metafunc.parametrize("arg2", [10], indirect=True) def pytest_funcarg__arg1(request): x = request.getfuncargvalue("arg2") return x + request.param def pytest_funcarg__arg2(request): return request.param def test_func1(arg1, arg2): assert arg1 == 11 """) result = testdir.runpytest("-v", p) result.stdout.fnmatch_lines([ "*test_func1*1*PASS*", "*1 passed*" ]) def test_conftest_funcargs_only_available_in_subdir(testdir): sub1 = testdir.mkpydir("sub1") sub2 = testdir.mkpydir("sub2") sub1.join("conftest.py").write(py.code.Source(""" import pytest def pytest_funcarg__arg1(request): pytest.raises(Exception, "request.getfuncargvalue('arg2')") """)) sub2.join("conftest.py").write(py.code.Source(""" import pytest def pytest_funcarg__arg2(request): pytest.raises(Exception, "request.getfuncargvalue('arg1')") """)) sub1.join("test_in_sub1.py").write("def test_1(arg1): pass") sub2.join("test_in_sub2.py").write("def test_2(arg2): pass") result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ "*2 passed*" ]) def test_funcarg_non_pycollectobj(testdir): # rough jstests usage testdir.makeconftest(""" import pytest def pytest_pycollect_makeitem(collector, name, obj): if name == "MyClass": return MyCollector(name, parent=collector) class MyCollector(pytest.Collector): def reportinfo(self): return self.fspath, 3, "xyz" """) modcol = testdir.getmodulecol(""" def pytest_funcarg__arg1(request): return 42 class MyClass: pass """) # this hook finds funcarg factories rep = modcol.ihook.pytest_make_collect_report(collector=modcol) clscol = rep.result[0] clscol.obj = lambda arg1: None clscol.funcargs = {} funcargs.fillfuncargs(clscol) assert clscol.funcargs['arg1'] == 42 def test_funcarg_lookup_error(testdir): p = testdir.makepyfile(""" def test_lookup_error(unknown): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*ERROR*test_lookup_error*", "*def test_lookup_error(unknown):*", "*LookupError: no factory found*unknown*", "*available funcargs*", "*1 error*", ]) assert "INTERNAL" not in result.stdout.str() class TestReportInfo: def test_itemreport_reportinfo(self, testdir, linecomp): testdir.makeconftest(""" import pytest class MyFunction(pytest.Function): def reportinfo(self): return "ABCDE", 42, "custom" def pytest_pycollect_makeitem(collector, name, obj): if name == "test_func": return MyFunction(name, parent=collector) """) item = testdir.getitem("def test_func(): pass") runner = item.config.pluginmanager.getplugin("runner") assert item.location == ("ABCDE", 42, "custom") def test_func_reportinfo(self, testdir): item = testdir.getitem("def test_func(): pass") fspath, lineno, modpath = item.reportinfo() assert fspath == item.fspath assert lineno == 0 assert modpath == "test_func" def test_class_reportinfo(self, testdir): modcol = testdir.getmodulecol(""" # lineno 0 class TestClass: def test_hello(self): pass """) classcol = testdir.collect_by_name(modcol, "TestClass") fspath, lineno, msg = classcol.reportinfo() assert fspath == modcol.fspath assert lineno == 1 assert msg == "TestClass" def test_generator_reportinfo(self, testdir): modcol = testdir.getmodulecol(""" # lineno 0 def test_gen(): def check(x): assert x yield check, 3 """) gencol = testdir.collect_by_name(modcol, "test_gen") fspath, lineno, modpath = gencol.reportinfo() assert fspath == modcol.fspath assert lineno == 1 assert modpath == "test_gen" genitem = gencol.collect()[0] fspath, lineno, modpath = genitem.reportinfo() assert fspath == modcol.fspath assert lineno == 2 assert modpath == "test_gen[0]" """ def test_func(): pass def test_genfunc(): def check(x): pass yield check, 3 class TestClass: def test_method(self): pass """ def test_show_funcarg(testdir): result = testdir.runpytest("--funcargs") result.stdout.fnmatch_lines([ "*tmpdir*", "*temporary directory*", ] ) class TestRaises: def test_raises(self): source = "int('qwe')" excinfo = pytest.raises(ValueError, source) code = excinfo.traceback[-1].frame.code s = str(code.fullsource) assert s == source def test_raises_exec(self): pytest.raises(ValueError, "a,x = []") def test_raises_syntax_error(self): pytest.raises(SyntaxError, "qwe qwe qwe") def test_raises_function(self): pytest.raises(ValueError, int, 'hello') def test_raises_callable_no_exception(self): class A: def __call__(self): pass try: pytest.raises(ValueError, A()) except pytest.raises.Exception: pass @pytest.mark.skipif('sys.version < "2.5"') def test_raises_as_contextmanager(self, testdir): testdir.makepyfile(""" from __future__ import with_statement import py, pytest def test_simple(): with pytest.raises(ZeroDivisionError) as excinfo: assert isinstance(excinfo, py.code.ExceptionInfo) 1/0 print (excinfo) assert excinfo.type == ZeroDivisionError def test_noraise(): with pytest.raises(pytest.raises.Exception): with pytest.raises(ValueError): int() def test_raise_wrong_exception_passes_by(): with pytest.raises(ZeroDivisionError): with pytest.raises(ValueError): 1/0 """) result = testdir.runpytest() result.stdout.fnmatch_lines([ '*3 passed*', ]) def test_customized_python_discovery(testdir): testdir.makeini(""" [pytest] python_files=check_*.py python_classes=Check python_functions=check """) p = testdir.makepyfile(""" def check_simple(): pass class CheckMyApp: def check_meth(self): pass """) p2 = p.new(basename=p.basename.replace("test", "check")) p.move(p2) result = testdir.runpytest("--collectonly", "-s") result.stdout.fnmatch_lines([ "*check_customized*", "*check_simple*", "*CheckMyApp*", "*check_meth*", ]) result = testdir.runpytest() assert result.ret == 0 result.stdout.fnmatch_lines([ "*2 passed*", ]) def test_collector_attributes(testdir): testdir.makeconftest(""" import pytest def pytest_pycollect_makeitem(collector): assert collector.Function == pytest.Function assert collector.Class == pytest.Class assert collector.Instance == pytest.Instance assert collector.Module == pytest.Module """) testdir.makepyfile(""" def test_hello(): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*1 passed*", ]) def test_customize_through_attributes(testdir): testdir.makeconftest(""" import pytest class MyFunction(pytest.Function): pass class MyInstance(pytest.Instance): Function = MyFunction class MyClass(pytest.Class): Instance = MyInstance def pytest_pycollect_makeitem(collector, name, obj): if name.startswith("MyTestClass"): return MyClass(name, parent=collector) """) testdir.makepyfile(""" class MyTestClass: def test_hello(self): pass """) result = testdir.runpytest("--collectonly") result.stdout.fnmatch_lines([ "*MyClass*", "*MyInstance*", "*MyFunction*test_hello*", ]) def test_unorderable_types(testdir): testdir.makepyfile(""" class TestJoinEmpty: pass def make_test(): class Test: pass Test.__name__ = "TestFoo" return Test TestFoo = make_test() """) result = testdir.runpytest() assert "TypeError" not in result.stdout.str() assert result.ret == 0 def test_issue117_sessionscopeteardown(testdir): testdir.makepyfile(""" def pytest_funcarg__app(request): app = request.cached_setup( scope='session', setup=lambda: 0, teardown=lambda x: 3/x) return app def test_func(app): pass """) result = testdir.runpytest() assert result.ret != 0 result.stderr.fnmatch_lines([ "*3/x*", "*ZeroDivisionError*", ]) class TestRequestAPI: @pytest.mark.xfail(reason="consider flub feedback") def test_setup_can_query_funcargs(self, testdir): testdir.makeconftest(""" def pytest_runtest_setup(item): assert not hasattr(item, "_request") """) testdir.makepyfile(""" def pytest_funcarg__a(request): return 1 def pytest_funcarg__b(request): return request.getfuncargvalue("a") + 1 def test_hello(b): assert b == 2 """) result = testdir.runpytest() assert result.ret == 0 result.stdout.fnmatch_lines([ "*1 passed*", ]) result = testdir.makeconftest(""" import pytest @pytest.setup() def mysetup(testcontext): testcontext.uses_funcarg("db") """) result = testdir.runpytest() assert result.ret == 0 result.stdout.fnmatch_lines([ "*1 passed*", ]) class TestFuncargFactory: def test_receives_funcargs(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory() def arg1(): return 1 @pytest.factory() def arg2(arg1): return arg1 + 1 def test_add(arg2): assert arg2 == 2 def test_all(arg1, arg2): assert arg1 == 1 assert arg2 == 2 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=2) def test_receives_funcargs_scope_mismatch(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="function") def arg1(): return 1 @pytest.factory(scope="module") def arg2(arg1): return arg1 + 1 def test_add(arg2): assert arg2 == 2 """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*ScopeMismatch*involved factories*", "* def arg2*", "* def arg1*", "*1 error*" ]) def test_funcarg_parametrized_and_used_twice(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(params=[1,2]) def arg1(testcontext): l.append(1) return testcontext.param @pytest.factory() def arg2(arg1): return arg1 + 1 def test_add(arg1, arg2): assert arg2 == arg1 + 1 assert len(l) == arg1 """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*2 passed*" ]) class TestResourceIntegrationFunctional: def test_parametrize_with_ids(self, testdir): testdir.makepyfile(""" import pytest def pytest_generate_tests(metafunc): metafunc.parametrize(("a", "b"), [(1,1), (1,2)], ids=["basic", "advanced"]) def test_function(a, b): assert a == b """) result = testdir.runpytest("-v") assert result.ret == 1 result.stdout.fnmatch_lines_random([ "*test_function*basic*PASSED", "*test_function*advanced*FAILED", ]) class TestFuncargManager: def pytest_funcarg__testdir(self, request): testdir = request.getfuncargvalue("testdir") testdir.makeconftest(""" def pytest_funcarg__hello(request): return "conftest" def pytest_funcarg__fm(request): return request.funcargmanager def pytest_funcarg__item(request): return request._pyfuncitem """) return testdir def test_parsefactories_conftest(self, testdir): testdir.makepyfile(""" def test_hello(item, fm): for name in ("fm", "hello", "item"): faclist = fm.getfactorylist(name, item.nodeid, item.obj) assert len(faclist) == 1 fac = faclist[0] assert fac.func.__name__ == "pytest_funcarg__" + name """) reprec = testdir.inline_run("-s") reprec.assertoutcome(passed=1) def test_parsefactories_conftest_and_module_and_class(self, testdir): testdir.makepyfile(""" def pytest_funcarg__hello(request): return "module" class TestClass: def pytest_funcarg__hello(self, request): return "class" def test_hello(self, item, fm): faclist = fm.getfactorylist("hello", item.nodeid, item.obj) print (faclist) assert len(faclist) == 3 assert faclist[0].func(item._request) == "conftest" assert faclist[1].func(item._request) == "module" assert faclist[2].func(item._request) == "class" """) reprec = testdir.inline_run("-s") reprec.assertoutcome(passed=1) class TestSetupDiscovery: def pytest_funcarg__testdir(self, request): testdir = request.getfuncargvalue("testdir") testdir.makeconftest(""" import pytest @pytest.setup() def perfunction(testcontext, tmpdir): pass @pytest.factory() def arg1(tmpdir): pass @pytest.setup() def perfunction2(arg1): pass def pytest_funcarg__fm(request): return request.funcargmanager def pytest_funcarg__item(request): return request._pyfuncitem """) return testdir def test_parsefactories_conftest(self, testdir): testdir.makepyfile(""" def test_check_setup(item, fm): setupcalls, allnames = fm.getsetuplist(item.nodeid) assert len(setupcalls) == 2 assert setupcalls[0].func.__name__ == "perfunction" assert "testcontext" in setupcalls[0].funcargnames assert "tmpdir" in setupcalls[0].funcargnames assert setupcalls[1].func.__name__ == "perfunction2" assert "testcontext" not in setupcalls[1].funcargnames assert "arg1" in setupcalls[1].funcargnames assert "tmpdir" not in setupcalls[1].funcargnames #assert "tmpdir" in setupcalls[1].depfuncargs """) reprec = testdir.inline_run("-s") reprec.assertoutcome(passed=1) class TestSetupManagement: def test_funcarg_and_setup(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(scope="module") def arg(): l.append(1) return 0 @pytest.setup(scope="class") def something(arg): l.append(2) def test_hello(arg): assert len(l) == 2 assert l == [1,2] assert arg == 0 def test_hello2(arg): assert len(l) == 2 assert l == [1,2] assert arg == 0 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=2) def test_setup_uses_parametrized_resource(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(params=[1,2]) def arg(testcontext): return testcontext.param @pytest.setup() def something(arg): l.append(arg) def test_hello(): if len(l) == 1: assert l == [1] elif len(l) == 2: assert l == [1, 2] else: 0/0 """) reprec = testdir.inline_run("-s") reprec.assertoutcome(passed=2) def test_session_parametrized_function_setup(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(scope="session", params=[1,2]) def arg(testcontext): return testcontext.param @pytest.setup(scope="function") def append(testcontext, arg): if testcontext.function.__name__ == "test_some": l.append(arg) def test_some(): pass def test_result(arg): assert len(l) == arg assert l[:arg] == [1,2][:arg] """) reprec = testdir.inline_run("-v", "-s") reprec.assertoutcome(passed=4) def test_class_function_parametrization_finalization(self, testdir): p = testdir.makeconftest(""" import pytest import pprint l = [] @pytest.factory(scope="function", params=[1,2]) def farg(testcontext): return testcontext.param @pytest.factory(scope="class", params=list("ab")) def carg(testcontext): return testcontext.param @pytest.setup(scope="class") def append(testcontext, farg, carg): def fin(): l.append("fin_%s%s" % (carg, farg)) testcontext.addfinalizer(fin) """) testdir.makepyfile(""" import pytest class TestClass: def test_1(self): pass class TestClass2: def test_2(self): pass """) reprec = testdir.inline_run("-v",) reprec.assertoutcome(passed=8) config = reprec.getcalls("pytest_unconfigure")[0].config l = config._conftest.getconftestmodules(p)[0].l assert l == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2 class TestFuncargMarker: def test_parametrize(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(params=["a", "b", "c"]) def arg(testcontext): return testcontext.param l = [] def test_param(arg): l.append(arg) def test_result(): assert l == list("abc") """) reprec = testdir.inline_run() reprec.assertoutcome(passed=4) def test_scope_session(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(scope="module") def arg(): l.append(1) return 1 def test_1(arg): assert arg == 1 def test_2(arg): assert arg == 1 assert len(l) == 1 class TestClass: def test3(self, arg): assert arg == 1 assert len(l) == 1 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=3) def test_scope_module_uses_session(self, testdir): testdir.makepyfile(""" import pytest l = [] @pytest.factory(scope="module") def arg(): l.append(1) return 1 def test_1(arg): assert arg == 1 def test_2(arg): assert arg == 1 assert len(l) == 1 class TestClass: def test3(self, arg): assert arg == 1 assert len(l) == 1 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=3) def test_scope_module_and_finalizer(self, testdir): testdir.makeconftest(""" import pytest finalized = [] created = [] @pytest.factory(scope="module") def arg(testcontext): created.append(1) assert testcontext.scope == "module" testcontext.addfinalizer(lambda: finalized.append(1)) def pytest_funcarg__created(request): return len(created) def pytest_funcarg__finalized(request): return len(finalized) """) testdir.makepyfile( test_mod1=""" def test_1(arg, created, finalized): assert created == 1 assert finalized == 0 def test_2(arg, created, finalized): assert created == 1 assert finalized == 0""", test_mod2=""" def test_3(arg, created, finalized): assert created == 2 assert finalized == 1""", test_mode3=""" def test_4(arg, created, finalized): assert created == 3 assert finalized == 2 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=4) @pytest.mark.parametrize("method", [ 'request.getfuncargvalue("arg")', 'request.cached_setup(lambda: None, scope="function")', ], ids=["getfuncargvalue", "cached_setup"]) def test_scope_mismatch(self, testdir, method): testdir.makeconftest(""" import pytest finalized = [] created = [] @pytest.factory(scope="function") def arg(testcontext): pass """) testdir.makepyfile( test_mod1=""" import pytest @pytest.factory(scope="session") def arg(testcontext): %s def test_1(arg): pass """ % method) result = testdir.runpytest() assert result.ret != 0 result.stdout.fnmatch_lines([ "*ScopeMismatch*You tried*function*session*request*", ]) def test_register_only_with_mark(self, testdir): testdir.makeconftest(""" import pytest @pytest.factory() def arg(): return 1 """) testdir.makepyfile( test_mod1=""" import pytest @pytest.factory() def arg(arg): return arg + 1 def test_1(arg): assert arg == 2 """) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_parametrize_and_scope(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="module", params=["a", "b", "c"]) def arg(testcontext): return testcontext.param l = [] def test_param(arg): l.append(arg) """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=3) l = reprec.getcalls("pytest_runtest_call")[0].item.module.l assert len(l) == 3 assert "a" in l assert "b" in l assert "c" in l def test_scope_mismatch(self, testdir): testdir.makeconftest(""" import pytest @pytest.factory(scope="function") def arg(testcontext): pass """) testdir.makepyfile(""" import pytest @pytest.factory(scope="session") def arg(arg): pass def test_mismatch(arg): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*ScopeMismatch*", "*1 error*", ]) def test_parametrize_separated_order(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="module", params=[1, 2]) def arg(testcontext): return testcontext.param l = [] def test_1(arg): l.append(arg) def test_2(arg): l.append(arg) """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=4) l = reprec.getcalls("pytest_runtest_call")[0].item.module.l assert l == [1,1,2,2] def test_module_parametrized_ordering(self, testdir): testdir.makeconftest(""" import pytest @pytest.factory(scope="session", params="s1 s2".split()) def sarg(): pass @pytest.factory(scope="module", params="m1 m2".split()) def marg(): pass """) testdir.makepyfile(test_mod1=""" def test_func(sarg): pass def test_func1(marg): pass """, test_mod2=""" def test_func2(sarg): pass def test_func3(sarg, marg): pass def test_func3b(sarg, marg): pass def test_func4(marg): pass """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines(""" test_mod1.py:1: test_func[s1] PASSED test_mod2.py:1: test_func2[s1] PASSED test_mod2.py:3: test_func3[s1-m1] PASSED test_mod2.py:5: test_func3b[s1-m1] PASSED test_mod2.py:3: test_func3[s1-m2] PASSED test_mod2.py:5: test_func3b[s1-m2] PASSED test_mod1.py:1: test_func[s2] PASSED test_mod2.py:1: test_func2[s2] PASSED test_mod2.py:3: test_func3[s2-m1] PASSED test_mod2.py:5: test_func3b[s2-m1] PASSED test_mod2.py:7: test_func4[m1] PASSED test_mod2.py:3: test_func3[s2-m2] PASSED test_mod2.py:5: test_func3b[s2-m2] PASSED test_mod2.py:7: test_func4[m2] PASSED test_mod1.py:3: test_func1[m1] PASSED test_mod1.py:3: test_func1[m2] PASSED """) def test_class_ordering(self, testdir): p = testdir.makeconftest(""" import pytest l = [] @pytest.factory(scope="function", params=[1,2]) def farg(testcontext): return testcontext.param @pytest.factory(scope="class", params=list("ab")) def carg(testcontext): return testcontext.param @pytest.setup(scope="class") def append(testcontext, farg, carg): def fin(): l.append("fin_%s%s" % (carg, farg)) testcontext.addfinalizer(fin) """) testdir.makepyfile(""" import pytest class TestClass2: def test_1(self): pass def test_2(self): pass class TestClass: def test_3(self): pass """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines(""" test_class_ordering.py:4: TestClass2.test_1[1-a] PASSED test_class_ordering.py:4: TestClass2.test_1[2-a] PASSED test_class_ordering.py:6: TestClass2.test_2[1-a] PASSED test_class_ordering.py:6: TestClass2.test_2[2-a] PASSED test_class_ordering.py:4: TestClass2.test_1[1-b] PASSED test_class_ordering.py:4: TestClass2.test_1[2-b] PASSED test_class_ordering.py:6: TestClass2.test_2[1-b] PASSED test_class_ordering.py:6: TestClass2.test_2[2-b] PASSED test_class_ordering.py:9: TestClass.test_3[1-a] PASSED test_class_ordering.py:9: TestClass.test_3[2-a] PASSED test_class_ordering.py:9: TestClass.test_3[1-b] PASSED test_class_ordering.py:9: TestClass.test_3[2-b] PASSED """) def test_parametrize_separated_order_higher_scope_first(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="function", params=[1, 2]) def arg(testcontext): param = testcontext.param testcontext.addfinalizer(lambda: l.append("fin:%s" % param)) l.append("create:%s" % param) return testcontext.param @pytest.factory(scope="module", params=["mod1", "mod2"]) def modarg(testcontext): param = testcontext.param testcontext.addfinalizer(lambda: l.append("fin:%s" % param)) l.append("create:%s" % param) return testcontext.param l = [] def test_1(arg): l.append("test1") def test_2(modarg): l.append("test2") def test_3(arg, modarg): l.append("test3") def test_4(modarg, arg): l.append("test4") def test_5(): assert len(l) == 12 * 3 import pprint pprint.pprint(l) assert l == [ 'create:1', 'test1', 'fin:1', 'create:2', 'test1', 'fin:2', 'create:mod1', 'test2', 'create:1', 'test3', 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1', 'test4', 'fin:1', 'create:2', 'test4', 'fin:mod1', 'fin:2', 'create:mod2', 'test2', 'create:1', 'test3', 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1', 'test4', 'fin:1', 'create:2', 'test4', 'fin:mod2', 'fin:2'] """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=12+1) def test_parametrize_separated_lifecycle(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="module", params=[1, 2]) def arg(testcontext): testcontext.config.l = l # to access from outer x = testcontext.param testcontext.addfinalizer(lambda: l.append("fin%s" % x)) return testcontext.param l = [] def test_1(arg): l.append(arg) def test_2(arg): l.append(arg) """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=4) l = reprec.getcalls("pytest_configure")[0].config.l import pprint pprint.pprint(l) assert len(l) == 6 assert l[0] == l[1] == 1 assert l[2] == "fin1" assert l[3] == l[4] == 2 assert l[5] == "fin2" def test_parametrize_function_scoped_finalizers_called(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="function", params=[1, 2]) def arg(testcontext): x = testcontext.param testcontext.addfinalizer(lambda: l.append("fin%s" % x)) return testcontext.param l = [] def test_1(arg): l.append(arg) def test_2(arg): l.append(arg) def test_3(): assert len(l) == 8 assert l == [1, "fin1", 2, "fin2", 1, "fin1", 2, "fin2"] """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=5) def test_parametrize_setup_function(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(scope="module", params=[1, 2]) def arg(testcontext): return testcontext.param @pytest.setup(scope="module") def mysetup(testcontext, arg): testcontext.addfinalizer(lambda: l.append("fin%s" % arg)) l.append("setup%s" % arg) l = [] def test_1(arg): l.append(arg) def test_2(arg): l.append(arg) def test_3(): import pprint pprint.pprint(l) if arg == 1: assert l == ["setup1", 1, 1, ] elif arg == 2: assert l == ["setup1", 1, 1, "fin1", "setup2", 2, 2, ] """) reprec = testdir.inline_run("-v") reprec.assertoutcome(passed=6) @pytest.mark.parametrize(("scope", "ok", "error"),[ ["session", "", "fspath class function module"], ["module", "module fspath", "cls function"], ["class", "module fspath cls", "function"], ["function", "module fspath cls function", ""] ]) class TestTestContextScopeAccess: def test_setup(self, testdir, scope, ok, error): testdir.makepyfile(""" import pytest @pytest.setup(scope=%r) def myscoped(testcontext): for x in %r: assert hasattr(testcontext, x) for x in %r: pytest.raises(AttributeError, lambda: getattr(testcontext, x)) assert testcontext.session assert testcontext.config def test_func(): pass """ %(scope, ok.split(), error.split())) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_funcarg(self, testdir, scope, ok, error): testdir.makepyfile(""" import pytest @pytest.factory(scope=%r) def arg(testcontext): for x in %r: assert hasattr(testcontext, x) for x in %r: pytest.raises(AttributeError, lambda: getattr(testcontext, x)) assert testcontext.session assert testcontext.config def test_func(arg): pass """ %(scope, ok.split(), error.split())) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) class TestErrors: def test_subfactory_missing_funcarg(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory() def gen(request): return 1 def test_something(gen): pass """) result = testdir.runpytest() assert result.ret != 0 result.stdout.fnmatch_lines([ "*def gen(request):*", "*no factory*request*", "*1 error*", ]) def test_setupfunc_missing_funcarg(self, testdir): testdir.makepyfile(""" import pytest @pytest.setup() def gen(request): return 1 def test_something(): pass """) result = testdir.runpytest() assert result.ret != 0 result.stdout.fnmatch_lines([ "*def gen(request):*", "*no factory*request*", "*1 error*", ]) class TestTestContextVarious: def test_newstyle_no_request(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory() def arg(request): pass def test_1(arg): pass """) result = testdir.runpytest() result.stdout.fnmatch_lines([ "*no factory found*request*", ]) def test_setupcontext_no_param(self, testdir): testdir.makepyfile(""" import pytest @pytest.factory(params=[1,2]) def arg(testcontext): return testcontext.param @pytest.setup() def mysetup(testcontext, arg): assert not hasattr(testcontext, "param") def test_1(arg): assert arg in (1,2) """) reprec = testdir.inline_run() reprec.assertoutcome(passed=2)