parent
9555d427ae
commit
07c835fdf3
|
@ -4,7 +4,7 @@ import sys, os
|
|||
default_plugins = (
|
||||
"session terminal python runner pdb capture mark skipping tmpdir monkeypatch "
|
||||
"recwarn pastebin unittest helpconfig nose assertion genscript "
|
||||
"junitxml doctest keyword").split()
|
||||
"junitxml doctest").split()
|
||||
|
||||
def main(args=None):
|
||||
import sys
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group._addoption('-k',
|
||||
action="store", dest="keyword", default='',
|
||||
help="only run test items matching the given "
|
||||
"space separated keywords. precede a keyword with '-' to negate. "
|
||||
"Terminate the expression with ':' to treat a match as a signal "
|
||||
"to run all subsequent tests. ")
|
||||
|
||||
def pytest_collection_modifyitems(items, config):
|
||||
keywordexpr = config.option.keyword
|
||||
if not keywordexpr:
|
||||
return
|
||||
selectuntil = False
|
||||
if keywordexpr[-1] == ":":
|
||||
selectuntil = True
|
||||
keywordexpr = keywordexpr[:-1]
|
||||
|
||||
remaining = []
|
||||
deselected = []
|
||||
for colitem in items:
|
||||
if keywordexpr and skipbykeyword(colitem, keywordexpr):
|
||||
deselected.append(colitem)
|
||||
else:
|
||||
remaining.append(colitem)
|
||||
if selectuntil:
|
||||
keywordexpr = None
|
||||
|
||||
if deselected:
|
||||
config.hook.pytest_deselected(items=deselected)
|
||||
items[:] = remaining
|
||||
|
||||
def skipbykeyword(colitem, keywordexpr):
|
||||
""" return True if they given keyword expression means to
|
||||
skip this collector/item.
|
||||
"""
|
||||
if not keywordexpr:
|
||||
return
|
||||
chain = colitem.listchain()
|
||||
for key in filter(None, keywordexpr.split()):
|
||||
eor = key[:1] == '-'
|
||||
if eor:
|
||||
key = key[1:]
|
||||
if not (eor ^ matchonekeyword(key, chain)):
|
||||
return True
|
||||
|
||||
def matchonekeyword(key, chain):
|
||||
elems = key.split(".")
|
||||
# XXX O(n^2), anyone cares?
|
||||
chain = [item.keywords for item in chain if item.keywords]
|
||||
for start, _ in enumerate(chain):
|
||||
if start + len(elems) > len(chain):
|
||||
return False
|
||||
for num, elem in enumerate(elems):
|
||||
for keyword in chain[num + start]:
|
||||
ok = False
|
||||
if elem in keyword:
|
||||
ok = True
|
||||
break
|
||||
if not ok:
|
||||
break
|
||||
if num == len(elems) - 1 and ok:
|
||||
return True
|
||||
return False
|
|
@ -87,6 +87,71 @@ import py
|
|||
def pytest_namespace():
|
||||
return {'mark': MarkGenerator()}
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group._addoption('-k',
|
||||
action="store", dest="keyword", default='',
|
||||
help="only run test items matching the given "
|
||||
"space separated keywords. precede a keyword with '-' to negate. "
|
||||
"Terminate the expression with ':' to treat a match as a signal "
|
||||
"to run all subsequent tests. ")
|
||||
|
||||
def pytest_collection_modifyitems(items, config):
|
||||
keywordexpr = config.option.keyword
|
||||
if not keywordexpr:
|
||||
return
|
||||
selectuntil = False
|
||||
if keywordexpr[-1] == ":":
|
||||
selectuntil = True
|
||||
keywordexpr = keywordexpr[:-1]
|
||||
|
||||
remaining = []
|
||||
deselected = []
|
||||
for colitem in items:
|
||||
if keywordexpr and skipbykeyword(colitem, keywordexpr):
|
||||
deselected.append(colitem)
|
||||
else:
|
||||
remaining.append(colitem)
|
||||
if selectuntil:
|
||||
keywordexpr = None
|
||||
|
||||
if deselected:
|
||||
config.hook.pytest_deselected(items=deselected)
|
||||
items[:] = remaining
|
||||
|
||||
def skipbykeyword(colitem, keywordexpr):
|
||||
""" return True if they given keyword expression means to
|
||||
skip this collector/item.
|
||||
"""
|
||||
if not keywordexpr:
|
||||
return
|
||||
chain = colitem.listchain()
|
||||
for key in filter(None, keywordexpr.split()):
|
||||
eor = key[:1] == '-'
|
||||
if eor:
|
||||
key = key[1:]
|
||||
if not (eor ^ matchonekeyword(key, chain)):
|
||||
return True
|
||||
|
||||
def matchonekeyword(key, chain):
|
||||
elems = key.split(".")
|
||||
# XXX O(n^2), anyone cares?
|
||||
chain = [item.keywords for item in chain if item.keywords]
|
||||
for start, _ in enumerate(chain):
|
||||
if start + len(elems) > len(chain):
|
||||
return False
|
||||
for num, elem in enumerate(elems):
|
||||
for keyword in chain[num + start]:
|
||||
ok = False
|
||||
if elem in keyword:
|
||||
ok = True
|
||||
break
|
||||
if not ok:
|
||||
break
|
||||
if num == len(elems) - 1 and ok:
|
||||
return True
|
||||
return False
|
||||
|
||||
class MarkGenerator:
|
||||
""" non-underscore attributes of this object can be used as decorators for
|
||||
marking test functions. Example: @py.test.mark.slowtest in front of a
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
import py
|
||||
|
||||
class Test_genitems:
|
||||
def test_check_collect_hashes(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
def test_1():
|
||||
pass
|
||||
|
||||
def test_2():
|
||||
pass
|
||||
""")
|
||||
p.copy(p.dirpath(p.purebasename + "2" + ".py"))
|
||||
items, reprec = testdir.inline_genitems(p.dirpath())
|
||||
assert len(items) == 4
|
||||
for numi, i in enumerate(items):
|
||||
for numj, j in enumerate(items):
|
||||
if numj != numi:
|
||||
assert hash(i) != hash(j)
|
||||
assert i != j
|
||||
|
||||
def test_root_conftest_syntax_error(self, testdir):
|
||||
# do we want to unify behaviour with
|
||||
# test_subdir_conftest_error?
|
||||
p = testdir.makepyfile(conftest="raise SyntaxError\n")
|
||||
py.test.raises(SyntaxError, testdir.inline_genitems, p.dirpath())
|
||||
|
||||
def test_example_items1(self, testdir):
|
||||
p = testdir.makepyfile('''
|
||||
def testone():
|
||||
pass
|
||||
|
||||
class TestX:
|
||||
def testmethod_one(self):
|
||||
pass
|
||||
|
||||
class TestY(TestX):
|
||||
pass
|
||||
''')
|
||||
items, reprec = testdir.inline_genitems(p)
|
||||
assert len(items) == 3
|
||||
assert items[0].name == 'testone'
|
||||
assert items[1].name == 'testmethod_one'
|
||||
assert items[2].name == 'testmethod_one'
|
||||
|
||||
# let's also test getmodpath here
|
||||
assert items[0].getmodpath() == "testone"
|
||||
assert items[1].getmodpath() == "TestX.testmethod_one"
|
||||
assert items[2].getmodpath() == "TestY.testmethod_one"
|
||||
|
||||
s = items[0].getmodpath(stopatmodule=False)
|
||||
assert s.endswith("test_example_items1.testone")
|
||||
print(s)
|
||||
|
||||
|
||||
class TestKeywordSelection:
|
||||
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']:
|
||||
#yield check, keyword, 'test_one'
|
||||
check(keyword, 'test_one')
|
||||
check('TestClass.test', 'test_method_one')
|
||||
|
||||
def test_select_extra_keywords(self, testdir):
|
||||
p = testdir.makepyfile(test_select="""
|
||||
def test_1():
|
||||
pass
|
||||
class TestClass:
|
||||
def test_2(self):
|
||||
pass
|
||||
""")
|
||||
testdir.makepyfile(conftest="""
|
||||
import py
|
||||
class Class(py.test.collect.Class):
|
||||
def _keywords(self):
|
||||
return ['xxx', self.name]
|
||||
""")
|
||||
for keyword in ('xxx', 'xxx test_2', 'TestClass', 'xxx -test_1',
|
||||
'TestClass test_2', 'xxx TestClass test_2',):
|
||||
reprec = testdir.inline_run(p.dirpath(), '-s', '-k', keyword)
|
||||
py.builtin.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 passed + skipped + failed == 0
|
||||
reprec = testdir.inline_run("-k", "mykeyword", p)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == 1
|
|
@ -173,3 +173,130 @@ class TestFunctional:
|
|||
result.stdout.fnmatch_lines([
|
||||
"keyword: *hello*"
|
||||
])
|
||||
|
||||
|
||||
class Test_genitems:
|
||||
def test_check_collect_hashes(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
def test_1():
|
||||
pass
|
||||
|
||||
def test_2():
|
||||
pass
|
||||
""")
|
||||
p.copy(p.dirpath(p.purebasename + "2" + ".py"))
|
||||
items, reprec = testdir.inline_genitems(p.dirpath())
|
||||
assert len(items) == 4
|
||||
for numi, i in enumerate(items):
|
||||
for numj, j in enumerate(items):
|
||||
if numj != numi:
|
||||
assert hash(i) != hash(j)
|
||||
assert i != j
|
||||
|
||||
def test_root_conftest_syntax_error(self, testdir):
|
||||
# do we want to unify behaviour with
|
||||
# test_subdir_conftest_error?
|
||||
p = testdir.makepyfile(conftest="raise SyntaxError\n")
|
||||
py.test.raises(SyntaxError, testdir.inline_genitems, p.dirpath())
|
||||
|
||||
def test_example_items1(self, testdir):
|
||||
p = testdir.makepyfile('''
|
||||
def testone():
|
||||
pass
|
||||
|
||||
class TestX:
|
||||
def testmethod_one(self):
|
||||
pass
|
||||
|
||||
class TestY(TestX):
|
||||
pass
|
||||
''')
|
||||
items, reprec = testdir.inline_genitems(p)
|
||||
assert len(items) == 3
|
||||
assert items[0].name == 'testone'
|
||||
assert items[1].name == 'testmethod_one'
|
||||
assert items[2].name == 'testmethod_one'
|
||||
|
||||
# let's also test getmodpath here
|
||||
assert items[0].getmodpath() == "testone"
|
||||
assert items[1].getmodpath() == "TestX.testmethod_one"
|
||||
assert items[2].getmodpath() == "TestY.testmethod_one"
|
||||
|
||||
s = items[0].getmodpath(stopatmodule=False)
|
||||
assert s.endswith("test_example_items1.testone")
|
||||
print(s)
|
||||
|
||||
|
||||
class TestKeywordSelection:
|
||||
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']:
|
||||
#yield check, keyword, 'test_one'
|
||||
check(keyword, 'test_one')
|
||||
check('TestClass.test', 'test_method_one')
|
||||
|
||||
def test_select_extra_keywords(self, testdir):
|
||||
p = testdir.makepyfile(test_select="""
|
||||
def test_1():
|
||||
pass
|
||||
class TestClass:
|
||||
def test_2(self):
|
||||
pass
|
||||
""")
|
||||
testdir.makepyfile(conftest="""
|
||||
import py
|
||||
class Class(py.test.collect.Class):
|
||||
def _keywords(self):
|
||||
return ['xxx', self.name]
|
||||
""")
|
||||
for keyword in ('xxx', 'xxx test_2', 'TestClass', 'xxx -test_1',
|
||||
'TestClass test_2', 'xxx TestClass test_2',):
|
||||
reprec = testdir.inline_run(p.dirpath(), '-s', '-k', keyword)
|
||||
py.builtin.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 passed + skipped + failed == 0
|
||||
reprec = testdir.inline_run("-k", "mykeyword", p)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == 1
|
||||
|
|
Loading…
Reference in New Issue