Last active
April 3, 2017 11:35
-
-
Save rmerkushin/d416da3d2e032ca0d949d4cf8266b50c to your computer and use it in GitHub Desktop.
Function for checking equality of two tables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
from dateutil import parser | |
from colorclass import Color | |
from colorclass.toggles import disable_all_colors | |
from terminaltables import AsciiTable | |
from terminaltables import SingleTable | |
from behave.configuration import Configuration | |
def _highlight_row(row: list, color: str) -> list: | |
"""Wraps every cell in row in specific Color""" | |
return [Color('{{{0}}}{1}{{/{0}}}'.format(color, cell)) for cell in row] | |
def _mark_rows_as(mark: str, rows: list, idx_start: int) -> list: | |
"""Wraps every cell in rows in Color(red) with row mark""" | |
return [[Color('{{red}}{0} ({1}){{/red}}'.format(idx_start + idx, mark))] | |
+ _highlight_row(row, 'red') for idx, row in enumerate(rows)] | |
def _mark_cell_as_passed(expected: str) -> Color: | |
"""Wrap cell in Color(green)""" | |
return Color('{{green}}{}{{/green}}'.format(expected)) | |
def _mark_cell_as_failed(expected: str, actual: str) -> Color: | |
"""Wraps cell in Color(red) with info about comparison""" | |
return Color('{{red}}expected: {0}{{/red}}\n{{red}}actual: {1}{{/red}}'.format(expected, actual)) | |
def assert_tables_are_equal(expected: list, actual: list, header: list = None, | |
title: str = None, datetime: bool = False, dt_delta: int = 60) -> None: | |
""" | |
Checks equality of two tables (for Behave test framework) | |
:param expected: expected table | |
:param actual: actual table | |
:param header: header for table with comparison results | |
:param title: title for table with comparison results | |
:param datetime: if true, compares time strings by delta. | |
Time strings should be present in format with `$dt=<timestamp>`. | |
More information about possible time format can be found here: https://dateutil.readthedocs.io/en/stable/parser.html | |
Example: $dt=2016-12-28 12:18:43.675448 | |
:param dt_delta: delta for time comparison (seconds) | |
""" | |
failed = False | |
table_data = [] | |
missing_rows = None | |
surplus_rows = None | |
len_expected = len(expected) | |
len_actual = len(actual) | |
if len_expected > len_actual: | |
missing_rows = expected[len_actual:] | |
expected = expected[:len_actual] | |
elif len_actual > len_expected: | |
surplus_rows = actual[len_expected:] | |
actual = actual[:len_expected] | |
for row_exp, row_act in zip(expected, actual): | |
if row_exp == row_act: | |
table_data.append(_highlight_row(row_exp, 'green')) | |
else: | |
row = [] | |
for cell_exp, cell_act in zip(row_exp, row_act): | |
if cell_exp == cell_act: | |
cell = _mark_cell_as_passed(cell_exp) | |
row.append(cell) | |
elif datetime and cell_exp.startswith('$dt='): | |
exp = parser.parse(cell_exp.split('=')[1]) | |
act = parser.parse(cell_act) | |
delta = exp - act | |
if math.fabs(delta.total_seconds()) > dt_delta: | |
failed = True | |
cell = _mark_cell_as_failed(cell_exp.split('=')[1], cell_act) | |
row.append(cell) | |
else: | |
cell = _mark_cell_as_passed(cell_act) | |
row.append(cell) | |
else: | |
failed = True | |
cell = _mark_cell_as_failed(cell_exp, cell_act) | |
row.append(cell) | |
table_data.append(row) | |
table_data = [[str(idx + 1)] + row for idx, row in enumerate(table_data)] | |
if missing_rows: | |
failed = True | |
message = 'Actual table has missing rows:\n' | |
table_data += _mark_rows_as('missing', missing_rows, len(table_data) + 1) | |
elif surplus_rows: | |
failed = True | |
message = 'Actual table has surplus rows:\n' | |
table_data += _mark_rows_as('surplus', surplus_rows, len(table_data) + 1) | |
else: | |
message = 'Tables are not equals:\n' | |
if header: | |
table_data.insert(0, ['№'] + header) | |
if ('ttest_out', 'console') in Configuration().userdata.items(): | |
table = SingleTable(table_data) | |
else: | |
disable_all_colors() | |
table = AsciiTable(table_data) | |
table.inner_row_border = True | |
table.title = title | |
if failed: | |
raise AssertionError(message + table.table) | |
else: | |
print('Tables are equals:\n{}\n'.format(table.table)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment