[Pytest-commit] commit/pytest: 2 new changesets
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Thu Dec 5 06:31:56 CET 2013
2 new commits in pytest:
https://bitbucket.org/hpk42/pytest/commits/20f0da86518e/
Changeset: 20f0da86518e
User: hpk42
Date: 2013-12-04 16:09:37
Summary: reopen #246 -- it turns out parametrized finalization ordering is not fully fixed -- i modified the test and marked it xfail for now.
Affected #: 1 file
diff -r aa1f0505a3156b9feca43cd67c5afc95622b9ac5 -r 20f0da86518e3636726e2880b3b4d761fce56ec2 testing/python/fixture.py
--- a/testing/python/fixture.py
+++ b/testing/python/fixture.py
@@ -1855,6 +1855,7 @@
reprec.assertoutcome(passed=5)
+ @pytest.mark.xfail
@pytest.mark.issue246
@pytest.mark.parametrize("scope", ["session", "function", "module"])
def test_finalizer_order_on_parametrization(self, scope, testdir):
@@ -1876,15 +1877,18 @@
def base(request, fix1):
def cleanup_base():
l.append("fin_base")
+ print ("finalizing base")
request.addfinalizer(cleanup_base)
+ def test_begin():
+ pass
def test_baz(base, fix2):
pass
def test_other():
pass
""" % {"scope": scope})
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
+ reprec = testdir.inline_run("-lvs")
+ reprec.assertoutcome(passed=3)
def test_parametrize_setup_function(self, testdir):
testdir.makepyfile("""
https://bitbucket.org/hpk42/pytest/commits/1338c1ed28ff/
Changeset: 1338c1ed28ff
User: hpk42
Date: 2013-12-05 06:09:29
Summary: refactor and document parametrized sorting code.
Affected #: 1 file
diff -r 20f0da86518e3636726e2880b3b4d761fce56ec2 -r 1338c1ed28ffbeda49a7a9dbf983de8b569f52db _pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -631,7 +631,7 @@
self._checkargnotcontained(arg)
getattr(self, valtype)[arg] = val
# we want self.params to be always set because of
- # parametrize_sorted() which groups tests by params/scope
+ # reorder_items() which groups tests by params/scope
if valtype == "funcargs":
self.params[arg] = id
self.indices[arg] = param_index
@@ -1600,7 +1600,7 @@
def pytest_collection_modifyitems(self, items):
# separate parametrized setups
- items[:] = parametrize_sorted(items, set(), {}, 0)
+ items[:] = reorder_items(items, set(), {}, 0)
@pytest.mark.trylast
def pytest_runtest_teardown(self, item, nextitem):
@@ -1822,85 +1822,77 @@
return tuple(argnames[startindex:])
# algorithm for sorting on a per-parametrized resource setup basis
+# it is called for scopenum==0 (session) first and performs sorting
+# down to the lower scopes such as to minimize number of "high scope"
+# setups and teardowns
-def parametrize_sorted(items, ignore, cache, scopenum):
- if scopenum >= 3:
+def reorder_items(items, ignore, cache, scopenum):
+ if scopenum >= scopenum_function:
return items
+ if len(items) < 2:
+ return items
+ #print "\nparametrize_Sorted", items, ignore, cache, scopenum
- # we pick the first item which has a arg/param combo in the
- # requested scope and sort other items with the same combo
- # into "newitems" which then is a list of all items using this
- # arg/param.
+ # we pick the first item which uses a fixture instance in the requested scope
+ # and which we haven't seen yet. We slice the input items list into
+ # a list of items_nomatch, items_using_same_fixtureinstance and
+ # items_remaining
+ slicing_argkey = None
+ for i, item in enumerate(items):
+ argkeys = get_parametrized_fixture_keys(item, ignore, scopenum, cache)
+ if slicing_argkey is None:
+ if argkeys:
+ slicing_argkey = argkeys.pop()
+ items_using_same_fixtureinstance = [item]
+ items_nomatch = items[:i]
+ items_remaining = []
+ continue
+ if slicing_argkey in argkeys:
+ items_using_same_fixtureinstance.append(item)
+ else:
+ items_remaining.append(item)
- similar_items = []
- other_items = []
- slicing_argparam = None
- slicing_index = 0
- for item in items:
- argparamlist = getfuncargparams(item, ignore, scopenum, cache)
- if slicing_argparam is None and argparamlist:
- slicing_argparam = argparamlist[0]
- slicing_index = len(other_items)
- if slicing_argparam in argparamlist:
- similar_items.append(item)
- else:
- other_items.append(item)
+ if slicing_argkey is None or len(items_using_same_fixtureinstance) == 1:
+ # nothing to sort on this level
+ return reorder_items(items, ignore, cache, scopenum+1)
- if (len(similar_items) + slicing_index) > 1:
- newignore = ignore.copy()
- newignore.add(slicing_argparam)
- part2 = parametrize_sorted(
- similar_items + other_items[slicing_index:],
- newignore, cache, scopenum)
- part1 = parametrize_sorted(
- other_items[:slicing_index], newignore,
- cache, scopenum+1)
- return part1 + part2
- else:
- other_items = parametrize_sorted(other_items, ignore, cache, scopenum+1)
- return other_items + similar_items
+ items_nomatch = reorder_items(items_nomatch, ignore, cache, scopenum+1)
+ newignore = ignore.copy()
+ newignore.add(slicing_argkey)
+ part2 = reorder_items(items_using_same_fixtureinstance + items_remaining,
+ newignore, cache, scopenum)
+ return items_nomatch + part2
-def getfuncargparams(item, ignore, scopenum, cache):
- """ return list of (arg,param) tuple, sorted by broader scope first. """
- assert scopenum < 3 # function
+def get_parametrized_fixture_keys(item, ignore, scopenum, cache):
+ """ return list of keys for all parametrized arguments which match
+ the specified scope. """
+ assert scopenum < scopenum_function # function
+ keys = set()
try:
cs = item.callspec
except AttributeError:
- return []
- if scopenum == 0:
- argparams = [x for x in cs.indices.items() if x not in ignore
- and cs._arg2scopenum[x[0]] == scopenum]
- elif scopenum == 1: # module
- argparams = []
- for argname, valindex in cs.indices.items():
- if cs._arg2scopenum[argname] == scopenum:
- key = (argname, valindex, item.fspath)
- if key in ignore:
- continue
- argparams.append(key)
- elif scopenum == 2: # class
- argparams = []
- for argname, valindex in cs.indices.items():
- if cs._arg2scopenum[argname] == scopenum:
- l = cache.setdefault(item.fspath, [])
- try:
- i = l.index(item.cls)
- except ValueError:
- i = len(l)
- l.append(item.cls)
- key = (argname, valindex, item.fspath, i)
- if key in ignore:
- continue
- argparams.append(key)
- #elif scopenum == 3:
- # argparams = []
- # for argname, param in cs.indices.items():
- # if cs._arg2scopenum[argname] == scopenum:
- # key = (argname, param, getfslineno(item.obj))
- # if key in ignore:
- # continue
- # argparams.append(key)
- return argparams
+ return keys # no parametrization on this item
+ # cs.indictes.items() is random order of argnames but
+ # then again different functions (items) can change order of
+ # arguments so it doesn't matter much probably
+ for argname, param_index in cs.indices.items():
+ if cs._arg2scopenum[argname] != scopenum:
+ continue
+ if scopenum == 0: # session
+ key = (argname, param_index)
+ elif scopenum == 1: # module
+ key = (argname, param_index, item.fspath)
+ elif scopenum == 2: # class
+ l = cache.setdefault(item.fspath, [])
+ try:
+ i = l.index(item.cls)
+ except ValueError:
+ i = len(l)
+ l.append(item.cls)
+ key = (argname, param_index, item.fspath, i)
+ if key not in ignore:
+ keys.add(key)
+ return keys
def xunitsetup(obj, name):
Repository URL: https://bitbucket.org/hpk42/pytest/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the pytest-commit
mailing list