| from __future__ import absolute_import, division, print_function |
| import os |
| import sys |
| import mock |
| import pytest |
| from _pytest.mark import ( |
| MarkGenerator as Mark, |
| ParameterSet, |
| transfer_markers, |
| EMPTY_PARAMETERSET_OPTION, |
| ) |
| from _pytest.nodes import Node |
| |
| ignore_markinfo = pytest.mark.filterwarnings( |
| "ignore:MarkInfo objects:_pytest.deprecated.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 |
| |
| @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_subprocess("--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*registered*"]) |
| |
| |
| @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_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("ignore") |
| def test_parameterset_extractfrom(argval, expected): |
| extracted = ParameterSet.extract_from(argval) |
| assert extracted == expected |
| |
| |
| 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]\n{}={}".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_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 |