topotest: improve json_cmp assert output

Create a specialized assert and json_cmp() result to improve the
comparison output. With this we also got a way to display all comparison
failures instead of just the first one.
This commit is contained in:
Rafael Zalamena 2017-06-29 12:18:46 -03:00 committed by Donald Sharp
parent 8833a8387f
commit 3668ed8dc2
2 changed files with 44 additions and 8 deletions

View File

@ -3,6 +3,7 @@ Topotest conftest.py file.
""" """
from lib.topogen import get_topogen from lib.topogen import get_topogen
from lib.topotest import json_cmp_result
import pytest import pytest
def pytest_addoption(parser): def pytest_addoption(parser):
@ -27,3 +28,15 @@ def pytest_runtest_call():
tgen.mininet_cli() tgen.mininet_cli()
pytest.exit('the topology executed successfully') pytest.exit('the topology executed successfully')
def pytest_assertrepr_compare(op, left, right):
"""
Show proper assertion error message for json_cmp results.
"""
json_result = left
if not isinstance(json_result, json_cmp_result):
json_result = right
if not isinstance(json_result, json_cmp_result):
return None
return json_result.errors

View File

@ -42,6 +42,20 @@ from mininet.link import Intf
from time import sleep from time import sleep
class json_cmp_result(object):
"json_cmp result class for better assertion messages"
def __init__(self):
self.errors = []
def add_error(self, error):
"Append error message to the result"
self.errors.append(error)
def has_errors(self):
"Returns True if there were errors, otherwise False."
return len(self.errors) > 0
def json_cmp(d1, d2, reason=False): def json_cmp(d1, d2, reason=False):
""" """
@ -54,30 +68,39 @@ def json_cmp(d1, d2, reason=False):
Note: key absence can be tested by adding a key with value `None`. Note: key absence can be tested by adding a key with value `None`.
""" """
squeue = [(d1, d2)] squeue = [(d1, d2, 'json')]
result = json_cmp_result()
for s in squeue: for s in squeue:
nd1, nd2 = s nd1, nd2, parent = s
s1, s2 = set(nd1), set(nd2) s1, s2 = set(nd1), set(nd2)
# Expect all required fields to exist. # Expect all required fields to exist.
s2_req = set([key for key in nd2 if nd2[key] is not None]) s2_req = set([key for key in nd2 if nd2[key] is not None])
diff = s2_req - s1 diff = s2_req - s1
if diff != set({}): if diff != set({}):
return 'expected keys "{}" in "{}"'.format(diff, str(nd1)) result.add_error('expected key(s) {} in {} (have {})'.format(
str(list(diff)), parent, str(list(s1))))
for key in s2.intersection(s1): for key in s2.intersection(s1):
# Test for non existence of key in d2 # Test for non existence of key in d2
if nd2[key] is None: if nd2[key] is None:
return '"{}" should not exist in "{}"'.format(key, str(nd1)) result.add_error('"{}" should not exist in {} (have {})'.format(
key, parent, str(s1)))
continue
# If nd1 key is a dict, we have to recurse in it later. # If nd1 key is a dict, we have to recurse in it later.
if isinstance(nd2[key], type({})): if isinstance(nd2[key], type({})):
squeue.append((nd1[key], nd2[key])) nparent = '{}["{}"]'.format(parent, key)
squeue.append((nd1[key], nd2[key], nparent))
continue continue
# Compare JSON values # Compare JSON values
if nd1[key] != nd2[key]: if nd1[key] != nd2[key]:
return '"{}" value is different ("{}" != "{}")'.format( result.add_error(
key, str(nd1[key]), str(nd2[key]) '{}["{}"] value is different (have "{}", expected "{}")'.format(
) parent, key, str(nd1[key]), str(nd2[key])))
continue
if result.has_errors():
return result
return None return None