Merged in dimazest/pytest-xdist/collection_diff_reporting (pull request #3)
Give more context when nodes collected different tests.
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
from xdist.dsession import DSession, LoadScheduling, EachScheduling
|
from xdist.dsession import (
|
||||||
|
DSession,
|
||||||
|
LoadScheduling,
|
||||||
|
EachScheduling,
|
||||||
|
report_collection_diff,
|
||||||
|
)
|
||||||
from _pytest import main as outcome
|
from _pytest import main as outcome
|
||||||
import py
|
import py
|
||||||
import execnet
|
import execnet
|
||||||
@@ -165,3 +170,35 @@ class TestDistReporter:
|
|||||||
linecomp.assert_contains_lines([
|
linecomp.assert_contains_lines([
|
||||||
"[X1,X2] rsyncing: hello",
|
"[X1,X2] rsyncing: hello",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_report_collection_diff_equal():
|
||||||
|
"""Test reporting of equal collections."""
|
||||||
|
from_collection = to_collection = ['aaa', 'bbb', 'ccc']
|
||||||
|
assert report_collection_diff(from_collection, to_collection, 1, 2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_report_collection_diff_different():
|
||||||
|
"""Test reporting of different collections."""
|
||||||
|
from_collection = ['aaa', 'bbb', 'ccc', 'YYY']
|
||||||
|
to_collection = ['aZa', 'bbb', 'XXX', 'ccc']
|
||||||
|
error_message = (
|
||||||
|
u'Different tests were collected between 1 and 2. The difference is:\n'
|
||||||
|
u'--- 1 \n'
|
||||||
|
u'\n'
|
||||||
|
u'+++ 2 \n'
|
||||||
|
u'\n'
|
||||||
|
u'@@ -1,4 +1,4 @@\n'
|
||||||
|
u'\n'
|
||||||
|
u'-aaa\n'
|
||||||
|
u'+aZa\n'
|
||||||
|
u' bbb\n'
|
||||||
|
u'+XXX\n'
|
||||||
|
u' ccc\n'
|
||||||
|
u'-YYY'
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
report_collection_diff(from_collection, to_collection, 1, 2)
|
||||||
|
except AssertionError as e:
|
||||||
|
assert unicode(e) == error_message
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import pytest, py
|
|
||||||
import sys
|
import sys
|
||||||
|
import difflib
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import py
|
||||||
from xdist.slavemanage import NodeManager
|
from xdist.slavemanage import NodeManager
|
||||||
|
|
||||||
|
|
||||||
queue = py.builtin._tryimport('queue', 'Queue')
|
queue = py.builtin._tryimport('queue', 'Queue')
|
||||||
|
|
||||||
|
|
||||||
class EachScheduling:
|
class EachScheduling:
|
||||||
|
|
||||||
def __init__(self, numnodes, log=None):
|
def __init__(self, numnodes, log=None):
|
||||||
@@ -127,15 +133,21 @@ class LoadScheduling:
|
|||||||
assert not hasattr(self, 'item2nodes')
|
assert not hasattr(self, 'item2nodes')
|
||||||
self.item2nodes = {}
|
self.item2nodes = {}
|
||||||
# XXX allow nodes to have different collections
|
# XXX allow nodes to have different collections
|
||||||
col = list(self.node2collection.values())[0]
|
first_node, col = list(self.node2collection.items())[0]
|
||||||
for node, collection in self.node2collection.items():
|
for node, collection in self.node2collection.items():
|
||||||
assert collection == col
|
report_collection_diff(
|
||||||
|
col,
|
||||||
|
collection,
|
||||||
|
first_node.gateway.id,
|
||||||
|
node.gateway.id,
|
||||||
|
)
|
||||||
|
|
||||||
self.pending = col
|
self.pending = col
|
||||||
if not col:
|
if not col:
|
||||||
return
|
return
|
||||||
available = list(self.node2pending.items())
|
available = list(self.node2pending.items())
|
||||||
num_available = self.numnodes
|
num_available = self.numnodes
|
||||||
max_one_round = num_available * self.ITEM_CHUNKSIZE -1
|
max_one_round = num_available * self.ITEM_CHUNKSIZE - 1
|
||||||
for i, item in enumerate(self.pending):
|
for i, item in enumerate(self.pending):
|
||||||
nodeindex = i % num_available
|
nodeindex = i % num_available
|
||||||
node, pending = available[nodeindex]
|
node, pending = available[nodeindex]
|
||||||
@@ -144,7 +156,35 @@ class LoadScheduling:
|
|||||||
pending.append(item)
|
pending.append(item)
|
||||||
if i >= max_one_round:
|
if i >= max_one_round:
|
||||||
break
|
break
|
||||||
del self.pending[:i+1]
|
del self.pending[:i + 1]
|
||||||
|
|
||||||
|
|
||||||
|
def report_collection_diff(from_collection, to_collection, from_id, to_id):
|
||||||
|
"""Report the collected test difference between two nodes.
|
||||||
|
|
||||||
|
:returns: True if collections are equal.
|
||||||
|
|
||||||
|
:raises: AssertionError with a detailed error message describing the
|
||||||
|
difference between the collections.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if from_collection == to_collection:
|
||||||
|
return True
|
||||||
|
|
||||||
|
diff = difflib.unified_diff(
|
||||||
|
from_collection,
|
||||||
|
to_collection,
|
||||||
|
fromfile=from_id,
|
||||||
|
tofile=to_id,
|
||||||
|
)
|
||||||
|
error_message = (
|
||||||
|
u'Different tests were collected between {from_id} and {to_id}. '
|
||||||
|
u'The difference is:\n'
|
||||||
|
u'{diff}'
|
||||||
|
).format(from_id=from_id, to_id=to_id, diff='\n'.join(diff))
|
||||||
|
|
||||||
|
raise AssertionError(error_message)
|
||||||
|
|
||||||
|
|
||||||
class Interrupted(KeyboardInterrupt):
|
class Interrupted(KeyboardInterrupt):
|
||||||
""" signals an immediate interruption. """
|
""" signals an immediate interruption. """
|
||||||
|
|||||||
Reference in New Issue
Block a user