1253 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			1253 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			Python
		
	
	
	
| from __future__ import absolute_import
 | |
| from __future__ import division
 | |
| from __future__ import print_function
 | |
| 
 | |
| import os
 | |
| import sys
 | |
| 
 | |
| try:
 | |
|     import mock
 | |
| except ImportError:
 | |
|     import unittest.mock as mock
 | |
| import pytest
 | |
| from _pytest.mark import (
 | |
|     MarkGenerator as Mark,
 | |
|     ParameterSet,
 | |
|     transfer_markers,
 | |
|     EMPTY_PARAMETERSET_OPTION,
 | |
| )
 | |
| from _pytest.nodes import Node, Collector
 | |
| 
 | |
| ignore_markinfo = pytest.mark.filterwarnings(
 | |
|     "ignore:MarkInfo objects:pytest.RemovedInPytest4Warning"
 | |
| )
 | |
| 
 | |
| 
 | |
| class TestMark(object):
 | |
|     def test_markinfo_repr(self):
 | |
|         from _pytest.mark import MarkInfo, Mark
 | |
| 
 | |
|         m = MarkInfo.for_mark(Mark("hello", (1, 2), {}))
 | |
|         repr(m)
 | |
| 
 | |
|     @pytest.mark.parametrize("attr", ["mark", "param"])
 | |
|     @pytest.mark.parametrize("modulename", ["py.test", "pytest"])
 | |
|     def test_pytest_exists_in_namespace_all(self, attr, modulename):
 | |
|         module = sys.modules[modulename]
 | |
|         assert attr in module.__all__
 | |
| 
 | |
|     def test_pytest_mark_notcallable(self):
 | |
|         mark = Mark()
 | |
|         pytest.raises((AttributeError, TypeError), mark)
 | |
| 
 | |
|     def test_mark_with_param(self):
 | |
|         def some_function(abc):
 | |
|             pass
 | |
| 
 | |
|         class SomeClass(object):
 | |
|             pass
 | |
| 
 | |
|         assert pytest.mark.fun(some_function) is some_function
 | |
|         assert pytest.mark.fun.with_args(some_function) is not some_function
 | |
| 
 | |
|         assert pytest.mark.fun(SomeClass) is SomeClass
 | |
|         assert pytest.mark.fun.with_args(SomeClass) is not SomeClass
 | |
| 
 | |
|     def test_pytest_mark_name_starts_with_underscore(self):
 | |
|         mark = Mark()
 | |
|         pytest.raises(AttributeError, getattr, mark, "_some_name")
 | |
| 
 | |
|     def test_pytest_mark_bare(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             pass
 | |
| 
 | |
|         mark.hello(f)
 | |
|         assert f.hello
 | |
| 
 | |
|     def test_mark_legacy_ignore_fail(self):
 | |
|         def add_attribute(func):
 | |
|             func.foo = 1
 | |
|             return func
 | |
| 
 | |
|         @pytest.mark.foo
 | |
|         @add_attribute
 | |
|         def test_fun():
 | |
|             pass
 | |
| 
 | |
|         assert test_fun.foo == 1
 | |
|         assert test_fun.pytestmark
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_pytest_mark_keywords(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             pass
 | |
| 
 | |
|         mark.world(x=3, y=4)(f)
 | |
|         assert f.world
 | |
|         assert f.world.kwargs["x"] == 3
 | |
|         assert f.world.kwargs["y"] == 4
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_apply_multiple_and_merge(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             pass
 | |
| 
 | |
|         mark.world
 | |
|         mark.world(x=3)(f)
 | |
|         assert f.world.kwargs["x"] == 3
 | |
|         mark.world(y=4)(f)
 | |
|         assert f.world.kwargs["x"] == 3
 | |
|         assert f.world.kwargs["y"] == 4
 | |
|         mark.world(y=1)(f)
 | |
|         assert f.world.kwargs["y"] == 1
 | |
|         assert len(f.world.args) == 0
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_pytest_mark_positional(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             pass
 | |
| 
 | |
|         mark.world("hello")(f)
 | |
|         assert f.world.args[0] == "hello"
 | |
|         mark.world("world")(f)
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_pytest_mark_positional_func_and_keyword(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             raise Exception
 | |
| 
 | |
|         m = mark.world(f, omega="hello")
 | |
| 
 | |
|         def g():
 | |
|             pass
 | |
| 
 | |
|         assert m(g) == g
 | |
|         assert g.world.args[0] is f
 | |
|         assert g.world.kwargs["omega"] == "hello"
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_pytest_mark_reuse(self):
 | |
|         mark = Mark()
 | |
| 
 | |
|         def f():
 | |
|             pass
 | |
| 
 | |
|         w = mark.some
 | |
|         w("hello", reason="123")(f)
 | |
|         assert f.some.args[0] == "hello"
 | |
|         assert f.some.kwargs["reason"] == "123"
 | |
| 
 | |
|         def g():
 | |
|             pass
 | |
| 
 | |
|         w("world", reason2="456")(g)
 | |
|         assert g.some.args[0] == "world"
 | |
|         assert "reason" not in g.some.kwargs
 | |
|         assert g.some.kwargs["reason2"] == "456"
 | |
| 
 | |
| 
 | |
| def test_marked_class_run_twice(testdir, request):
 | |
|     """Test fails file is run twice that contains marked class.
 | |
|     See issue#683.
 | |
|     """
 | |
|     py_file = testdir.makepyfile(
 | |
|         """
 | |
|     import pytest
 | |
|     @pytest.mark.parametrize('abc', [1, 2, 3])
 | |
|     class Test1(object):
 | |
|         def test_1(self, abc):
 | |
|             assert abc in [1, 2, 3]
 | |
|     """
 | |
|     )
 | |
|     file_name = os.path.basename(py_file.strpath)
 | |
|     rec = testdir.inline_run(file_name, file_name)
 | |
|     rec.assertoutcome(passed=6)
 | |
| 
 | |
| 
 | |
| def test_ini_markers(testdir):
 | |
|     testdir.makeini(
 | |
|         """
 | |
|         [pytest]
 | |
|         markers =
 | |
|             a1: this is a webtest marker
 | |
|             a2: this is a smoke marker
 | |
|     """
 | |
|     )
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         def test_markers(pytestconfig):
 | |
|             markers = pytestconfig.getini("markers")
 | |
|             print (markers)
 | |
|             assert len(markers) >= 2
 | |
|             assert markers[0].startswith("a1:")
 | |
|             assert markers[1].startswith("a2:")
 | |
|     """
 | |
|     )
 | |
|     rec = testdir.inline_run()
 | |
|     rec.assertoutcome(passed=1)
 | |
| 
 | |
| 
 | |
| def test_markers_option(testdir):
 | |
|     testdir.makeini(
 | |
|         """
 | |
|         [pytest]
 | |
|         markers =
 | |
|             a1: this is a webtest marker
 | |
|             a1some: another marker
 | |
|             nodescription
 | |
|     """
 | |
|     )
 | |
|     result = testdir.runpytest("--markers")
 | |
|     result.stdout.fnmatch_lines(
 | |
|         ["*a1*this is a webtest*", "*a1some*another marker", "*nodescription*"]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_ini_markers_whitespace(testdir):
 | |
|     testdir.makeini(
 | |
|         """
 | |
|         [pytest]
 | |
|         markers =
 | |
|             a1 : this is a whitespace marker
 | |
|     """
 | |
|     )
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
| 
 | |
|         @pytest.mark.a1
 | |
|         def test_markers():
 | |
|             assert True
 | |
|     """
 | |
|     )
 | |
|     rec = testdir.inline_run("--strict", "-m", "a1")
 | |
|     rec.assertoutcome(passed=1)
 | |
| 
 | |
| 
 | |
| def test_marker_without_description(testdir):
 | |
|     testdir.makefile(
 | |
|         ".cfg",
 | |
|         setup="""
 | |
|         [tool:pytest]
 | |
|         markers=slow
 | |
|     """,
 | |
|     )
 | |
|     testdir.makeconftest(
 | |
|         """
 | |
|         import pytest
 | |
|         pytest.mark.xfail('FAIL')
 | |
|     """
 | |
|     )
 | |
|     ftdir = testdir.mkdir("ft1_dummy")
 | |
|     testdir.tmpdir.join("conftest.py").move(ftdir.join("conftest.py"))
 | |
|     rec = testdir.runpytest("--strict")
 | |
|     rec.assert_outcomes()
 | |
| 
 | |
| 
 | |
| def test_markers_option_with_plugin_in_current_dir(testdir):
 | |
|     testdir.makeconftest('pytest_plugins = "flip_flop"')
 | |
|     testdir.makepyfile(
 | |
|         flip_flop="""\
 | |
|         def pytest_configure(config):
 | |
|             config.addinivalue_line("markers", "flip:flop")
 | |
| 
 | |
|         def pytest_generate_tests(metafunc):
 | |
|             try:
 | |
|                 mark = metafunc.function.flipper
 | |
|             except AttributeError:
 | |
|                 return
 | |
|             metafunc.parametrize("x", (10, 20))"""
 | |
|     )
 | |
|     testdir.makepyfile(
 | |
|         """\
 | |
|         import pytest
 | |
|         @pytest.mark.flipper
 | |
|         def test_example(x):
 | |
|             assert x"""
 | |
|     )
 | |
| 
 | |
|     result = testdir.runpytest("--markers")
 | |
|     result.stdout.fnmatch_lines(["*flip*flop*"])
 | |
| 
 | |
| 
 | |
| def test_mark_on_pseudo_function(testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
| 
 | |
|         @pytest.mark.r(lambda x: 0/0)
 | |
|         def test_hello():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     reprec = testdir.inline_run()
 | |
|     reprec.assertoutcome(passed=1)
 | |
| 
 | |
| 
 | |
| def test_strict_prohibits_unregistered_markers(testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
|         @pytest.mark.unregisteredmark
 | |
|         def test_hello():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     result = testdir.runpytest("--strict")
 | |
|     assert result.ret != 0
 | |
|     result.stdout.fnmatch_lines(["'unregisteredmark' not a registered marker"])
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "spec",
 | |
|     [
 | |
|         ("xyz", ("test_one",)),
 | |
|         ("xyz and xyz2", ()),
 | |
|         ("xyz2", ("test_two",)),
 | |
|         ("xyz or xyz2", ("test_one", "test_two")),
 | |
|     ],
 | |
| )
 | |
| def test_mark_option(spec, testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
|         @pytest.mark.xyz
 | |
|         def test_one():
 | |
|             pass
 | |
|         @pytest.mark.xyz2
 | |
|         def test_two():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     opt, passed_result = spec
 | |
|     rec = testdir.inline_run("-m", opt)
 | |
|     passed, skipped, fail = rec.listoutcomes()
 | |
|     passed = [x.nodeid.split("::")[-1] for x in passed]
 | |
|     assert len(passed) == len(passed_result)
 | |
|     assert list(passed) == list(passed_result)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "spec", [("interface", ("test_interface",)), ("not interface", ("test_nointer",))]
 | |
| )
 | |
| def test_mark_option_custom(spec, testdir):
 | |
|     testdir.makeconftest(
 | |
|         """
 | |
|         import pytest
 | |
|         def pytest_collection_modifyitems(items):
 | |
|             for item in items:
 | |
|                 if "interface" in item.nodeid:
 | |
|                     item.add_marker(pytest.mark.interface)
 | |
|     """
 | |
|     )
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         def test_interface():
 | |
|             pass
 | |
|         def test_nointer():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     opt, passed_result = spec
 | |
|     rec = testdir.inline_run("-m", opt)
 | |
|     passed, skipped, fail = rec.listoutcomes()
 | |
|     passed = [x.nodeid.split("::")[-1] for x in passed]
 | |
|     assert len(passed) == len(passed_result)
 | |
|     assert list(passed) == list(passed_result)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "spec",
 | |
|     [
 | |
|         ("interface", ("test_interface",)),
 | |
|         ("not interface", ("test_nointer", "test_pass")),
 | |
|         ("pass", ("test_pass",)),
 | |
|         ("not pass", ("test_interface", "test_nointer")),
 | |
|     ],
 | |
| )
 | |
| def test_keyword_option_custom(spec, testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         def test_interface():
 | |
|             pass
 | |
|         def test_nointer():
 | |
|             pass
 | |
|         def test_pass():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     opt, passed_result = spec
 | |
|     rec = testdir.inline_run("-k", opt)
 | |
|     passed, skipped, fail = rec.listoutcomes()
 | |
|     passed = [x.nodeid.split("::")[-1] for x in passed]
 | |
|     assert len(passed) == len(passed_result)
 | |
|     assert list(passed) == list(passed_result)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "spec",
 | |
|     [
 | |
|         ("None", ("test_func[None]",)),
 | |
|         ("1.3", ("test_func[1.3]",)),
 | |
|         ("2-3", ("test_func[2-3]",)),
 | |
|     ],
 | |
| )
 | |
| def test_keyword_option_parametrize(spec, testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
|         @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
 | |
|         def test_func(arg):
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     opt, passed_result = spec
 | |
|     rec = testdir.inline_run("-k", opt)
 | |
|     passed, skipped, fail = rec.listoutcomes()
 | |
|     passed = [x.nodeid.split("::")[-1] for x in passed]
 | |
|     assert len(passed) == len(passed_result)
 | |
|     assert list(passed) == list(passed_result)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "spec",
 | |
|     [
 | |
|         (
 | |
|             "foo or import",
 | |
|             "ERROR: Python keyword 'import' not accepted in expressions passed to '-k'",
 | |
|         ),
 | |
|         ("foo or", "ERROR: Wrong expression passed to '-k': foo or"),
 | |
|     ],
 | |
| )
 | |
| def test_keyword_option_wrong_arguments(spec, testdir, capsys):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|             def test_func(arg):
 | |
|                 pass
 | |
|         """
 | |
|     )
 | |
|     opt, expected_result = spec
 | |
|     testdir.inline_run("-k", opt)
 | |
|     out = capsys.readouterr().err
 | |
|     assert expected_result in out
 | |
| 
 | |
| 
 | |
| def test_parametrized_collected_from_command_line(testdir):
 | |
|     """Parametrized test not collected if test named specified
 | |
|        in command line issue#649.
 | |
|     """
 | |
|     py_file = testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
|         @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
 | |
|         def test_func(arg):
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     file_name = os.path.basename(py_file.strpath)
 | |
|     rec = testdir.inline_run(file_name + "::" + "test_func")
 | |
|     rec.assertoutcome(passed=3)
 | |
| 
 | |
| 
 | |
| def test_parametrized_collect_with_wrong_args(testdir):
 | |
|     """Test collect parametrized func with wrong number of args."""
 | |
|     py_file = testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
| 
 | |
|         @pytest.mark.parametrize('foo, bar', [(1, 2, 3)])
 | |
|         def test_func(foo, bar):
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     result = testdir.runpytest(py_file)
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             'E   ValueError: In "parametrize" the number of values ((1, 2, 3)) '
 | |
|             "must be equal to the number of names (['foo', 'bar'])"
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_parametrized_with_kwargs(testdir):
 | |
|     """Test collect parametrized func with wrong number of args."""
 | |
|     py_file = testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
| 
 | |
|         @pytest.fixture(params=[1,2])
 | |
|         def a(request):
 | |
|             return request.param
 | |
| 
 | |
|         @pytest.mark.parametrize(argnames='b', argvalues=[1, 2])
 | |
|         def test_func(a, b):
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     result = testdir.runpytest(py_file)
 | |
|     assert result.ret == 0
 | |
| 
 | |
| 
 | |
| class TestFunctional(object):
 | |
|     def test_mark_per_function(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.mark.hello
 | |
|             def test_hello():
 | |
|                 assert hasattr(test_hello, 'hello')
 | |
|         """
 | |
|         )
 | |
|         result = testdir.runpytest(p)
 | |
|         result.stdout.fnmatch_lines(["*1 passed*"])
 | |
| 
 | |
|     def test_mark_per_module(self, testdir):
 | |
|         item = testdir.getitem(
 | |
|             """
 | |
|             import pytest
 | |
|             pytestmark = pytest.mark.hello
 | |
|             def test_func():
 | |
|                 pass
 | |
|         """
 | |
|         )
 | |
|         keywords = item.keywords
 | |
|         assert "hello" in keywords
 | |
| 
 | |
|     def test_marklist_per_class(self, testdir):
 | |
|         item = testdir.getitem(
 | |
|             """
 | |
|             import pytest
 | |
|             class TestClass(object):
 | |
|                 pytestmark = [pytest.mark.hello, pytest.mark.world]
 | |
|                 def test_func(self):
 | |
|                     assert TestClass.test_func.hello
 | |
|                     assert TestClass.test_func.world
 | |
|         """
 | |
|         )
 | |
|         keywords = item.keywords
 | |
|         assert "hello" in keywords
 | |
| 
 | |
|     def test_marklist_per_module(self, testdir):
 | |
|         item = testdir.getitem(
 | |
|             """
 | |
|             import pytest
 | |
|             pytestmark = [pytest.mark.hello, pytest.mark.world]
 | |
|             class TestClass(object):
 | |
|                 def test_func(self):
 | |
|                     assert TestClass.test_func.hello
 | |
|                     assert TestClass.test_func.world
 | |
|         """
 | |
|         )
 | |
|         keywords = item.keywords
 | |
|         assert "hello" in keywords
 | |
|         assert "world" in keywords
 | |
| 
 | |
|     def test_mark_per_class_decorator(self, testdir):
 | |
|         item = testdir.getitem(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.mark.hello
 | |
|             class TestClass(object):
 | |
|                 def test_func(self):
 | |
|                     assert TestClass.test_func.hello
 | |
|         """
 | |
|         )
 | |
|         keywords = item.keywords
 | |
|         assert "hello" in keywords
 | |
| 
 | |
|     def test_mark_per_class_decorator_plus_existing_dec(self, testdir):
 | |
|         item = testdir.getitem(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.mark.hello
 | |
|             class TestClass(object):
 | |
|                 pytestmark = pytest.mark.world
 | |
|                 def test_func(self):
 | |
|                     assert TestClass.test_func.hello
 | |
|                     assert TestClass.test_func.world
 | |
|         """
 | |
|         )
 | |
|         keywords = item.keywords
 | |
|         assert "hello" in keywords
 | |
|         assert "world" in keywords
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_merging_markers(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             pytestmark = pytest.mark.hello("pos1", x=1, y=2)
 | |
|             class TestClass(object):
 | |
|                 # classlevel overrides module level
 | |
|                 pytestmark = pytest.mark.hello(x=3)
 | |
|                 @pytest.mark.hello("pos0", z=4)
 | |
|                 def test_func(self):
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         item, = items
 | |
|         keywords = item.keywords
 | |
|         marker = keywords["hello"]
 | |
|         assert marker.args == ("pos0", "pos1")
 | |
|         assert marker.kwargs == {"x": 1, "y": 2, "z": 4}
 | |
| 
 | |
|         # test the new __iter__ interface
 | |
|         values = list(marker)
 | |
|         assert len(values) == 3
 | |
|         assert values[0].args == ("pos0",)
 | |
|         assert values[1].args == ()
 | |
|         assert values[2].args == ("pos1",)
 | |
| 
 | |
|     def test_merging_markers_deep(self, testdir):
 | |
|         # issue 199 - propagate markers into nested classes
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             class TestA(object):
 | |
|                 pytestmark = pytest.mark.a
 | |
|                 def test_b(self):
 | |
|                     assert True
 | |
|                 class TestC(object):
 | |
|                     # this one didnt get marked
 | |
|                     def test_d(self):
 | |
|                         assert True
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         for item in items:
 | |
|             print(item, item.keywords)
 | |
|             assert [x for x in item.iter_markers() if x.name == "a"]
 | |
| 
 | |
|     def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
| 
 | |
|             @pytest.mark.a
 | |
|             class Base(object): pass
 | |
| 
 | |
|             @pytest.mark.b
 | |
|             class Test1(Base):
 | |
|                 def test_foo(self): pass
 | |
| 
 | |
|             class Test2(Base):
 | |
|                 def test_bar(self): pass
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         self.assert_markers(items, test_foo=("a", "b"), test_bar=("a",))
 | |
| 
 | |
|     @pytest.mark.issue568
 | |
|     def test_mark_should_not_pass_to_siebling_class(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
| 
 | |
|             class TestBase(object):
 | |
|                 def test_foo(self):
 | |
|                     pass
 | |
| 
 | |
|             @pytest.mark.b
 | |
|             class TestSub(TestBase):
 | |
|                 pass
 | |
| 
 | |
| 
 | |
|             class TestOtherSub(TestBase):
 | |
|                 pass
 | |
| 
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         base_item, sub_item, sub_item_other = items
 | |
|         print(items, [x.nodeid for x in items])
 | |
|         # legacy api smears
 | |
|         assert hasattr(base_item.obj, "b")
 | |
|         assert hasattr(sub_item_other.obj, "b")
 | |
|         assert hasattr(sub_item.obj, "b")
 | |
| 
 | |
|         # new api seregates
 | |
|         assert not list(base_item.iter_markers(name="b"))
 | |
|         assert not list(sub_item_other.iter_markers(name="b"))
 | |
|         assert list(sub_item.iter_markers(name="b"))
 | |
| 
 | |
|     def test_mark_decorator_baseclasses_merged(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
| 
 | |
|             @pytest.mark.a
 | |
|             class Base(object): pass
 | |
| 
 | |
|             @pytest.mark.b
 | |
|             class Base2(Base): pass
 | |
| 
 | |
|             @pytest.mark.c
 | |
|             class Test1(Base2):
 | |
|                 def test_foo(self): pass
 | |
| 
 | |
|             class Test2(Base2):
 | |
|                 @pytest.mark.d
 | |
|                 def test_bar(self): pass
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         self.assert_markers(items, test_foo=("a", "b", "c"), test_bar=("a", "b", "d"))
 | |
| 
 | |
|     def test_mark_closest(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
| 
 | |
|             @pytest.mark.c(location="class")
 | |
|             class Test:
 | |
|                 @pytest.mark.c(location="function")
 | |
|                 def test_has_own():
 | |
|                     pass
 | |
| 
 | |
|                 def test_has_inherited():
 | |
|                     pass
 | |
| 
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         has_own, has_inherited = items
 | |
|         assert has_own.get_closest_marker("c").kwargs == {"location": "function"}
 | |
|         assert has_inherited.get_closest_marker("c").kwargs == {"location": "class"}
 | |
|         assert has_own.get_closest_marker("missing") is None
 | |
| 
 | |
|     def test_mark_with_wrong_marker(self, testdir):
 | |
|         reprec = testdir.inline_runsource(
 | |
|             """
 | |
|                 import pytest
 | |
|                 class pytestmark(object):
 | |
|                     pass
 | |
|                 def test_func():
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         values = reprec.getfailedcollections()
 | |
|         assert len(values) == 1
 | |
|         assert "TypeError" in str(values[0].longrepr)
 | |
| 
 | |
|     def test_mark_dynamically_in_funcarg(self, testdir):
 | |
|         testdir.makeconftest(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.fixture
 | |
|             def arg(request):
 | |
|                 request.applymarker(pytest.mark.hello)
 | |
|             def pytest_terminal_summary(terminalreporter):
 | |
|                 values = terminalreporter.stats['passed']
 | |
|                 terminalreporter._tw.line("keyword: %s" % values[0].keywords)
 | |
|         """
 | |
|         )
 | |
|         testdir.makepyfile(
 | |
|             """
 | |
|             def test_func(arg):
 | |
|                 pass
 | |
|         """
 | |
|         )
 | |
|         result = testdir.runpytest()
 | |
|         result.stdout.fnmatch_lines(["keyword: *hello*"])
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_merging_markers_two_functions(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.mark.hello("pos1", z=4)
 | |
|             @pytest.mark.hello("pos0", z=3)
 | |
|             def test_func():
 | |
|                 pass
 | |
|         """
 | |
|         )
 | |
|         items, rec = testdir.inline_genitems(p)
 | |
|         item, = items
 | |
|         keywords = item.keywords
 | |
|         marker = keywords["hello"]
 | |
|         values = list(marker)
 | |
|         assert len(values) == 2
 | |
|         assert values[0].args == ("pos0",)
 | |
|         assert values[1].args == ("pos1",)
 | |
| 
 | |
|     def test_no_marker_match_on_unmarked_names(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.mark.shouldmatch
 | |
|             def test_marked():
 | |
|                 assert 1
 | |
| 
 | |
|             def test_unmarked():
 | |
|                 assert 1
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run("-m", "test_unmarked", p)
 | |
|         passed, skipped, failed = reprec.listoutcomes()
 | |
|         assert len(passed) + len(skipped) + len(failed) == 0
 | |
|         dlist = reprec.getcalls("pytest_deselected")
 | |
|         deselected_tests = dlist[0].items
 | |
|         assert len(deselected_tests) == 2
 | |
| 
 | |
|     def test_invalid_m_option(self, testdir):
 | |
|         testdir.makepyfile(
 | |
|             """
 | |
|             def test_a():
 | |
|                 pass
 | |
|         """
 | |
|         )
 | |
|         result = testdir.runpytest("-m bogus/")
 | |
|         result.stdout.fnmatch_lines(
 | |
|             ["INTERNALERROR> Marker expression must be valid Python!"]
 | |
|         )
 | |
| 
 | |
|     def test_keywords_at_node_level(self, testdir):
 | |
|         testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
|             @pytest.fixture(scope="session", autouse=True)
 | |
|             def some(request):
 | |
|                 request.keywords["hello"] = 42
 | |
|                 assert "world" not in request.keywords
 | |
| 
 | |
|             @pytest.fixture(scope="function", autouse=True)
 | |
|             def funcsetup(request):
 | |
|                 assert "world" in request.keywords
 | |
|                 assert "hello" in  request.keywords
 | |
| 
 | |
|             @pytest.mark.world
 | |
|             def test_function():
 | |
|                 pass
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run()
 | |
|         reprec.assertoutcome(passed=1)
 | |
| 
 | |
|     @ignore_markinfo
 | |
|     def test_keyword_added_for_session(self, testdir):
 | |
|         testdir.makeconftest(
 | |
|             """
 | |
|             import pytest
 | |
|             def pytest_collection_modifyitems(session):
 | |
|                 session.add_marker("mark1")
 | |
|                 session.add_marker(pytest.mark.mark2)
 | |
|                 session.add_marker(pytest.mark.mark3)
 | |
|                 pytest.raises(ValueError, lambda:
 | |
|                         session.add_marker(10))
 | |
|         """
 | |
|         )
 | |
|         testdir.makepyfile(
 | |
|             """
 | |
|             def test_some(request):
 | |
|                 assert "mark1" in request.keywords
 | |
|                 assert "mark2" in request.keywords
 | |
|                 assert "mark3" in request.keywords
 | |
|                 assert 10 not in request.keywords
 | |
|                 marker = request.node.get_marker("mark1")
 | |
|                 assert marker.name == "mark1"
 | |
|                 assert marker.args == ()
 | |
|                 assert marker.kwargs == {}
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run("-m", "mark1")
 | |
|         reprec.assertoutcome(passed=1)
 | |
| 
 | |
|     def assert_markers(self, items, **expected):
 | |
|         """assert that given items have expected marker names applied to them.
 | |
|         expected should be a dict of (item name -> seq of expected marker names)
 | |
| 
 | |
|         .. note:: this could be moved to ``testdir`` if proven to be useful
 | |
|         to other modules.
 | |
|         """
 | |
|         from _pytest.mark import MarkInfo
 | |
| 
 | |
|         items = {x.name: x for x in items}
 | |
|         for name, expected_markers in expected.items():
 | |
|             markers = items[name].keywords._markers
 | |
|             marker_names = {
 | |
|                 name for (name, v) in markers.items() if isinstance(v, MarkInfo)
 | |
|             }
 | |
|             assert marker_names == set(expected_markers)
 | |
| 
 | |
|     @pytest.mark.issue1540
 | |
|     @pytest.mark.filterwarnings("ignore")
 | |
|     def test_mark_from_parameters(self, testdir):
 | |
|         testdir.makepyfile(
 | |
|             """
 | |
|             import pytest
 | |
| 
 | |
|             pytestmark = pytest.mark.skipif(True, reason='skip all')
 | |
| 
 | |
|             # skipifs inside fixture params
 | |
|             params = [pytest.mark.skipif(False, reason='dont skip')('parameter')]
 | |
| 
 | |
| 
 | |
|             @pytest.fixture(params=params)
 | |
|             def parameter(request):
 | |
|                 return request.param
 | |
| 
 | |
| 
 | |
|             def test_1(parameter):
 | |
|                 assert True
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run()
 | |
|         reprec.assertoutcome(skipped=1)
 | |
| 
 | |
| 
 | |
| class TestKeywordSelection(object):
 | |
|     def test_select_simple(self, testdir):
 | |
|         file_test = testdir.makepyfile(
 | |
|             """
 | |
|             def test_one():
 | |
|                 assert 0
 | |
|             class TestClass(object):
 | |
|                 def test_method_one(self):
 | |
|                     assert 42 == 43
 | |
|         """
 | |
|         )
 | |
| 
 | |
|         def check(keyword, name):
 | |
|             reprec = testdir.inline_run("-s", "-k", keyword, file_test)
 | |
|             passed, skipped, failed = reprec.listoutcomes()
 | |
|             assert len(failed) == 1
 | |
|             assert failed[0].nodeid.split("::")[-1] == name
 | |
|             assert len(reprec.getcalls("pytest_deselected")) == 1
 | |
| 
 | |
|         for keyword in ["test_one", "est_on"]:
 | |
|             check(keyword, "test_one")
 | |
|         check("TestClass and test", "test_method_one")
 | |
| 
 | |
|     @pytest.mark.parametrize(
 | |
|         "keyword",
 | |
|         [
 | |
|             "xxx",
 | |
|             "xxx and test_2",
 | |
|             "TestClass",
 | |
|             "xxx and not test_1",
 | |
|             "TestClass and test_2",
 | |
|             "xxx and TestClass and test_2",
 | |
|         ],
 | |
|     )
 | |
|     def test_select_extra_keywords(self, testdir, keyword):
 | |
|         p = testdir.makepyfile(
 | |
|             test_select="""
 | |
|             def test_1():
 | |
|                 pass
 | |
|             class TestClass(object):
 | |
|                 def test_2(self):
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         testdir.makepyfile(
 | |
|             conftest="""
 | |
|             import pytest
 | |
|             @pytest.hookimpl(hookwrapper=True)
 | |
|             def pytest_pycollect_makeitem(name):
 | |
|                 outcome = yield
 | |
|                 if name == "TestClass":
 | |
|                     item = outcome.get_result()
 | |
|                     item.extra_keyword_matches.add("xxx")
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run(p.dirpath(), "-s", "-k", keyword)
 | |
|         print("keyword", repr(keyword))
 | |
|         passed, skipped, failed = reprec.listoutcomes()
 | |
|         assert len(passed) == 1
 | |
|         assert passed[0].nodeid.endswith("test_2")
 | |
|         dlist = reprec.getcalls("pytest_deselected")
 | |
|         assert len(dlist) == 1
 | |
|         assert dlist[0].items[0].name == "test_1"
 | |
| 
 | |
|     def test_select_starton(self, testdir):
 | |
|         threepass = testdir.makepyfile(
 | |
|             test_threepass="""
 | |
|             def test_one(): assert 1
 | |
|             def test_two(): assert 1
 | |
|             def test_three(): assert 1
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run("-k", "test_two:", threepass)
 | |
|         passed, skipped, failed = reprec.listoutcomes()
 | |
|         assert len(passed) == 2
 | |
|         assert not failed
 | |
|         dlist = reprec.getcalls("pytest_deselected")
 | |
|         assert len(dlist) == 1
 | |
|         item = dlist[0].items[0]
 | |
|         assert item.name == "test_one"
 | |
| 
 | |
|     def test_keyword_extra(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|            def test_one():
 | |
|                assert 0
 | |
|            test_one.mykeyword = True
 | |
|         """
 | |
|         )
 | |
|         reprec = testdir.inline_run("-k", "mykeyword", p)
 | |
|         passed, skipped, failed = reprec.countoutcomes()
 | |
|         assert failed == 1
 | |
| 
 | |
|     @pytest.mark.xfail
 | |
|     def test_keyword_extra_dash(self, testdir):
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|            def test_one():
 | |
|                assert 0
 | |
|            test_one.mykeyword = True
 | |
|         """
 | |
|         )
 | |
|         # with argparse the argument to an option cannot
 | |
|         # start with '-'
 | |
|         reprec = testdir.inline_run("-k", "-mykeyword", p)
 | |
|         passed, skipped, failed = reprec.countoutcomes()
 | |
|         assert passed + skipped + failed == 0
 | |
| 
 | |
|     def test_no_magic_values(self, testdir):
 | |
|         """Make sure the tests do not match on magic values,
 | |
|         no double underscored values, like '__dict__',
 | |
|         and no instance values, like '()'.
 | |
|         """
 | |
|         p = testdir.makepyfile(
 | |
|             """
 | |
|             def test_one(): assert 1
 | |
|         """
 | |
|         )
 | |
| 
 | |
|         def assert_test_is_not_selected(keyword):
 | |
|             reprec = testdir.inline_run("-k", keyword, p)
 | |
|             passed, skipped, failed = reprec.countoutcomes()
 | |
|             dlist = reprec.getcalls("pytest_deselected")
 | |
|             assert passed + skipped + failed == 0
 | |
|             deselected_tests = dlist[0].items
 | |
|             assert len(deselected_tests) == 1
 | |
| 
 | |
|         assert_test_is_not_selected("__")
 | |
|         assert_test_is_not_selected("()")
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "argval, expected",
 | |
|     [
 | |
|         (
 | |
|             pytest.mark.skip()((1, 2)),
 | |
|             ParameterSet(values=(1, 2), marks=[pytest.mark.skip], id=None),
 | |
|         ),
 | |
|         (
 | |
|             pytest.mark.xfail(pytest.mark.skip()((1, 2))),
 | |
|             ParameterSet(
 | |
|                 values=(1, 2), marks=[pytest.mark.xfail, pytest.mark.skip], id=None
 | |
|             ),
 | |
|         ),
 | |
|     ],
 | |
| )
 | |
| @pytest.mark.filterwarnings("default")
 | |
| def test_parameterset_extractfrom(argval, expected):
 | |
|     from _pytest.deprecated import MARK_PARAMETERSET_UNPACKING
 | |
| 
 | |
|     warn_called = []
 | |
| 
 | |
|     class DummyItem:
 | |
|         def warn(self, warning):
 | |
|             warn_called.append(warning)
 | |
| 
 | |
|     extracted = ParameterSet.extract_from(argval, belonging_definition=DummyItem())
 | |
|     assert extracted == expected
 | |
|     assert warn_called == [MARK_PARAMETERSET_UNPACKING]
 | |
| 
 | |
| 
 | |
| def test_legacy_transfer():
 | |
|     class FakeModule(object):
 | |
|         pytestmark = []
 | |
| 
 | |
|     class FakeClass(object):
 | |
|         pytestmark = pytest.mark.nofun
 | |
| 
 | |
|     @pytest.mark.fun
 | |
|     def fake_method(self):
 | |
|         pass
 | |
| 
 | |
|     transfer_markers(fake_method, FakeClass, FakeModule)
 | |
| 
 | |
|     # legacy marks transfer smeared
 | |
|     assert fake_method.nofun
 | |
|     assert fake_method.fun
 | |
|     # pristine marks dont transfer
 | |
|     assert fake_method.pytestmark == [pytest.mark.fun.mark]
 | |
| 
 | |
| 
 | |
| class TestMarkDecorator(object):
 | |
|     @pytest.mark.parametrize(
 | |
|         "lhs, rhs, expected",
 | |
|         [
 | |
|             (pytest.mark.foo(), pytest.mark.foo(), True),
 | |
|             (pytest.mark.foo(), pytest.mark.bar(), False),
 | |
|             (pytest.mark.foo(), "bar", False),
 | |
|             ("foo", pytest.mark.bar(), False),
 | |
|         ],
 | |
|     )
 | |
|     def test__eq__(self, lhs, rhs, expected):
 | |
|         assert (lhs == rhs) == expected
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("mark", [None, "", "skip", "xfail"])
 | |
| def test_parameterset_for_parametrize_marks(testdir, mark):
 | |
|     if mark is not None:
 | |
|         testdir.makeini(
 | |
|             """
 | |
|         [pytest]
 | |
|         {}={}
 | |
|         """.format(
 | |
|                 EMPTY_PARAMETERSET_OPTION, mark
 | |
|             )
 | |
|         )
 | |
| 
 | |
|     config = testdir.parseconfig()
 | |
|     from _pytest.mark import pytest_configure, get_empty_parameterset_mark
 | |
| 
 | |
|     pytest_configure(config)
 | |
|     result_mark = get_empty_parameterset_mark(config, ["a"], all)
 | |
|     if mark in (None, ""):
 | |
|         # normalize to the requested name
 | |
|         mark = "skip"
 | |
|     assert result_mark.name == mark
 | |
|     assert result_mark.kwargs["reason"].startswith("got empty parameter set ")
 | |
|     if mark == "xfail":
 | |
|         assert result_mark.kwargs.get("run") is False
 | |
| 
 | |
| 
 | |
| def test_parameterset_for_fail_at_collect(testdir):
 | |
|     testdir.makeini(
 | |
|         """
 | |
|     [pytest]
 | |
|     {}=fail_at_collect
 | |
|     """.format(
 | |
|             EMPTY_PARAMETERSET_OPTION
 | |
|         )
 | |
|     )
 | |
| 
 | |
|     config = testdir.parseconfig()
 | |
|     from _pytest.mark import pytest_configure, get_empty_parameterset_mark
 | |
|     from _pytest.compat import getfslineno
 | |
| 
 | |
|     pytest_configure(config)
 | |
| 
 | |
|     test_func = all
 | |
|     func_name = test_func.__name__
 | |
|     _, func_lineno = getfslineno(test_func)
 | |
|     expected_errmsg = r"Empty parameter set in '%s' at line %d" % (
 | |
|         func_name,
 | |
|         func_lineno,
 | |
|     )
 | |
| 
 | |
|     with pytest.raises(Collector.CollectError, match=expected_errmsg):
 | |
|         get_empty_parameterset_mark(config, ["a"], test_func)
 | |
| 
 | |
| 
 | |
| def test_parameterset_for_parametrize_bad_markname(testdir):
 | |
|     with pytest.raises(pytest.UsageError):
 | |
|         test_parameterset_for_parametrize_marks(testdir, "bad")
 | |
| 
 | |
| 
 | |
| def test_mark_expressions_no_smear(testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
| 
 | |
|         class BaseTests(object):
 | |
|             def test_something(self):
 | |
|                 pass
 | |
| 
 | |
|         @pytest.mark.FOO
 | |
|         class TestFooClass(BaseTests):
 | |
|             pass
 | |
| 
 | |
|         @pytest.mark.BAR
 | |
|         class TestBarClass(BaseTests):
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     reprec = testdir.inline_run("-m", "FOO")
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     dlist = reprec.getcalls("pytest_deselected")
 | |
|     assert passed == 1
 | |
|     assert skipped == failed == 0
 | |
|     deselected_tests = dlist[0].items
 | |
|     assert len(deselected_tests) == 1
 | |
| 
 | |
|     # keywords smear - expected behaviour
 | |
|     reprec_keywords = testdir.inline_run("-k", "FOO")
 | |
|     passed_k, skipped_k, failed_k = reprec_keywords.countoutcomes()
 | |
|     assert passed_k == 2
 | |
|     assert skipped_k == failed_k == 0
 | |
| 
 | |
| 
 | |
| def test_addmarker_getmarker():
 | |
|     node = Node("Test", config=mock.Mock(), session=mock.Mock(), nodeid="Test")
 | |
|     node.add_marker(pytest.mark.a(1))
 | |
|     node.add_marker("b")
 | |
|     node.get_marker("a").combined
 | |
|     node.get_marker("b").combined
 | |
| 
 | |
| 
 | |
| def test_addmarker_order():
 | |
|     node = Node("Test", config=mock.Mock(), session=mock.Mock(), nodeid="Test")
 | |
|     node.add_marker("a")
 | |
|     node.add_marker("b")
 | |
|     node.add_marker("c", append=False)
 | |
|     extracted = [x.name for x in node.iter_markers()]
 | |
|     assert extracted == ["c", "a", "b"]
 | |
| 
 | |
| 
 | |
| @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/3605")
 | |
| @pytest.mark.filterwarnings("ignore")
 | |
| def test_markers_from_parametrize(testdir):
 | |
|     testdir.makepyfile(
 | |
|         """
 | |
|         from __future__ import print_function
 | |
|         import pytest
 | |
| 
 | |
|         first_custom_mark = pytest.mark.custom_marker
 | |
|         custom_mark = pytest.mark.custom_mark
 | |
|         @pytest.fixture(autouse=True)
 | |
|         def trigger(request):
 | |
|             custom_mark =request.node.get_marker('custom_mark')
 | |
|             print("Custom mark %s" % custom_mark)
 | |
| 
 | |
|         @custom_mark("custom mark non parametrized")
 | |
|         def test_custom_mark_non_parametrized():
 | |
|             print("Hey from test")
 | |
| 
 | |
|         @pytest.mark.parametrize(
 | |
|             "obj_type",
 | |
|             [
 | |
|                 first_custom_mark("first custom mark")("template"),
 | |
|                 pytest.param( # Think this should be recommended way?
 | |
|                     "disk",
 | |
|                     marks=custom_mark('custom mark1')
 | |
|                 ),
 | |
|                 custom_mark("custom mark2")("vm"),  # Tried also this
 | |
|             ]
 | |
|         )
 | |
|         def test_custom_mark_parametrized(obj_type):
 | |
|             print("obj_type is:", obj_type)
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     result = testdir.runpytest()
 | |
|     result.assert_outcomes(passed=4)
 |