1# -*- coding: utf-8 -*- 2import re 3import sys 4import attr 5import _pytest._code 6import py 7import pytest 8from _pytest import python, fixtures 9 10import hypothesis 11from hypothesis import strategies 12 13PY3 = sys.version_info >= (3, 0) 14 15 16class TestMetafunc(object): 17 18 def Metafunc(self, func, config=None): 19 # the unit tests of this class check if things work correctly 20 # on the funcarg level, so we don't need a full blown 21 # initiliazation 22 class FixtureInfo(object): 23 name2fixturedefs = None 24 25 def __init__(self, names): 26 self.names_closure = names 27 28 @attr.s 29 class DefinitionMock(object): 30 obj = attr.ib() 31 32 names = fixtures.getfuncargnames(func) 33 fixtureinfo = FixtureInfo(names) 34 definition = DefinitionMock(func) 35 return python.Metafunc(definition, fixtureinfo, config) 36 37 def test_no_funcargs(self, testdir): 38 39 def function(): 40 pass 41 42 metafunc = self.Metafunc(function) 43 assert not metafunc.fixturenames 44 repr(metafunc._calls) 45 46 def test_function_basic(self): 47 48 def func(arg1, arg2="qwe"): 49 pass 50 51 metafunc = self.Metafunc(func) 52 assert len(metafunc.fixturenames) == 1 53 assert "arg1" in metafunc.fixturenames 54 assert metafunc.function is func 55 assert metafunc.cls is None 56 57 def test_addcall_no_args(self): 58 59 def func(arg1): 60 pass 61 62 metafunc = self.Metafunc(func) 63 metafunc.addcall() 64 assert len(metafunc._calls) == 1 65 call = metafunc._calls[0] 66 assert call.id == "0" 67 assert not hasattr(call, "param") 68 69 def test_addcall_id(self): 70 71 def func(arg1): 72 pass 73 74 metafunc = self.Metafunc(func) 75 pytest.raises(ValueError, "metafunc.addcall(id=None)") 76 77 metafunc.addcall(id=1) 78 pytest.raises(ValueError, "metafunc.addcall(id=1)") 79 pytest.raises(ValueError, "metafunc.addcall(id='1')") 80 metafunc.addcall(id=2) 81 assert len(metafunc._calls) == 2 82 assert metafunc._calls[0].id == "1" 83 assert metafunc._calls[1].id == "2" 84 85 def test_addcall_param(self): 86 87 def func(arg1): 88 pass 89 90 metafunc = self.Metafunc(func) 91 92 class obj(object): 93 pass 94 95 metafunc.addcall(param=obj) 96 metafunc.addcall(param=obj) 97 metafunc.addcall(param=1) 98 assert len(metafunc._calls) == 3 99 assert metafunc._calls[0].getparam("arg1") == obj 100 assert metafunc._calls[1].getparam("arg1") == obj 101 assert metafunc._calls[2].getparam("arg1") == 1 102 103 def test_addcall_funcargs(self): 104 105 def func(x): 106 pass 107 108 metafunc = self.Metafunc(func) 109 110 class obj(object): 111 pass 112 113 metafunc.addcall(funcargs={"x": 2}) 114 metafunc.addcall(funcargs={"x": 3}) 115 pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})") 116 assert len(metafunc._calls) == 2 117 assert metafunc._calls[0].funcargs == {"x": 2} 118 assert metafunc._calls[1].funcargs == {"x": 3} 119 assert not hasattr(metafunc._calls[1], "param") 120 121 def test_parametrize_error(self): 122 123 def func(x, y): 124 pass 125 126 metafunc = self.Metafunc(func) 127 metafunc.parametrize("x", [1, 2]) 128 pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) 129 pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) 130 metafunc.parametrize("y", [1, 2]) 131 pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) 132 pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) 133 134 def test_parametrize_bad_scope(self, testdir): 135 136 def func(x): 137 pass 138 139 metafunc = self.Metafunc(func) 140 try: 141 metafunc.parametrize("x", [1], scope="doggy") 142 except ValueError as ve: 143 assert "has an unsupported scope value 'doggy'" in str(ve) 144 145 def test_parametrize_and_id(self): 146 147 def func(x, y): 148 pass 149 150 metafunc = self.Metafunc(func) 151 152 metafunc.parametrize("x", [1, 2], ids=["basic", "advanced"]) 153 metafunc.parametrize("y", ["abc", "def"]) 154 ids = [x.id for x in metafunc._calls] 155 assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"] 156 157 def test_parametrize_and_id_unicode(self): 158 """Allow unicode strings for "ids" parameter in Python 2 (##1905)""" 159 160 def func(x): 161 pass 162 163 metafunc = self.Metafunc(func) 164 metafunc.parametrize("x", [1, 2], ids=[u"basic", u"advanced"]) 165 ids = [x.id for x in metafunc._calls] 166 assert ids == [u"basic", u"advanced"] 167 168 def test_parametrize_with_wrong_number_of_ids(self, testdir): 169 170 def func(x, y): 171 pass 172 173 metafunc = self.Metafunc(func) 174 175 pytest.raises( 176 ValueError, lambda: metafunc.parametrize("x", [1, 2], ids=["basic"]) 177 ) 178 179 pytest.raises( 180 ValueError, 181 lambda: metafunc.parametrize( 182 ("x", "y"), [("abc", "def"), ("ghi", "jkl")], ids=["one"] 183 ), 184 ) 185 186 @pytest.mark.issue510 187 def test_parametrize_empty_list(self): 188 189 def func(y): 190 pass 191 192 class MockConfig(object): 193 194 def getini(self, name): 195 return "" 196 197 @property 198 def hook(self): 199 return self 200 201 def pytest_make_parametrize_id(self, **kw): 202 pass 203 204 metafunc = self.Metafunc(func, MockConfig()) 205 metafunc.parametrize("y", []) 206 assert "skip" == metafunc._calls[0].marks[0].name 207 208 def test_parametrize_with_userobjects(self): 209 210 def func(x, y): 211 pass 212 213 metafunc = self.Metafunc(func) 214 215 class A(object): 216 pass 217 218 metafunc.parametrize("x", [A(), A()]) 219 metafunc.parametrize("y", list("ab")) 220 assert metafunc._calls[0].id == "x0-a" 221 assert metafunc._calls[1].id == "x0-b" 222 assert metafunc._calls[2].id == "x1-a" 223 assert metafunc._calls[3].id == "x1-b" 224 225 @hypothesis.given(strategies.text() | strategies.binary()) 226 @hypothesis.settings( 227 deadline=400.0 228 ) # very close to std deadline and CI boxes are not reliable in CPU power 229 def test_idval_hypothesis(self, value): 230 from _pytest.python import _idval 231 232 escaped = _idval(value, "a", 6, None) 233 assert isinstance(escaped, str) 234 if PY3: 235 escaped.encode("ascii") 236 else: 237 escaped.decode("ascii") 238 239 def test_unicode_idval(self): 240 """This tests that Unicode strings outside the ASCII character set get 241 escaped, using byte escapes if they're in that range or unicode 242 escapes if they're not. 243 244 """ 245 from _pytest.python import _idval 246 247 values = [ 248 (u"", ""), 249 (u"ascii", "ascii"), 250 (u"ação", "a\\xe7\\xe3o"), 251 (u"josé@blah.com", "jos\\xe9@blah.com"), 252 ( 253 u"δοκ.ιμή@παράδειγμα.δοκιμή", 254 "\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3" 255 "\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae", 256 ), 257 ] 258 for val, expected in values: 259 assert _idval(val, "a", 6, None) == expected 260 261 def test_bytes_idval(self): 262 """unittest for the expected behavior to obtain ids for parametrized 263 bytes values: 264 - python2: non-ascii strings are considered bytes and formatted using 265 "binary escape", where any byte < 127 is escaped into its hex form. 266 - python3: bytes objects are always escaped using "binary escape". 267 """ 268 from _pytest.python import _idval 269 270 values = [ 271 (b"", ""), 272 (b"\xc3\xb4\xff\xe4", "\\xc3\\xb4\\xff\\xe4"), 273 (b"ascii", "ascii"), 274 (u"αρά".encode("utf-8"), "\\xce\\xb1\\xcf\\x81\\xce\\xac"), 275 ] 276 for val, expected in values: 277 assert _idval(val, "a", 6, None) == expected 278 279 def test_class_or_function_idval(self): 280 """unittest for the expected behavior to obtain ids for parametrized 281 values that are classes or functions: their __name__. 282 """ 283 from _pytest.python import _idval 284 285 class TestClass(object): 286 pass 287 288 def test_function(): 289 pass 290 291 values = [(TestClass, "TestClass"), (test_function, "test_function")] 292 for val, expected in values: 293 assert _idval(val, "a", 6, None) == expected 294 295 @pytest.mark.issue250 296 def test_idmaker_autoname(self): 297 from _pytest.python import idmaker 298 299 result = idmaker( 300 ("a", "b"), [pytest.param("string", 1.0), pytest.param("st-ring", 2.0)] 301 ) 302 assert result == ["string-1.0", "st-ring-2.0"] 303 304 result = idmaker( 305 ("a", "b"), [pytest.param(object(), 1.0), pytest.param(object(), object())] 306 ) 307 assert result == ["a0-1.0", "a1-b1"] 308 # unicode mixing, issue250 309 result = idmaker( 310 (py.builtin._totext("a"), "b"), [pytest.param({}, b"\xc3\xb4")] 311 ) 312 assert result == ["a0-\\xc3\\xb4"] 313 314 def test_idmaker_with_bytes_regex(self): 315 from _pytest.python import idmaker 316 317 result = idmaker(("a"), [pytest.param(re.compile(b"foo"), 1.0)]) 318 assert result == ["foo"] 319 320 def test_idmaker_native_strings(self): 321 from _pytest.python import idmaker 322 323 totext = py.builtin._totext 324 result = idmaker( 325 ("a", "b"), 326 [ 327 pytest.param(1.0, -1.1), 328 pytest.param(2, -202), 329 pytest.param("three", "three hundred"), 330 pytest.param(True, False), 331 pytest.param(None, None), 332 pytest.param(re.compile("foo"), re.compile("bar")), 333 pytest.param(str, int), 334 pytest.param(list("six"), [66, 66]), 335 pytest.param({7}, set("seven")), 336 pytest.param(tuple("eight"), (8, -8, 8)), 337 pytest.param(b"\xc3\xb4", b"name"), 338 pytest.param(b"\xc3\xb4", totext("other")), 339 ], 340 ) 341 assert ( 342 result 343 == [ 344 "1.0--1.1", 345 "2--202", 346 "three-three hundred", 347 "True-False", 348 "None-None", 349 "foo-bar", 350 "str-int", 351 "a7-b7", 352 "a8-b8", 353 "a9-b9", 354 "\\xc3\\xb4-name", 355 "\\xc3\\xb4-other", 356 ] 357 ) 358 359 def test_idmaker_enum(self): 360 from _pytest.python import idmaker 361 362 enum = pytest.importorskip("enum") 363 e = enum.Enum("Foo", "one, two") 364 result = idmaker(("a", "b"), [pytest.param(e.one, e.two)]) 365 assert result == ["Foo.one-Foo.two"] 366 367 @pytest.mark.issue351 368 def test_idmaker_idfn(self): 369 from _pytest.python import idmaker 370 371 def ids(val): 372 if isinstance(val, Exception): 373 return repr(val) 374 375 result = idmaker( 376 ("a", "b"), 377 [ 378 pytest.param(10.0, IndexError()), 379 pytest.param(20, KeyError()), 380 pytest.param("three", [1, 2, 3]), 381 ], 382 idfn=ids, 383 ) 384 assert result == ["10.0-IndexError()", "20-KeyError()", "three-b2"] 385 386 @pytest.mark.issue351 387 def test_idmaker_idfn_unique_names(self): 388 from _pytest.python import idmaker 389 390 def ids(val): 391 return "a" 392 393 result = idmaker( 394 ("a", "b"), 395 [ 396 pytest.param(10.0, IndexError()), 397 pytest.param(20, KeyError()), 398 pytest.param("three", [1, 2, 3]), 399 ], 400 idfn=ids, 401 ) 402 assert result == ["a-a0", "a-a1", "a-a2"] 403 404 @pytest.mark.issue351 405 def test_idmaker_idfn_exception(self): 406 from _pytest.python import idmaker 407 from _pytest.recwarn import WarningsRecorder 408 409 class BadIdsException(Exception): 410 pass 411 412 def ids(val): 413 raise BadIdsException("ids raised") 414 415 rec = WarningsRecorder() 416 with rec: 417 idmaker( 418 ("a", "b"), 419 [ 420 pytest.param(10.0, IndexError()), 421 pytest.param(20, KeyError()), 422 pytest.param("three", [1, 2, 3]), 423 ], 424 idfn=ids, 425 ) 426 427 assert ( 428 [str(i.message) for i in rec.list] 429 == [ 430 "Raised while trying to determine id of parameter a at position 0." 431 "\nUpdate your code as this will raise an error in pytest-4.0.", 432 "Raised while trying to determine id of parameter b at position 0." 433 "\nUpdate your code as this will raise an error in pytest-4.0.", 434 "Raised while trying to determine id of parameter a at position 1." 435 "\nUpdate your code as this will raise an error in pytest-4.0.", 436 "Raised while trying to determine id of parameter b at position 1." 437 "\nUpdate your code as this will raise an error in pytest-4.0.", 438 "Raised while trying to determine id of parameter a at position 2." 439 "\nUpdate your code as this will raise an error in pytest-4.0.", 440 "Raised while trying to determine id of parameter b at position 2." 441 "\nUpdate your code as this will raise an error in pytest-4.0.", 442 ] 443 ) 444 445 def test_parametrize_ids_exception(self, testdir): 446 """ 447 :param testdir: the instance of Testdir class, a temporary 448 test directory. 449 """ 450 testdir.makepyfile( 451 """ 452 import pytest 453 454 def ids(arg): 455 raise Exception("bad ids") 456 457 @pytest.mark.parametrize("arg", ["a", "b"], ids=ids) 458 def test_foo(arg): 459 pass 460 """ 461 ) 462 with pytest.warns(DeprecationWarning): 463 result = testdir.runpytest("--collect-only") 464 result.stdout.fnmatch_lines( 465 [ 466 "<Module 'test_parametrize_ids_exception.py'>", 467 " <Function 'test_foo[a]'>", 468 " <Function 'test_foo[b]'>", 469 ] 470 ) 471 472 def test_idmaker_with_ids(self): 473 from _pytest.python import idmaker 474 475 result = idmaker( 476 ("a", "b"), [pytest.param(1, 2), pytest.param(3, 4)], ids=["a", None] 477 ) 478 assert result == ["a", "3-4"] 479 480 def test_idmaker_with_paramset_id(self): 481 from _pytest.python import idmaker 482 483 result = idmaker( 484 ("a", "b"), 485 [pytest.param(1, 2, id="me"), pytest.param(3, 4, id="you")], 486 ids=["a", None], 487 ) 488 assert result == ["me", "you"] 489 490 def test_idmaker_with_ids_unique_names(self): 491 from _pytest.python import idmaker 492 493 result = idmaker( 494 ("a"), map(pytest.param, [1, 2, 3, 4, 5]), ids=["a", "a", "b", "c", "b"] 495 ) 496 assert result == ["a0", "a1", "b0", "c", "b1"] 497 498 def test_addcall_and_parametrize(self): 499 500 def func(x, y): 501 pass 502 503 metafunc = self.Metafunc(func) 504 metafunc.addcall({"x": 1}) 505 metafunc.parametrize("y", [2, 3]) 506 assert len(metafunc._calls) == 2 507 assert metafunc._calls[0].funcargs == {"x": 1, "y": 2} 508 assert metafunc._calls[1].funcargs == {"x": 1, "y": 3} 509 assert metafunc._calls[0].id == "0-2" 510 assert metafunc._calls[1].id == "0-3" 511 512 @pytest.mark.issue714 513 def test_parametrize_indirect(self): 514 515 def func(x, y): 516 pass 517 518 metafunc = self.Metafunc(func) 519 metafunc.parametrize("x", [1], indirect=True) 520 metafunc.parametrize("y", [2, 3], indirect=True) 521 assert len(metafunc._calls) == 2 522 assert metafunc._calls[0].funcargs == {} 523 assert metafunc._calls[1].funcargs == {} 524 assert metafunc._calls[0].params == dict(x=1, y=2) 525 assert metafunc._calls[1].params == dict(x=1, y=3) 526 527 @pytest.mark.issue714 528 def test_parametrize_indirect_list(self): 529 530 def func(x, y): 531 pass 532 533 metafunc = self.Metafunc(func) 534 metafunc.parametrize("x, y", [("a", "b")], indirect=["x"]) 535 assert metafunc._calls[0].funcargs == dict(y="b") 536 assert metafunc._calls[0].params == dict(x="a") 537 538 @pytest.mark.issue714 539 def test_parametrize_indirect_list_all(self): 540 541 def func(x, y): 542 pass 543 544 metafunc = self.Metafunc(func) 545 metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "y"]) 546 assert metafunc._calls[0].funcargs == {} 547 assert metafunc._calls[0].params == dict(x="a", y="b") 548 549 @pytest.mark.issue714 550 def test_parametrize_indirect_list_empty(self): 551 552 def func(x, y): 553 pass 554 555 metafunc = self.Metafunc(func) 556 metafunc.parametrize("x, y", [("a", "b")], indirect=[]) 557 assert metafunc._calls[0].funcargs == dict(x="a", y="b") 558 assert metafunc._calls[0].params == {} 559 560 @pytest.mark.issue714 561 def test_parametrize_indirect_list_functional(self, testdir): 562 """ 563 Test parametrization with 'indirect' parameter applied on 564 particular arguments. As y is is direct, its value should 565 be used directly rather than being passed to the fixture 566 y. 567 568 :param testdir: the instance of Testdir class, a temporary 569 test directory. 570 """ 571 testdir.makepyfile( 572 """ 573 import pytest 574 @pytest.fixture(scope='function') 575 def x(request): 576 return request.param * 3 577 @pytest.fixture(scope='function') 578 def y(request): 579 return request.param * 2 580 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x']) 581 def test_simple(x,y): 582 assert len(x) == 3 583 assert len(y) == 1 584 """ 585 ) 586 result = testdir.runpytest("-v") 587 result.stdout.fnmatch_lines(["*test_simple*a-b*", "*1 passed*"]) 588 589 @pytest.mark.issue714 590 def test_parametrize_indirect_list_error(self, testdir): 591 592 def func(x, y): 593 pass 594 595 metafunc = self.Metafunc(func) 596 with pytest.raises(ValueError): 597 metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "z"]) 598 599 @pytest.mark.issue714 600 def test_parametrize_uses_no_fixture_error_indirect_false(self, testdir): 601 """The 'uses no fixture' error tells the user at collection time 602 that the parametrize data they've set up doesn't correspond to the 603 fixtures in their test function, rather than silently ignoring this 604 and letting the test potentially pass. 605 """ 606 testdir.makepyfile( 607 """ 608 import pytest 609 610 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=False) 611 def test_simple(x): 612 assert len(x) == 3 613 """ 614 ) 615 result = testdir.runpytest("--collect-only") 616 result.stdout.fnmatch_lines(["*uses no argument 'y'*"]) 617 618 @pytest.mark.issue714 619 def test_parametrize_uses_no_fixture_error_indirect_true(self, testdir): 620 testdir.makepyfile( 621 """ 622 import pytest 623 @pytest.fixture(scope='function') 624 def x(request): 625 return request.param * 3 626 @pytest.fixture(scope='function') 627 def y(request): 628 return request.param * 2 629 630 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=True) 631 def test_simple(x): 632 assert len(x) == 3 633 """ 634 ) 635 result = testdir.runpytest("--collect-only") 636 result.stdout.fnmatch_lines(["*uses no fixture 'y'*"]) 637 638 @pytest.mark.issue714 639 def test_parametrize_indirect_uses_no_fixture_error_indirect_string(self, testdir): 640 testdir.makepyfile( 641 """ 642 import pytest 643 @pytest.fixture(scope='function') 644 def x(request): 645 return request.param * 3 646 647 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect='y') 648 def test_simple(x): 649 assert len(x) == 3 650 """ 651 ) 652 result = testdir.runpytest("--collect-only") 653 result.stdout.fnmatch_lines(["*uses no fixture 'y'*"]) 654 655 @pytest.mark.issue714 656 def test_parametrize_indirect_uses_no_fixture_error_indirect_list(self, testdir): 657 testdir.makepyfile( 658 """ 659 import pytest 660 @pytest.fixture(scope='function') 661 def x(request): 662 return request.param * 3 663 664 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['y']) 665 def test_simple(x): 666 assert len(x) == 3 667 """ 668 ) 669 result = testdir.runpytest("--collect-only") 670 result.stdout.fnmatch_lines(["*uses no fixture 'y'*"]) 671 672 @pytest.mark.issue714 673 def test_parametrize_argument_not_in_indirect_list(self, testdir): 674 testdir.makepyfile( 675 """ 676 import pytest 677 @pytest.fixture(scope='function') 678 def x(request): 679 return request.param * 3 680 681 @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x']) 682 def test_simple(x): 683 assert len(x) == 3 684 """ 685 ) 686 result = testdir.runpytest("--collect-only") 687 result.stdout.fnmatch_lines(["*uses no argument 'y'*"]) 688 689 def test_parametrize_gives_indicative_error_on_function_with_default_argument( 690 self, testdir 691 ): 692 testdir.makepyfile( 693 """ 694 import pytest 695 696 @pytest.mark.parametrize('x, y', [('a', 'b')]) 697 def test_simple(x, y=1): 698 assert len(x) == 1 699 """ 700 ) 701 result = testdir.runpytest("--collect-only") 702 result.stdout.fnmatch_lines( 703 ["*already takes an argument 'y' with a default value"] 704 ) 705 706 def test_addcalls_and_parametrize_indirect(self): 707 708 def func(x, y): 709 pass 710 711 metafunc = self.Metafunc(func) 712 metafunc.addcall(param="123") 713 metafunc.parametrize("x", [1], indirect=True) 714 metafunc.parametrize("y", [2, 3], indirect=True) 715 assert len(metafunc._calls) == 2 716 assert metafunc._calls[0].funcargs == {} 717 assert metafunc._calls[1].funcargs == {} 718 assert metafunc._calls[0].params == dict(x=1, y=2) 719 assert metafunc._calls[1].params == dict(x=1, y=3) 720 721 def test_parametrize_functional(self, testdir): 722 testdir.makepyfile( 723 """ 724 import pytest 725 def pytest_generate_tests(metafunc): 726 metafunc.parametrize('x', [1,2], indirect=True) 727 metafunc.parametrize('y', [2]) 728 @pytest.fixture 729 def x(request): 730 return request.param * 10 731 732 def test_simple(x,y): 733 assert x in (10,20) 734 assert y == 2 735 """ 736 ) 737 result = testdir.runpytest("-v") 738 result.stdout.fnmatch_lines( 739 ["*test_simple*1-2*", "*test_simple*2-2*", "*2 passed*"] 740 ) 741 742 def test_parametrize_onearg(self): 743 metafunc = self.Metafunc(lambda x: None) 744 metafunc.parametrize("x", [1, 2]) 745 assert len(metafunc._calls) == 2 746 assert metafunc._calls[0].funcargs == dict(x=1) 747 assert metafunc._calls[0].id == "1" 748 assert metafunc._calls[1].funcargs == dict(x=2) 749 assert metafunc._calls[1].id == "2" 750 751 def test_parametrize_onearg_indirect(self): 752 metafunc = self.Metafunc(lambda x: None) 753 metafunc.parametrize("x", [1, 2], indirect=True) 754 assert metafunc._calls[0].params == dict(x=1) 755 assert metafunc._calls[0].id == "1" 756 assert metafunc._calls[1].params == dict(x=2) 757 assert metafunc._calls[1].id == "2" 758 759 def test_parametrize_twoargs(self): 760 metafunc = self.Metafunc(lambda x, y: None) 761 metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)]) 762 assert len(metafunc._calls) == 2 763 assert metafunc._calls[0].funcargs == dict(x=1, y=2) 764 assert metafunc._calls[0].id == "1-2" 765 assert metafunc._calls[1].funcargs == dict(x=3, y=4) 766 assert metafunc._calls[1].id == "3-4" 767 768 def test_parametrize_multiple_times(self, testdir): 769 testdir.makepyfile( 770 """ 771 import pytest 772 pytestmark = pytest.mark.parametrize("x", [1,2]) 773 def test_func(x): 774 assert 0, x 775 class TestClass(object): 776 pytestmark = pytest.mark.parametrize("y", [3,4]) 777 def test_meth(self, x, y): 778 assert 0, x 779 """ 780 ) 781 result = testdir.runpytest() 782 assert result.ret == 1 783 result.assert_outcomes(failed=6) 784 785 def test_parametrize_CSV(self, testdir): 786 testdir.makepyfile( 787 """ 788 import pytest 789 @pytest.mark.parametrize("x, y,", [(1,2), (2,3)]) 790 def test_func(x, y): 791 assert x+1 == y 792 """ 793 ) 794 reprec = testdir.inline_run() 795 reprec.assertoutcome(passed=2) 796 797 def test_parametrize_class_scenarios(self, testdir): 798 testdir.makepyfile( 799 """ 800 # same as doc/en/example/parametrize scenario example 801 def pytest_generate_tests(metafunc): 802 idlist = [] 803 argvalues = [] 804 for scenario in metafunc.cls.scenarios: 805 idlist.append(scenario[0]) 806 items = scenario[1].items() 807 argnames = [x[0] for x in items] 808 argvalues.append(([x[1] for x in items])) 809 metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class") 810 811 class Test(object): 812 scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}], 813 ['2', {'arg':'value2', "arg2": "value2"}]] 814 815 def test_1(self, arg, arg2): 816 pass 817 818 def test_2(self, arg2, arg): 819 pass 820 821 def test_3(self, arg, arg2): 822 pass 823 """ 824 ) 825 result = testdir.runpytest("-v") 826 assert result.ret == 0 827 result.stdout.fnmatch_lines( 828 """ 829 *test_1*1* 830 *test_2*1* 831 *test_3*1* 832 *test_1*2* 833 *test_2*2* 834 *test_3*2* 835 *6 passed* 836 """ 837 ) 838 839 def test_format_args(self): 840 841 def function1(): 842 pass 843 844 assert fixtures._format_args(function1) == "()" 845 846 def function2(arg1): 847 pass 848 849 assert fixtures._format_args(function2) == "(arg1)" 850 851 def function3(arg1, arg2="qwe"): 852 pass 853 854 assert fixtures._format_args(function3) == "(arg1, arg2='qwe')" 855 856 def function4(arg1, *args, **kwargs): 857 pass 858 859 assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)" 860 861 862class TestMetafuncFunctional(object): 863 864 def test_attributes(self, testdir): 865 p = testdir.makepyfile( 866 """ 867 # assumes that generate/provide runs in the same process 868 import sys, pytest 869 def pytest_generate_tests(metafunc): 870 metafunc.addcall(param=metafunc) 871 872 @pytest.fixture 873 def metafunc(request): 874 assert request._pyfuncitem._genid == "0" 875 return request.param 876 877 def test_function(metafunc, pytestconfig): 878 assert metafunc.config == pytestconfig 879 assert metafunc.module.__name__ == __name__ 880 assert metafunc.function == test_function 881 assert metafunc.cls is None 882 883 class TestClass(object): 884 def test_method(self, metafunc, pytestconfig): 885 assert metafunc.config == pytestconfig 886 assert metafunc.module.__name__ == __name__ 887 if sys.version_info > (3, 0): 888 unbound = TestClass.test_method 889 else: 890 unbound = TestClass.test_method.im_func 891 # XXX actually have an unbound test function here? 892 assert metafunc.function == unbound 893 assert metafunc.cls == TestClass 894 """ 895 ) 896 result = testdir.runpytest(p, "-v") 897 result.assert_outcomes(passed=2) 898 899 def test_addcall_with_two_funcargs_generators(self, testdir): 900 testdir.makeconftest( 901 """ 902 def pytest_generate_tests(metafunc): 903 assert "arg1" in metafunc.fixturenames 904 metafunc.addcall(funcargs=dict(arg1=1, arg2=2)) 905 """ 906 ) 907 p = testdir.makepyfile( 908 """ 909 def pytest_generate_tests(metafunc): 910 metafunc.addcall(funcargs=dict(arg1=1, arg2=1)) 911 912 class TestClass(object): 913 def test_myfunc(self, arg1, arg2): 914 assert arg1 == arg2 915 """ 916 ) 917 result = testdir.runpytest("-v", p) 918 result.stdout.fnmatch_lines( 919 ["*test_myfunc*0*PASS*", "*test_myfunc*1*FAIL*", "*1 failed, 1 passed*"] 920 ) 921 922 def test_two_functions(self, testdir): 923 p = testdir.makepyfile( 924 """ 925 def pytest_generate_tests(metafunc): 926 metafunc.addcall(param=10) 927 metafunc.addcall(param=20) 928 929 import pytest 930 @pytest.fixture 931 def arg1(request): 932 return request.param 933 934 def test_func1(arg1): 935 assert arg1 == 10 936 def test_func2(arg1): 937 assert arg1 in (10, 20) 938 """ 939 ) 940 result = testdir.runpytest("-v", p) 941 result.stdout.fnmatch_lines( 942 [ 943 "*test_func1*0*PASS*", 944 "*test_func1*1*FAIL*", 945 "*test_func2*PASS*", 946 "*1 failed, 3 passed*", 947 ] 948 ) 949 950 def test_noself_in_method(self, testdir): 951 p = testdir.makepyfile( 952 """ 953 def pytest_generate_tests(metafunc): 954 assert 'xyz' not in metafunc.fixturenames 955 956 class TestHello(object): 957 def test_hello(xyz): 958 pass 959 """ 960 ) 961 result = testdir.runpytest(p) 962 result.assert_outcomes(passed=1) 963 964 def test_generate_plugin_and_module(self, testdir): 965 testdir.makeconftest( 966 """ 967 def pytest_generate_tests(metafunc): 968 assert "arg1" in metafunc.fixturenames 969 metafunc.addcall(id="world", param=(2,100)) 970 """ 971 ) 972 p = testdir.makepyfile( 973 """ 974 def pytest_generate_tests(metafunc): 975 metafunc.addcall(param=(1,1), id="hello") 976 977 import pytest 978 @pytest.fixture 979 def arg1(request): 980 return request.param[0] 981 @pytest.fixture 982 def arg2(request): 983 return request.param[1] 984 985 class TestClass(object): 986 def test_myfunc(self, arg1, arg2): 987 assert arg1 == arg2 988 """ 989 ) 990 result = testdir.runpytest("-v", p) 991 result.stdout.fnmatch_lines( 992 [ 993 "*test_myfunc*hello*PASS*", 994 "*test_myfunc*world*FAIL*", 995 "*1 failed, 1 passed*", 996 ] 997 ) 998 999 def test_generate_tests_in_class(self, testdir): 1000 p = testdir.makepyfile( 1001 """ 1002 class TestClass(object): 1003 def pytest_generate_tests(self, metafunc): 1004 metafunc.addcall(funcargs={'hello': 'world'}, id="hello") 1005 1006 def test_myfunc(self, hello): 1007 assert hello == "world" 1008 """ 1009 ) 1010 result = testdir.runpytest("-v", p) 1011 result.stdout.fnmatch_lines(["*test_myfunc*hello*PASS*", "*1 passed*"]) 1012 1013 def test_two_functions_not_same_instance(self, testdir): 1014 p = testdir.makepyfile( 1015 """ 1016 def pytest_generate_tests(metafunc): 1017 metafunc.addcall({'arg1': 10}) 1018 metafunc.addcall({'arg1': 20}) 1019 1020 class TestClass(object): 1021 def test_func(self, arg1): 1022 assert not hasattr(self, 'x') 1023 self.x = 1 1024 """ 1025 ) 1026 result = testdir.runpytest("-v", p) 1027 result.stdout.fnmatch_lines( 1028 ["*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*"] 1029 ) 1030 1031 def test_issue28_setup_method_in_generate_tests(self, testdir): 1032 p = testdir.makepyfile( 1033 """ 1034 def pytest_generate_tests(metafunc): 1035 metafunc.addcall({'arg1': 1}) 1036 1037 class TestClass(object): 1038 def test_method(self, arg1): 1039 assert arg1 == self.val 1040 def setup_method(self, func): 1041 self.val = 1 1042 """ 1043 ) 1044 result = testdir.runpytest(p) 1045 result.assert_outcomes(passed=1) 1046 1047 def test_parametrize_functional2(self, testdir): 1048 testdir.makepyfile( 1049 """ 1050 def pytest_generate_tests(metafunc): 1051 metafunc.parametrize("arg1", [1,2]) 1052 metafunc.parametrize("arg2", [4,5]) 1053 def test_hello(arg1, arg2): 1054 assert 0, (arg1, arg2) 1055 """ 1056 ) 1057 result = testdir.runpytest() 1058 result.stdout.fnmatch_lines( 1059 ["*(1, 4)*", "*(1, 5)*", "*(2, 4)*", "*(2, 5)*", "*4 failed*"] 1060 ) 1061 1062 def test_parametrize_and_inner_getfixturevalue(self, testdir): 1063 p = testdir.makepyfile( 1064 """ 1065 def pytest_generate_tests(metafunc): 1066 metafunc.parametrize("arg1", [1], indirect=True) 1067 metafunc.parametrize("arg2", [10], indirect=True) 1068 1069 import pytest 1070 @pytest.fixture 1071 def arg1(request): 1072 x = request.getfixturevalue("arg2") 1073 return x + request.param 1074 1075 @pytest.fixture 1076 def arg2(request): 1077 return request.param 1078 1079 def test_func1(arg1, arg2): 1080 assert arg1 == 11 1081 """ 1082 ) 1083 result = testdir.runpytest("-v", p) 1084 result.stdout.fnmatch_lines(["*test_func1*1*PASS*", "*1 passed*"]) 1085 1086 def test_parametrize_on_setup_arg(self, testdir): 1087 p = testdir.makepyfile( 1088 """ 1089 def pytest_generate_tests(metafunc): 1090 assert "arg1" in metafunc.fixturenames 1091 metafunc.parametrize("arg1", [1], indirect=True) 1092 1093 import pytest 1094 @pytest.fixture 1095 def arg1(request): 1096 return request.param 1097 1098 @pytest.fixture 1099 def arg2(request, arg1): 1100 return 10 * arg1 1101 1102 def test_func(arg2): 1103 assert arg2 == 10 1104 """ 1105 ) 1106 result = testdir.runpytest("-v", p) 1107 result.stdout.fnmatch_lines(["*test_func*1*PASS*", "*1 passed*"]) 1108 1109 def test_parametrize_with_ids(self, testdir): 1110 testdir.makeini( 1111 """ 1112 [pytest] 1113 console_output_style=classic 1114 """ 1115 ) 1116 testdir.makepyfile( 1117 """ 1118 import pytest 1119 def pytest_generate_tests(metafunc): 1120 metafunc.parametrize(("a", "b"), [(1,1), (1,2)], 1121 ids=["basic", "advanced"]) 1122 1123 def test_function(a, b): 1124 assert a == b 1125 """ 1126 ) 1127 result = testdir.runpytest("-v") 1128 assert result.ret == 1 1129 result.stdout.fnmatch_lines_random( 1130 ["*test_function*basic*PASSED", "*test_function*advanced*FAILED"] 1131 ) 1132 1133 def test_parametrize_without_ids(self, testdir): 1134 testdir.makepyfile( 1135 """ 1136 import pytest 1137 def pytest_generate_tests(metafunc): 1138 metafunc.parametrize(("a", "b"), 1139 [(1,object()), (1.3,object())]) 1140 1141 def test_function(a, b): 1142 assert 1 1143 """ 1144 ) 1145 result = testdir.runpytest("-v") 1146 result.stdout.fnmatch_lines( 1147 """ 1148 *test_function*1-b0* 1149 *test_function*1.3-b1* 1150 """ 1151 ) 1152 1153 def test_parametrize_with_None_in_ids(self, testdir): 1154 testdir.makepyfile( 1155 """ 1156 import pytest 1157 def pytest_generate_tests(metafunc): 1158 metafunc.parametrize(("a", "b"), [(1,1), (1,1), (1,2)], 1159 ids=["basic", None, "advanced"]) 1160 1161 def test_function(a, b): 1162 assert a == b 1163 """ 1164 ) 1165 result = testdir.runpytest("-v") 1166 assert result.ret == 1 1167 result.stdout.fnmatch_lines_random( 1168 [ 1169 "*test_function*basic*PASSED*", 1170 "*test_function*1-1*PASSED*", 1171 "*test_function*advanced*FAILED*", 1172 ] 1173 ) 1174 1175 def test_fixture_parametrized_empty_ids(self, testdir): 1176 """Fixtures parametrized with empty ids cause an internal error (#1849).""" 1177 testdir.makepyfile( 1178 """ 1179 import pytest 1180 1181 @pytest.fixture(scope="module", ids=[], params=[]) 1182 def temp(request): 1183 return request.param 1184 1185 def test_temp(temp): 1186 pass 1187 """ 1188 ) 1189 result = testdir.runpytest() 1190 result.stdout.fnmatch_lines(["* 1 skipped *"]) 1191 1192 def test_parametrized_empty_ids(self, testdir): 1193 """Tests parametrized with empty ids cause an internal error (#1849).""" 1194 testdir.makepyfile( 1195 """ 1196 import pytest 1197 1198 @pytest.mark.parametrize('temp', [], ids=list()) 1199 def test_temp(temp): 1200 pass 1201 """ 1202 ) 1203 result = testdir.runpytest() 1204 result.stdout.fnmatch_lines(["* 1 skipped *"]) 1205 1206 def test_parametrized_ids_invalid_type(self, testdir): 1207 """Tests parametrized with ids as non-strings (#1857).""" 1208 testdir.makepyfile( 1209 """ 1210 import pytest 1211 1212 @pytest.mark.parametrize("x, expected", [(10, 20), (40, 80)], ids=(None, 2)) 1213 def test_ids_numbers(x,expected): 1214 assert x * 2 == expected 1215 """ 1216 ) 1217 result = testdir.runpytest() 1218 result.stdout.fnmatch_lines( 1219 ["*ids must be list of strings, found: 2 (type: int)*"] 1220 ) 1221 1222 def test_parametrize_with_identical_ids_get_unique_names(self, testdir): 1223 testdir.makepyfile( 1224 """ 1225 import pytest 1226 def pytest_generate_tests(metafunc): 1227 metafunc.parametrize(("a", "b"), [(1,1), (1,2)], 1228 ids=["a", "a"]) 1229 1230 def test_function(a, b): 1231 assert a == b 1232 """ 1233 ) 1234 result = testdir.runpytest("-v") 1235 assert result.ret == 1 1236 result.stdout.fnmatch_lines_random( 1237 ["*test_function*a0*PASSED*", "*test_function*a1*FAILED*"] 1238 ) 1239 1240 @pytest.mark.parametrize(("scope", "length"), [("module", 2), ("function", 4)]) 1241 def test_parametrize_scope_overrides(self, testdir, scope, length): 1242 testdir.makepyfile( 1243 """ 1244 import pytest 1245 values = [] 1246 def pytest_generate_tests(metafunc): 1247 if "arg" in metafunc.funcargnames: 1248 metafunc.parametrize("arg", [1,2], indirect=True, 1249 scope=%r) 1250 @pytest.fixture 1251 def arg(request): 1252 values.append(request.param) 1253 return request.param 1254 def test_hello(arg): 1255 assert arg in (1,2) 1256 def test_world(arg): 1257 assert arg in (1,2) 1258 def test_checklength(): 1259 assert len(values) == %d 1260 """ 1261 % (scope, length) 1262 ) 1263 reprec = testdir.inline_run() 1264 reprec.assertoutcome(passed=5) 1265 1266 def test_parametrize_issue323(self, testdir): 1267 testdir.makepyfile( 1268 """ 1269 import pytest 1270 1271 @pytest.fixture(scope='module', params=range(966)) 1272 def foo(request): 1273 return request.param 1274 1275 def test_it(foo): 1276 pass 1277 def test_it2(foo): 1278 pass 1279 """ 1280 ) 1281 reprec = testdir.inline_run("--collect-only") 1282 assert not reprec.getcalls("pytest_internalerror") 1283 1284 def test_usefixtures_seen_in_generate_tests(self, testdir): 1285 testdir.makepyfile( 1286 """ 1287 import pytest 1288 def pytest_generate_tests(metafunc): 1289 assert "abc" in metafunc.fixturenames 1290 metafunc.parametrize("abc", [1]) 1291 1292 @pytest.mark.usefixtures("abc") 1293 def test_function(): 1294 pass 1295 """ 1296 ) 1297 reprec = testdir.runpytest() 1298 reprec.assert_outcomes(passed=1) 1299 1300 def test_generate_tests_only_done_in_subdir(self, testdir): 1301 sub1 = testdir.mkpydir("sub1") 1302 sub2 = testdir.mkpydir("sub2") 1303 sub1.join("conftest.py").write( 1304 _pytest._code.Source( 1305 """ 1306 def pytest_generate_tests(metafunc): 1307 assert metafunc.function.__name__ == "test_1" 1308 """ 1309 ) 1310 ) 1311 sub2.join("conftest.py").write( 1312 _pytest._code.Source( 1313 """ 1314 def pytest_generate_tests(metafunc): 1315 assert metafunc.function.__name__ == "test_2" 1316 """ 1317 ) 1318 ) 1319 sub1.join("test_in_sub1.py").write("def test_1(): pass") 1320 sub2.join("test_in_sub2.py").write("def test_2(): pass") 1321 result = testdir.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1) 1322 result.assert_outcomes(passed=3) 1323 1324 def test_generate_same_function_names_issue403(self, testdir): 1325 testdir.makepyfile( 1326 """ 1327 import pytest 1328 1329 def make_tests(): 1330 @pytest.mark.parametrize("x", range(2)) 1331 def test_foo(x): 1332 pass 1333 return test_foo 1334 1335 test_x = make_tests() 1336 test_y = make_tests() 1337 """ 1338 ) 1339 reprec = testdir.runpytest() 1340 reprec.assert_outcomes(passed=4) 1341 1342 @pytest.mark.issue463 1343 @pytest.mark.parametrize("attr", ["parametrise", "parameterize", "parameterise"]) 1344 def test_parametrize_misspelling(self, testdir, attr): 1345 testdir.makepyfile( 1346 """ 1347 import pytest 1348 1349 @pytest.mark.{}("x", range(2)) 1350 def test_foo(x): 1351 pass 1352 """.format( 1353 attr 1354 ) 1355 ) 1356 reprec = testdir.inline_run("--collectonly") 1357 failures = reprec.getfailures() 1358 assert len(failures) == 1 1359 expectederror = "MarkerError: test_foo has '{}', spelling should be 'parametrize'".format( 1360 attr 1361 ) 1362 assert expectederror in failures[0].longrepr.reprcrash.message 1363 1364 1365class TestMetafuncFunctionalAuto(object): 1366 """ 1367 Tests related to automatically find out the correct scope for parametrized tests (#1832). 1368 """ 1369 1370 def test_parametrize_auto_scope(self, testdir): 1371 testdir.makepyfile( 1372 """ 1373 import pytest 1374 1375 @pytest.fixture(scope='session', autouse=True) 1376 def fixture(): 1377 return 1 1378 1379 @pytest.mark.parametrize('animal', ["dog", "cat"]) 1380 def test_1(animal): 1381 assert animal in ('dog', 'cat') 1382 1383 @pytest.mark.parametrize('animal', ['fish']) 1384 def test_2(animal): 1385 assert animal == 'fish' 1386 1387 """ 1388 ) 1389 result = testdir.runpytest() 1390 result.stdout.fnmatch_lines(["* 3 passed *"]) 1391 1392 def test_parametrize_auto_scope_indirect(self, testdir): 1393 testdir.makepyfile( 1394 """ 1395 import pytest 1396 1397 @pytest.fixture(scope='session') 1398 def echo(request): 1399 return request.param 1400 1401 @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=['echo']) 1402 def test_1(animal, echo): 1403 assert animal in ('dog', 'cat') 1404 assert echo in (1, 2, 3) 1405 1406 @pytest.mark.parametrize('animal, echo', [('fish', 3)], indirect=['echo']) 1407 def test_2(animal, echo): 1408 assert animal == 'fish' 1409 assert echo in (1, 2, 3) 1410 """ 1411 ) 1412 result = testdir.runpytest() 1413 result.stdout.fnmatch_lines(["* 3 passed *"]) 1414 1415 def test_parametrize_auto_scope_override_fixture(self, testdir): 1416 testdir.makepyfile( 1417 """ 1418 import pytest 1419 1420 @pytest.fixture(scope='session', autouse=True) 1421 def animal(): 1422 return 'fox' 1423 1424 @pytest.mark.parametrize('animal', ["dog", "cat"]) 1425 def test_1(animal): 1426 assert animal in ('dog', 'cat') 1427 """ 1428 ) 1429 result = testdir.runpytest() 1430 result.stdout.fnmatch_lines(["* 2 passed *"]) 1431 1432 def test_parametrize_all_indirects(self, testdir): 1433 testdir.makepyfile( 1434 """ 1435 import pytest 1436 1437 @pytest.fixture() 1438 def animal(request): 1439 return request.param 1440 1441 @pytest.fixture(scope='session') 1442 def echo(request): 1443 return request.param 1444 1445 @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=True) 1446 def test_1(animal, echo): 1447 assert animal in ('dog', 'cat') 1448 assert echo in (1, 2, 3) 1449 1450 @pytest.mark.parametrize('animal, echo', [("fish", 3)], indirect=True) 1451 def test_2(animal, echo): 1452 assert animal == 'fish' 1453 assert echo in (1, 2, 3) 1454 """ 1455 ) 1456 result = testdir.runpytest() 1457 result.stdout.fnmatch_lines(["* 3 passed *"]) 1458 1459 def test_parametrize_issue634(self, testdir): 1460 testdir.makepyfile( 1461 """ 1462 import pytest 1463 1464 @pytest.fixture(scope='module') 1465 def foo(request): 1466 print('preparing foo-%d' % request.param) 1467 return 'foo-%d' % request.param 1468 1469 def test_one(foo): 1470 pass 1471 1472 def test_two(foo): 1473 pass 1474 1475 test_two.test_with = (2, 3) 1476 1477 def pytest_generate_tests(metafunc): 1478 params = (1, 2, 3, 4) 1479 if not 'foo' in metafunc.fixturenames: 1480 return 1481 1482 test_with = getattr(metafunc.function, 'test_with', None) 1483 if test_with: 1484 params = test_with 1485 metafunc.parametrize('foo', params, indirect=True) 1486 """ 1487 ) 1488 result = testdir.runpytest("-s") 1489 output = result.stdout.str() 1490 assert output.count("preparing foo-2") == 1 1491 assert output.count("preparing foo-3") == 1 1492 1493 1494@pytest.mark.filterwarnings("ignore:Applying marks directly to parameters") 1495@pytest.mark.issue308 1496class TestMarkersWithParametrization(object): 1497 1498 def test_simple_mark(self, testdir): 1499 s = """ 1500 import pytest 1501 1502 @pytest.mark.foo 1503 @pytest.mark.parametrize(("n", "expected"), [ 1504 (1, 2), 1505 pytest.mark.bar((1, 3)), 1506 (2, 3), 1507 ]) 1508 def test_increment(n, expected): 1509 assert n + 1 == expected 1510 """ 1511 items = testdir.getitems(s) 1512 assert len(items) == 3 1513 for item in items: 1514 assert "foo" in item.keywords 1515 assert "bar" not in items[0].keywords 1516 assert "bar" in items[1].keywords 1517 assert "bar" not in items[2].keywords 1518 1519 def test_select_based_on_mark(self, testdir): 1520 s = """ 1521 import pytest 1522 1523 @pytest.mark.parametrize(("n", "expected"), [ 1524 (1, 2), 1525 pytest.mark.foo((2, 3)), 1526 (3, 4), 1527 ]) 1528 def test_increment(n, expected): 1529 assert n + 1 == expected 1530 """ 1531 testdir.makepyfile(s) 1532 rec = testdir.inline_run("-m", "foo") 1533 passed, skipped, fail = rec.listoutcomes() 1534 assert len(passed) == 1 1535 assert len(skipped) == 0 1536 assert len(fail) == 0 1537 1538 @pytest.mark.xfail(reason="is this important to support??") 1539 def test_nested_marks(self, testdir): 1540 s = """ 1541 import pytest 1542 mastermark = pytest.mark.foo(pytest.mark.bar) 1543 1544 @pytest.mark.parametrize(("n", "expected"), [ 1545 (1, 2), 1546 mastermark((1, 3)), 1547 (2, 3), 1548 ]) 1549 def test_increment(n, expected): 1550 assert n + 1 == expected 1551 """ 1552 items = testdir.getitems(s) 1553 assert len(items) == 3 1554 for mark in ["foo", "bar"]: 1555 assert mark not in items[0].keywords 1556 assert mark in items[1].keywords 1557 assert mark not in items[2].keywords 1558 1559 def test_simple_xfail(self, testdir): 1560 s = """ 1561 import pytest 1562 1563 @pytest.mark.parametrize(("n", "expected"), [ 1564 (1, 2), 1565 pytest.mark.xfail((1, 3)), 1566 (2, 3), 1567 ]) 1568 def test_increment(n, expected): 1569 assert n + 1 == expected 1570 """ 1571 testdir.makepyfile(s) 1572 reprec = testdir.inline_run() 1573 # xfail is skip?? 1574 reprec.assertoutcome(passed=2, skipped=1) 1575 1576 def test_simple_xfail_single_argname(self, testdir): 1577 s = """ 1578 import pytest 1579 1580 @pytest.mark.parametrize("n", [ 1581 2, 1582 pytest.mark.xfail(3), 1583 4, 1584 ]) 1585 def test_isEven(n): 1586 assert n % 2 == 0 1587 """ 1588 testdir.makepyfile(s) 1589 reprec = testdir.inline_run() 1590 reprec.assertoutcome(passed=2, skipped=1) 1591 1592 def test_xfail_with_arg(self, testdir): 1593 s = """ 1594 import pytest 1595 1596 @pytest.mark.parametrize(("n", "expected"), [ 1597 (1, 2), 1598 pytest.mark.xfail("True")((1, 3)), 1599 (2, 3), 1600 ]) 1601 def test_increment(n, expected): 1602 assert n + 1 == expected 1603 """ 1604 testdir.makepyfile(s) 1605 reprec = testdir.inline_run() 1606 reprec.assertoutcome(passed=2, skipped=1) 1607 1608 def test_xfail_with_kwarg(self, testdir): 1609 s = """ 1610 import pytest 1611 1612 @pytest.mark.parametrize(("n", "expected"), [ 1613 (1, 2), 1614 pytest.mark.xfail(reason="some bug")((1, 3)), 1615 (2, 3), 1616 ]) 1617 def test_increment(n, expected): 1618 assert n + 1 == expected 1619 """ 1620 testdir.makepyfile(s) 1621 reprec = testdir.inline_run() 1622 reprec.assertoutcome(passed=2, skipped=1) 1623 1624 def test_xfail_with_arg_and_kwarg(self, testdir): 1625 s = """ 1626 import pytest 1627 1628 @pytest.mark.parametrize(("n", "expected"), [ 1629 (1, 2), 1630 pytest.mark.xfail("True", reason="some bug")((1, 3)), 1631 (2, 3), 1632 ]) 1633 def test_increment(n, expected): 1634 assert n + 1 == expected 1635 """ 1636 testdir.makepyfile(s) 1637 reprec = testdir.inline_run() 1638 reprec.assertoutcome(passed=2, skipped=1) 1639 1640 @pytest.mark.parametrize("strict", [True, False]) 1641 def test_xfail_passing_is_xpass(self, testdir, strict): 1642 s = """ 1643 import pytest 1644 1645 @pytest.mark.parametrize(("n", "expected"), [ 1646 (1, 2), 1647 pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})((2, 3)), 1648 (3, 4), 1649 ]) 1650 def test_increment(n, expected): 1651 assert n + 1 == expected 1652 """.format( 1653 strict=strict 1654 ) 1655 testdir.makepyfile(s) 1656 reprec = testdir.inline_run() 1657 passed, failed = (2, 1) if strict else (3, 0) 1658 reprec.assertoutcome(passed=passed, failed=failed) 1659 1660 def test_parametrize_called_in_generate_tests(self, testdir): 1661 s = """ 1662 import pytest 1663 1664 1665 def pytest_generate_tests(metafunc): 1666 passingTestData = [(1, 2), 1667 (2, 3)] 1668 failingTestData = [(1, 3), 1669 (2, 2)] 1670 1671 testData = passingTestData + [pytest.mark.xfail(d) 1672 for d in failingTestData] 1673 metafunc.parametrize(("n", "expected"), testData) 1674 1675 1676 def test_increment(n, expected): 1677 assert n + 1 == expected 1678 """ 1679 testdir.makepyfile(s) 1680 reprec = testdir.inline_run() 1681 reprec.assertoutcome(passed=2, skipped=2) 1682 1683 @pytest.mark.issue290 1684 def test_parametrize_ID_generation_string_int_works(self, testdir): 1685 testdir.makepyfile( 1686 """ 1687 import pytest 1688 1689 @pytest.fixture 1690 def myfixture(): 1691 return 'example' 1692 @pytest.mark.parametrize( 1693 'limit', (0, '0')) 1694 def test_limit(limit, myfixture): 1695 return 1696 """ 1697 ) 1698 reprec = testdir.inline_run() 1699 reprec.assertoutcome(passed=2) 1700 1701 @pytest.mark.parametrize("strict", [True, False]) 1702 def test_parametrize_marked_value(self, testdir, strict): 1703 s = """ 1704 import pytest 1705 1706 @pytest.mark.parametrize(("n", "expected"), [ 1707 pytest.param( 1708 2,3, 1709 marks=pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict}), 1710 ), 1711 pytest.param( 1712 2,3, 1713 marks=[pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})], 1714 ), 1715 ]) 1716 def test_increment(n, expected): 1717 assert n + 1 == expected 1718 """.format( 1719 strict=strict 1720 ) 1721 testdir.makepyfile(s) 1722 reprec = testdir.inline_run() 1723 passed, failed = (0, 2) if strict else (2, 0) 1724 reprec.assertoutcome(passed=passed, failed=failed) 1725 1726 def test_pytest_make_parametrize_id(self, testdir): 1727 testdir.makeconftest( 1728 """ 1729 def pytest_make_parametrize_id(config, val): 1730 return str(val * 2) 1731 """ 1732 ) 1733 testdir.makepyfile( 1734 """ 1735 import pytest 1736 1737 @pytest.mark.parametrize("x", range(2)) 1738 def test_func(x): 1739 pass 1740 """ 1741 ) 1742 result = testdir.runpytest("-v") 1743 result.stdout.fnmatch_lines(["*test_func*0*PASS*", "*test_func*2*PASS*"]) 1744 1745 def test_pytest_make_parametrize_id_with_argname(self, testdir): 1746 testdir.makeconftest( 1747 """ 1748 def pytest_make_parametrize_id(config, val, argname): 1749 return str(val * 2 if argname == 'x' else val * 10) 1750 """ 1751 ) 1752 testdir.makepyfile( 1753 """ 1754 import pytest 1755 1756 @pytest.mark.parametrize("x", range(2)) 1757 def test_func_a(x): 1758 pass 1759 1760 @pytest.mark.parametrize("y", [1]) 1761 def test_func_b(y): 1762 pass 1763 """ 1764 ) 1765 result = testdir.runpytest("-v") 1766 result.stdout.fnmatch_lines( 1767 ["*test_func_a*0*PASS*", "*test_func_a*2*PASS*", "*test_func_b*10*PASS*"] 1768 ) 1769