diff --git a/energyplus_regressions/__init__.py b/energyplus_regressions/__init__.py index caaa52c..c777832 100644 --- a/energyplus_regressions/__init__.py +++ b/energyplus_regressions/__init__.py @@ -1,2 +1,2 @@ NAME = 'energyplus_regressions' -VERSION = '2.1.3' +VERSION = '2.1.4' diff --git a/energyplus_regressions/diffs/table_diff.py b/energyplus_regressions/diffs/table_diff.py index b45e8a8..1bf8fa4 100755 --- a/energyplus_regressions/diffs/table_diff.py +++ b/energyplus_regressions/diffs/table_diff.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import unicode_literals """Takes two E+ html output files and compares them usage: @@ -36,6 +34,7 @@ __copyright__ = "Copyright (c) 2009 Santosh Philip and Amir Roth 2013" __license__ = "GNU General Public License Version 3" +from pathlib import Path import sys import getopt import os.path @@ -45,8 +44,8 @@ help_message = __doc__ -path = os.path.dirname(__file__) -script_dir = os.path.abspath(path) +this_file = Path(__file__).resolve() +script_dir = this_file.parent title_css = """ tuple[float | str, float | str, str]: if x == y: return 0, 0, 'equal' - # noinspection PyBroadException try: - diff = 'equal' - fx = float(x) fy = float(y) - abs_diff = abs(fx - fy) - - # the following two lines were here, but I don't see how they could be hit, I'm commenting for now - # if abs_diff == 0.0: - # return 0, 0, 'equal' - rel_diff = abs((fx - fy) / fx) if abs(fx) > abs(fy) else abs((fy - fx) / fy) - + diff = 'equal' if abs_diff > abs_thresh and rel_diff > rel_thresh: diff = 'big' elif (0 < abs_diff <= abs_thresh) or (0 < rel_diff <= rel_thresh): diff = 'small' - # the following else clause was here, but again, I don't see how it could be hit, commenting - # else: - # diff = 'equal' return abs_diff, rel_diff, diff except ValueError: # if we couldn't get a float out of it, we are doing string comparison, check case-insensitively before leaving if x.lower().strip() == y.lower().strip(): return 0, 0, 'equal' else: - return '%s vs %s' % (x, y), '%s vs %s' % (x, y), 'stringdiff' + return f'{x} vs {y}', f'{x} vs {y}', 'stringdiff' def prev_sib(entity): @@ -235,7 +222,8 @@ def hdict2soup(soup, heading, num, hdict, tdict, horder): # Convert html table to heading dictionary (and header list) in single step -def table2hdict_horder(table): +def table2hdict_horder(table, table_a=None): + # If table_a_hdict is passed in, we can try to match the row order to avoid diffs just due to row order hdict = {} horder = [] trows = table('tr') @@ -250,7 +238,56 @@ def table2hdict_horder(table): hdict[hcontents] = [] horder.append(hcontents) - for trow in trows[1:]: + # Assume we are going to just loop over the rows and compare the data + search_rows = trows[1:] + + # But we can handle it specially if we passed in table_a and it's just a valid reorder + # There are some weird things to consider here though. For example, some tables have multiple entirely blank + # rows, just there for visual spacing. Also there are tables where the far left entry is not unique. + # Consider the End Uses by Subcategory table. One row starts with "Heating" and then "General". + # The next row then has nothing in the first column, but the second column is "Boiler". + # This implies that "Heating" was a grouping, and "General" or "Boiler" is the actual subcategory. + # I think the only way to handle this robustly would be to use the entire + # row as the key, which is annoying, but should work well. + if table_a: + # process the rows of the "base" table_a that was provided into a list of search keys + trows_a = table_a('tr') + table_a_row_order = [] + for trow in trows_a[1:]: + search_key = [] + for tcol in trow('td'): + if tcol.contents: + search_key.append(tcol.contents[0]) + else: # pragma: no cover + # I really don't think we can make it here while searching, but I don't want to accidentally crash + search_key.append("") + table_a_row_order.append(search_key) + # process the rows of the "mod" table that was provided into a list of search keys + found_table_b_row_order = [] + for trow in trows[1:]: + search_key = [] + for tcol in trow('td'): + if tcol.contents: + search_key.append(tcol.contents[0]) + else: # pragma: no cover + # I really don't think we can make it here while searching, but I don't want to accidentally crash + search_key.append("") + found_table_b_row_order.append(search_key) + # it's the same order exactly, skip any searching and just run with search_rows as-is + if table_a_row_order == found_table_b_row_order: + pass + # if not exactly the same but overall the same stuff, it's reordered and we can match things up + elif sorted(table_a_row_order) == sorted(found_table_b_row_order): + # now just build the list of trows to search by index based on table a order + search_rows = [] + for to_find_val in table_a_row_order: + for search_row_index, trow in enumerate(trows[1:]): + if found_table_b_row_order[search_row_index] == to_find_val: + search_rows.append(trow) + break + + # whether it was reordered or just using the literal order, build out the hdict instance to pass back + for trow in search_rows: for htd, td in zip(trows[0]('td'), trow('td')): try: hcontents = htd.contents[0] @@ -317,7 +354,10 @@ def make_err_table_row(err_soup, tabletag, uheading, count_of_tables, abs_diff_f 'size mismatch' if size_error > 0 else 'not in 1' if not_in_1 > 0 else 'not in 2' if not_in_2 > 0 else '') -def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file, err_file, summary_file): +def table_diff( + thresh_dict: ThreshDict, input_file_1: str, input_file_2: str, abs_diff_file: str, + rel_diff_file: str, err_file: str, summary_file: str +): """ Compares two xxxTable.html files returning ( @@ -326,32 +366,33 @@ def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file <#size_diff>, <#not_in_file1>, <#not_in_file2> ) """ + file_1 = Path(input_file_1) + file_2 = Path(input_file_2) - case_name = inputfile1.split(os.sep)[-2] + case_name = file_1.parent.name # Test for existence of input files - if not os.path.exists(inputfile1): - return 'unable to open file <%s>' % inputfile1, 0, 0, 0, 0, 0, 0, 0, 0 - if not os.path.exists(inputfile2): - return 'unable to open file <%s>' % inputfile2, 0, 0, 0, 0, 0, 0, 0, 0 + if not file_1.exists(): + return 'unable to open file <%s>' % input_file_1, 0, 0, 0, 0, 0, 0, 0, 0 + if not file_2.exists(): + return 'unable to open file <%s>' % input_file_2, 0, 0, 0, 0, 0, 0, 0, 0 - with open(inputfile1, 'rb') as f_1: + with open(file_1, 'rb') as f_1: txt1 = f_1.read().decode('utf-8', errors='ignore') - with open(inputfile2, 'rb') as f_2: + with open(file_2, 'rb') as f_2: txt2 = f_2.read().decode('utf-8', errors='ignore') - pagetitle = '%s vs %s' % (os.path.basename(inputfile1), os.path.basename(inputfile2)) + page_title = f'{file_1.name} vs {file_2.name}' # Error soup - err_soup = BeautifulSoup(title_css % (pagetitle + ' -- summary', the_css,), - features='html.parser') + err_soup = BeautifulSoup(title_css % (page_title + ' -- summary', the_css,), features='html.parser') # Abs diff soup - abs_diff_soup = BeautifulSoup(title_css % (pagetitle + ' -- absolute differences', the_css,), + abs_diff_soup = BeautifulSoup(title_css % (page_title + ' -- absolute differences', the_css,), features='html.parser') # Rel diff soup - rel_diff_soup = BeautifulSoup(title_css % (pagetitle + ' -- relative differences', the_css,), + rel_diff_soup = BeautifulSoup(title_css % (page_title + ' -- relative differences', the_css,), features='html.parser') # Make error table @@ -381,9 +422,9 @@ def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file uheadings2.append(get_table_unique_heading(table)) if any([x is None for x in uheadings1]): - return 'malformed comment/table structure in <%s>' % inputfile1, 0, 0, 0, 0, 0, 0, 0, 0 + return 'malformed comment/table structure in <%s>' % input_file_1, 0, 0, 0, 0, 0, 0, 0, 0 if any([x is None for x in uheadings2]): - return 'malformed comment/table structure in <%s>' % inputfile2, 0, 0, 0, 0, 0, 0, 0, 0 + return 'malformed comment/table structure in <%s>' % input_file_2, 0, 0, 0, 0, 0, 0, 0, 0 uhset1 = set(uheadings1) uhset2 = set(uheadings2) @@ -414,6 +455,14 @@ def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file uheading1 = uheadings1[i1] + # There are some (for now one) tables that we will want to skip entirely because they are not useful for + # throwing regressions, add search keys to this list to skip them + completely_skippable_table_keys = [ + 'Object Count Summary_Entire Facility_Input Fields' + ] + if any([x in uheading1 for x in completely_skippable_table_keys]): + continue + # Table missing in second input file if uheading1 not in uhset_match: table_not_in_2 = 1 @@ -435,8 +484,19 @@ def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file table_not_in_1, table_not_in_2) continue + # create a list of order-dependent table uheading keys, tables that include these keys in the name + # these will use strict row order enforcement + row_order_dependent_table_keys = ['Monthly', 'Topology'] + + # always process the first table into a base hdict hdict1, horder1 = table2hdict_horder(table1) - hdict2, horder2 = table2hdict_horder(table2) + + # if we are in a row order dependent table, don't pass table1 as a baseline, just use the literal in-place order + if any(k in uheading1 for k in row_order_dependent_table_keys): + hdict2, horder2 = table2hdict_horder(table2) + # but for all other tables, we can use the first table as a baseline to carefully match up the rows + else: + hdict2, horder2 = table2hdict_horder(table2, table1) # honestly, if the column headings have changed, this should be an indicator to all reviewers that this needs # up close investigation. As such, we are going to trigger the following things: @@ -556,7 +616,7 @@ def table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file count_of_size_error, count_of_not_in_1, count_of_not_in_2) -def main(argv=None): # pragma: no cover +def main(argv=None) -> int: # pragma: no cover if argv is None: argv = sys.argv try: @@ -565,19 +625,9 @@ def main(argv=None): # pragma: no cover print(sys.argv[0].split("/")[-1] + ": " + str(msg) + "\n\t for help use --help") return -1 - # Test for correct number of arguments - # prog_name = os.path.basename(sys.argv[0]) - # if len(args) == 5: - [inputfile1, inputfile2, abs_diff_file, rel_diff_file, err_file, summary_file] = args - # else: - # info('%s: incorrect operands: Try %s -h for more info' % (prog_name, prog_name)) - # return -1 - - # Load diffing threshold dictionary + [input_file_1, input_file_2, abs_diff_file, rel_diff_file, err_file, summary_file] = args thresh_dict = ThreshDict(os.path.join(script_dir, 'math_diff.config')) - - # run the main program. - table_diff(thresh_dict, inputfile1, inputfile2, abs_diff_file, rel_diff_file, err_file, summary_file) + table_diff(thresh_dict, input_file_1, input_file_2, abs_diff_file, rel_diff_file, err_file, summary_file) return 0 diff --git a/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_base.htm b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_base.htm new file mode 100644 index 0000000..661ccee --- /dev/null +++ b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_base.htm @@ -0,0 +1,209 @@ + + + + OutPatientHealthCare RUNPERIOD 3 ** Denver-Aurora-Buckley AFB CO USA TMY3 WMO#=724695 + 2025-05-15 + 09:19:23 + - EnergyPlus + + + + +

Program Version:EnergyPlus, Version 25.2.0-1d1af7dd68, YMD=2025.05.15 09:19

+

Tabular Output Report in Format: HTML

+

Building: OutPatientHealthCare

+

Environment: RUNPERIOD 3 ** Denver-Aurora-Buckley AFB CO USA TMY3 WMO#=724695

+

Simulation Timestamp: 2025-05-15 + 09:19:23

+
+ +

Report: Annual Building Utility Performance Summary

+

For: Entire Facility

+

Timestamp: 2025-05-15 + 09:19:23

+Values gathered over 0.00 hours

+WARNING: THE REPORT DOES NOT REPRESENT A FULL ANNUAL SIMULATION.

+

+ +

Report: Energy Meters

+

For: Entire Facility

+

Timestamp: 2025-05-15 + 09:19:23

+Annual and Peak Values - Electricity

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Electricity Annual Value [GJ]Electricity Minimum Value [W]Timestamp of Minimum {TIMESTAMP}Electricity Maximum Value [W]Timestamp of Maximum {TIMESTAMP}
ElectricityNet:Plant 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
Cogeneration:ElectricityNet 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
General:Cogeneration:ElectricityNet 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
Electricity:HVAC 12.30 30407.2421-JUL-04:15 173684.0421-DEC-07:15
Fans:Electricity 2.36 6859.4121-DEC-00:30 32834.8521-JUL-15:00
General:Fans:Electricity 2.36 6859.4121-DEC-00:30 32834.8521-JUL-15:00
Heating:Electricity 4.43 0.0021-JUL-00:15 140841.6121-DEC-07:15
+

+Monthly Precipitation Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Monthly Total Precipitation from .epw [mm]Monthly Total Hours of Rain from .epwMonthly Total Precipitation in Site:Precipitation [mm]Monthly Total Roof Irrigation Depth [mm]Monthly Total Rain Collection Volume [m3]
Jan 0.20 0   
Feb 0.10 0   
Mar 0.00 0   
Apr 0.00 0   
May 0.00 0   
Jun 0.00 0   
Jul 0.00 0   
Aug 0.00 0   
Sep 0.00 0   
Oct 0.00 0   
Nov 0.00 0   
Dec 0.00 0   
+

+ + diff --git a/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_mod.htm b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_mod.htm new file mode 100644 index 0000000..e219e46 --- /dev/null +++ b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_row_reorder_mod.htm @@ -0,0 +1,209 @@ + + + + OutPatientHealthCare RUNPERIOD 3 ** Denver-Aurora-Buckley AFB CO USA TMY3 WMO#=724695 + 2025-05-15 + 09:19:23 + - EnergyPlus + + + + +

Program Version:EnergyPlus, Version 25.2.0-1d1af7dd68, YMD=2025.05.15 09:19

+

Tabular Output Report in Format: HTML

+

Building: OutPatientHealthCare

+

Environment: RUNPERIOD 3 ** Denver-Aurora-Buckley AFB CO USA TMY3 WMO#=724695

+

Simulation Timestamp: 2025-05-15 + 09:19:23

+
+ +

Report: Annual Building Utility Performance Summary

+

For: Entire Facility

+

Timestamp: 2025-05-15 + 09:19:23

+Values gathered over 0.00 hours

+WARNING: THE REPORT DOES NOT REPRESENT A FULL ANNUAL SIMULATION.

+

+ +

Report: Energy Meters

+

For: Entire Facility

+

Timestamp: 2025-05-15 + 09:19:23

+Annual and Peak Values - Electricity

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Electricity Annual Value [GJ]Electricity Minimum Value [W]Timestamp of Minimum {TIMESTAMP}Electricity Maximum Value [W]Timestamp of Maximum {TIMESTAMP}
ElectricityNet:Plant 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
Cogeneration:ElectricityNet 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
Fans:Electricity 2.36 6859.4121-DEC-00:30 32834.8521-JUL-15:00
General:Fans:Electricity 2.36 6859.4121-DEC-00:30 32834.8521-JUL-15:00
General:Cogeneration:ElectricityNet 25.58 79056.2721-DEC-20:15 247648.4021-JUL-15:00
Electricity:HVAC 12.30 30407.2421-JUL-04:15 173684.0421-DEC-07:15
Heating:Electricity 4.43 0.0021-JUL-00:15 140841.6121-DEC-07:15
+

+Monthly Precipitation Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Monthly Total Precipitation from .epw [mm]Monthly Total Hours of Rain from .epwMonthly Total Precipitation in Site:Precipitation [mm]Monthly Total Roof Irrigation Depth [mm]Monthly Total Rain Collection Volume [m3]
Feb 0.10 0   
Jan 0.20 0   
Mar 0.00 0   
Apr 0.00 0   
May 0.00 0   
Jun 0.00 0   
Jul 0.00 0   
Aug 0.00 0   
Sep 0.00 0   
Oct 0.00 0   
Nov 0.00 0   
Dec 0.00 0   
+

+ + diff --git a/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_base.htm b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_base.htm new file mode 100644 index 0000000..24187fb --- /dev/null +++ b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_base.htm @@ -0,0 +1,137 @@ + + + + Bldg DENVER CENTENNIAL ANN CLG 1% CONDNS DB=>MWB ** + 2018-11-20 + 17:26:37 + - EnergyPlus + + + +

Table of Contents

+ +

Program Version:EnergyPlus, Version 9.0.1-a7c9cc14ce, YMD=2018.11.20 17:26

+

Tabular Output Report in Format: HTML

+

Building: Bldg

+

Environment: DENVER CENTENNIAL ANN CLG 1% CONDNS DB=>MWB **

+

Simulation Timestamp: 2018-11-20 + 17:26:37

+
+

Table of Contents

+ +

Report: Annual Building Utility Performance Summary

+

For: Entire Facility

+

Timestamp: 2018-11-20 + 17:26:37

+Values gathered over 0.00 hours

+WARNING: THE REPORT DOES NOT REPRESENT A FULL ANNUAL SIMULATION.

+

+Site and Source Energy

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Total Energy [GJ]Energy Per Total Building Area [MJ/m2]Energy Per Conditioned Building Area [MJ/m2]
Total Site Energy 0.00 0.00 0.00
Net Site Energy 0.00 0.00 0.00
Total Source Energy 0.00 0.00 0.00
Net Source Energy 0.00 0.00 0.00
+

+Site to Source Energy Conversion Factors

+ + + + + + + + + + + + + +
Site=>Source Conversion Factor
Electricity 3.167
Natural Gas 1.084
+

+Building Area

+ + + + + + + + + + + + + + + + + +
Area [m2]
Total Building Area 232.26
Net Conditioned Building Area 232.26
Unconditioned Building Area 0.00
+

+Input Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Count
IDF Objects 3836
Defaulted Fields 3292
Fields with Defaults 15207
Autosized Fields 991
Autosizable Fields 1241
Autocalculated Fields 1456
Autocalculatable Fields 2969
+

+
+ + diff --git a/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_mod.htm b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_mod.htm new file mode 100644 index 0000000..8b6b605 --- /dev/null +++ b/energyplus_regressions/tests/diffs/tbl_resources/eplustbl_skips_some_tables_mod.htm @@ -0,0 +1,137 @@ + + + + Bldg DENVER CENTENNIAL ANN CLG 1% CONDNS DB=>MWB ** + 2018-11-20 + 17:26:37 + - EnergyPlus + + + +

Table of Contents

+ +

Program Version:EnergyPlus, Version 9.0.1-a7c9cc14ce, YMD=2018.11.20 17:26

+

Tabular Output Report in Format: HTML

+

Building: Bldg

+

Environment: DENVER CENTENNIAL ANN CLG 1% CONDNS DB=>MWB **

+

Simulation Timestamp: 2018-11-20 + 17:26:37

+
+

Table of Contents

+ +

Report: Annual Building Utility Performance Summary

+

For: Entire Facility

+

Timestamp: 2018-11-20 + 17:26:37

+Values gathered over 0.00 hours

+WARNING: THE REPORT DOES NOT REPRESENT A FULL ANNUAL SIMULATION.

+

+Site and Source Energy

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Total Energy [GJ]Energy Per Total Building Area [MJ/m2]Energy Per Conditioned Building Area [MJ/m2]
Total Site Energy 0.00 0.00 0.00
Net Site Energy 0.00 0.00 0.00
Total Source Energy 0.00 0.00 0.00
Net Source Energy 0.00 0.00 0.00
+

+Site to Source Energy Conversion Factors

+ + + + + + + + + + + + + +
Site=>Source Conversion Factor
Electricity 3.167
Natural Gas 1.084
+

+Building Area

+ + + + + + + + + + + + + + + + + +
Area [m2]
Total Building Area 232.26
Net Conditioned Building Area 232.26
Unconditioned Building Area 0.00
+

+Input Fields

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Count
IDF Objects 3836
Defaulted Fields 3292
Fields with Defaults 15207
Autosized Fields 992
Autosizable Fields 1242
Autocalculated Fields 1456
Autocalculatable Fields 2969
+

+
+ + diff --git a/energyplus_regressions/tests/diffs/test_table_diff.py b/energyplus_regressions/tests/diffs/test_table_diff.py index 6747d3c..221354d 100644 --- a/energyplus_regressions/tests/diffs/test_table_diff.py +++ b/energyplus_regressions/tests/diffs/test_table_diff.py @@ -34,6 +34,26 @@ def test_identical_files(self): self.assertEqual(0, response[7]) # in file 2 but not in file 1 self.assertEqual(0, response[8]) # in file 1 but not in file 2 + def test_skips_some_tables(self): + response = table_diff( + self.thresh_dict, + os.path.join(self.diff_files_dir, 'eplustbl_skips_some_tables_base.htm'), + os.path.join(self.diff_files_dir, 'eplustbl_skips_some_tables_mod.htm'), + os.path.join(self.temp_output_dir, 'abs_diff.htm'), + os.path.join(self.temp_output_dir, 'rel_diff.htm'), + os.path.join(self.temp_output_dir, 'math_diff.log'), + os.path.join(self.temp_output_dir, 'summary.htm'), + ) + self.assertEqual('', response[0]) # diff status + self.assertEqual(4, response[1]) # count_of_tables + self.assertEqual(0, response[2]) # big diffs + self.assertEqual(0, response[3]) # small diffs + self.assertEqual(17, response[4]) # equals # only includes the tables that were compared, not skipped + self.assertEqual(0, response[5]) # string diffs + self.assertEqual(0, response[6]) # size errors + self.assertEqual(0, response[7]) # in file 2 but not in file 1 + self.assertEqual(0, response[8]) # in file 1 but not in file 2 + def test_invalid_file_1(self): response = table_diff( self.thresh_dict, @@ -292,7 +312,7 @@ def test_weird_unicode_issue(self): self.assertEqual(155, response[1]) # count_of_tables self.assertEqual(334, response[2]) # big diffs self.assertEqual(67, response[3]) # small diffs - self.assertEqual(3763, response[4]) # equals + self.assertEqual(3756, response[4]) # equals self.assertEqual(21, response[5]) # string diffs self.assertEqual(0, response[6]) # size errors self.assertEqual(0, response[7]) # in file 2 but not in file 1 @@ -313,7 +333,7 @@ def test_unicode_but_not_utf8_encoded_table(self): self.assertEqual(155, response[1]) # count_of_tables self.assertEqual(334, response[2]) # big diffs self.assertEqual(67, response[3]) # small diffs - self.assertEqual(3763, response[4]) # equals + self.assertEqual(3756, response[4]) # equals self.assertEqual(21, response[5]) # string diffs self.assertEqual(0, response[6]) # size errors self.assertEqual(0, response[7]) # in file 2 but not in file 1 @@ -496,6 +516,27 @@ def test_odd_column_heading_mismatch_diff(self): self.assertEqual(0, response[7]) # in file 2 but not in file 1 self.assertEqual(0, response[8]) # in file 1 but not in file 2 + def test_reordering_is_ok_sometimes(self): + # This table has a table with the rows reordered + response = table_diff( + self.thresh_dict, + os.path.join(self.diff_files_dir, 'eplustbl_row_reorder_base.htm'), + os.path.join(self.diff_files_dir, 'eplustbl_row_reorder_mod.htm'), + os.path.join(self.temp_output_dir, 'abs_diff.htm'), + os.path.join(self.temp_output_dir, 'rel_diff.htm'), + os.path.join(self.temp_output_dir, 'math_diff.log'), + os.path.join(self.temp_output_dir, 'summary.htm'), + ) + self.assertEqual('', response[0]) # diff status + self.assertEqual(2, response[1]) # count_of_tables + self.assertEqual(2, response[2]) # big diffs # Only because of the time-based table reordered + self.assertEqual(0, response[3]) # small diffs + self.assertEqual(93, response[4]) # equals + self.assertEqual(0, response[5]) # string diffs + self.assertEqual(0, response[6]) # size errors + self.assertEqual(0, response[7]) # in file 2 but not in file 1 + self.assertEqual(0, response[8]) # in file 1 but not in file 2 + # it seems like this is something that table_diff just cannot handle. The duplicate empty column heading is causing # major problems. I'm going to skip this test for now, but leave the two table diff resource files in place # so that we could try to investigate later if we ever wanted.