DataComparerLibrary 0.843__tar.gz → 0.845__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datacomparerlibrary-0.843/src/DataComparerLibrary.egg-info → datacomparerlibrary-0.845}/PKG-INFO +60 -6
- datacomparerlibrary-0.843/PKG-INFO → datacomparerlibrary-0.845/README.rst +47 -23
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/setup.py +3 -1
- datacomparerlibrary-0.845/src/DataComparerLibrary/arraycomparer.py +206 -0
- datacomparerlibrary-0.845/src/DataComparerLibrary/datacomparer.py +135 -0
- datacomparerlibrary-0.845/src/DataComparerLibrary/datetimehandler.py +100 -0
- datacomparerlibrary-0.845/src/DataComparerLibrary/report.py +44 -0
- datacomparerlibrary-0.845/src/DataComparerLibrary/version.py +3 -0
- datacomparerlibrary-0.843/README.rst → datacomparerlibrary-0.845/src/DataComparerLibrary.egg-info/PKG-INFO +77 -3
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/SOURCES.txt +3 -0
- datacomparerlibrary-0.843/src/DataComparerLibrary/datacomparer.py +0 -487
- datacomparerlibrary-0.843/src/DataComparerLibrary/version.py +0 -3
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/LICENSE.txt +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/pyproject.toml +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/setup.cfg +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/__init__.py +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/datasorter.py +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/delimitertranslator.py +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/fileconverter.py +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/tools.py +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/dependency_links.txt +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/top_level.txt +0 -0
- {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/test/test1.py +0 -0
{datacomparerlibrary-0.843/src/DataComparerLibrary.egg-info → datacomparerlibrary-0.845}/PKG-INFO
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: DataComparerLibrary
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: For comparing csv-files
|
|
3
|
+
Version: 0.845
|
|
4
|
+
Summary: For comparing csv-files, 2d-array with a csv-file or 2d-arrays. For comparing text-files, text variable with a text-file or text variables. Including a sorting module.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author: René Philip Zuijderduijn
|
|
7
7
|
Author-email: datacomparerlibrary@outlook.com
|
|
@@ -15,8 +15,18 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
20
|
Description-Content-Type: text/x-rst
|
|
19
21
|
License-File: LICENSE.txt
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: keywords
|
|
28
|
+
Dynamic: license
|
|
29
|
+
Dynamic: summary
|
|
20
30
|
|
|
21
31
|
===================
|
|
22
32
|
DataComparerLibrary
|
|
@@ -106,8 +116,12 @@ The DataComparerLibrary can be used for:
|
|
|
106
116
|
quotechar.
|
|
107
117
|
|
|
108
118
|
|
|
119
|
+
Comparing Data
|
|
120
|
+
--------------
|
|
121
|
+
|
|
122
|
+
|
|
109
123
|
Examples of using the DataComparerLibrary for comparing data in Python
|
|
110
|
-
|
|
124
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
111
125
|
|
|
112
126
|
Below there are some examples how to call the methods of the DataComparerLibrary in Python::
|
|
113
127
|
|
|
@@ -122,7 +136,7 @@ Below there are some examples how to call the methods of the DataComparerLibrary
|
|
|
122
136
|
|
|
123
137
|
|
|
124
138
|
Examples of using the DataComparerLibrary keywords for comparing data in Robot Framework
|
|
125
|
-
|
|
139
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
126
140
|
|
|
127
141
|
Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
|
|
128
142
|
|
|
@@ -146,7 +160,7 @@ Below there are some examples how to call the keywords of the DataComparerLibrar
|
|
|
146
160
|
|
|
147
161
|
|
|
148
162
|
Examples comparing Actual Data with Expected Data
|
|
149
|
-
|
|
163
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
150
164
|
|
|
151
165
|
Below there is an example of actual and expected data with some different cases.
|
|
152
166
|
|
|
@@ -185,6 +199,46 @@ Based on current datetime = 2023-09-06 19:04:00 (example):
|
|
|
185
199
|
+--------------+----------+--------------+---------------------------------+---------+-------------+
|
|
186
200
|
|
|
187
201
|
|
|
202
|
+
Comparing Text
|
|
203
|
+
--------------
|
|
204
|
+
|
|
205
|
+
Examples of using the DataComparerLibrary for comparing text in Python
|
|
206
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
207
|
+
|
|
208
|
+
Below there are some examples how to call the methods of the DataComparerLibrary in Python::
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
a = DataComparer
|
|
212
|
+
a.compare_text_files(self, actual_file, expected_file)
|
|
213
|
+
a.compare_text_variable_with_text_file(self, actual_text_input, expected_file)
|
|
214
|
+
a.compare_text_file_with_text_variable(self, actual_file, expected_text_input)
|
|
215
|
+
a.compare_text_variables(self, actual_text_input, expected_text_input)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
Examples of using the DataComparerLibrary keywords for comparing text in Robot Framework
|
|
219
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
220
|
+
|
|
221
|
+
Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
*** Settings ***
|
|
225
|
+
Library DataComparerLibrary
|
|
226
|
+
|
|
227
|
+
*** Test Cases ***
|
|
228
|
+
Testcase_DataComparer
|
|
229
|
+
Examples
|
|
230
|
+
|
|
231
|
+
*** Keywords ***
|
|
232
|
+
Examples
|
|
233
|
+
Run Keyword And Continue On Failure DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
234
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
235
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
236
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
237
|
+
DataComparerLibrary.Compare Text Variable With File ${actual_text_input} C:\\Users\\expected.txt
|
|
238
|
+
DataComparerLibrary.Compare Text File With Text Variable C:\\Users\\actual.txt ${expected_text_input}
|
|
239
|
+
DataComparerLibrary.Compare Text Variables ${actual_text_input} ${expected_text_input}
|
|
240
|
+
|
|
241
|
+
|
|
188
242
|
|
|
189
243
|
DataSorter
|
|
190
244
|
==========
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: DataComparerLibrary
|
|
3
|
-
Version: 0.843
|
|
4
|
-
Summary: For comparing csv-files or 2d-array with csv-file.
|
|
5
|
-
Home-page:
|
|
6
|
-
Author: René Philip Zuijderduijn
|
|
7
|
-
Author-email: datacomparerlibrary@outlook.com
|
|
8
|
-
License: Apache
|
|
9
|
-
Keywords: robotframework testing test-automation datacompare
|
|
10
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
-
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
12
|
-
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
-
Description-Content-Type: text/x-rst
|
|
19
|
-
License-File: LICENSE.txt
|
|
20
|
-
|
|
21
1
|
===================
|
|
22
2
|
DataComparerLibrary
|
|
23
3
|
===================
|
|
@@ -106,8 +86,12 @@ The DataComparerLibrary can be used for:
|
|
|
106
86
|
quotechar.
|
|
107
87
|
|
|
108
88
|
|
|
89
|
+
Comparing Data
|
|
90
|
+
--------------
|
|
91
|
+
|
|
92
|
+
|
|
109
93
|
Examples of using the DataComparerLibrary for comparing data in Python
|
|
110
|
-
|
|
94
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
111
95
|
|
|
112
96
|
Below there are some examples how to call the methods of the DataComparerLibrary in Python::
|
|
113
97
|
|
|
@@ -122,7 +106,7 @@ Below there are some examples how to call the methods of the DataComparerLibrary
|
|
|
122
106
|
|
|
123
107
|
|
|
124
108
|
Examples of using the DataComparerLibrary keywords for comparing data in Robot Framework
|
|
125
|
-
|
|
109
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
126
110
|
|
|
127
111
|
Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
|
|
128
112
|
|
|
@@ -146,7 +130,7 @@ Below there are some examples how to call the keywords of the DataComparerLibrar
|
|
|
146
130
|
|
|
147
131
|
|
|
148
132
|
Examples comparing Actual Data with Expected Data
|
|
149
|
-
|
|
133
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
150
134
|
|
|
151
135
|
Below there is an example of actual and expected data with some different cases.
|
|
152
136
|
|
|
@@ -185,6 +169,46 @@ Based on current datetime = 2023-09-06 19:04:00 (example):
|
|
|
185
169
|
+--------------+----------+--------------+---------------------------------+---------+-------------+
|
|
186
170
|
|
|
187
171
|
|
|
172
|
+
Comparing Text
|
|
173
|
+
--------------
|
|
174
|
+
|
|
175
|
+
Examples of using the DataComparerLibrary for comparing text in Python
|
|
176
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
177
|
+
|
|
178
|
+
Below there are some examples how to call the methods of the DataComparerLibrary in Python::
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
a = DataComparer
|
|
182
|
+
a.compare_text_files(self, actual_file, expected_file)
|
|
183
|
+
a.compare_text_variable_with_text_file(self, actual_text_input, expected_file)
|
|
184
|
+
a.compare_text_file_with_text_variable(self, actual_file, expected_text_input)
|
|
185
|
+
a.compare_text_variables(self, actual_text_input, expected_text_input)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
Examples of using the DataComparerLibrary keywords for comparing text in Robot Framework
|
|
189
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
190
|
+
|
|
191
|
+
Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
*** Settings ***
|
|
195
|
+
Library DataComparerLibrary
|
|
196
|
+
|
|
197
|
+
*** Test Cases ***
|
|
198
|
+
Testcase_DataComparer
|
|
199
|
+
Examples
|
|
200
|
+
|
|
201
|
+
*** Keywords ***
|
|
202
|
+
Examples
|
|
203
|
+
Run Keyword And Continue On Failure DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
204
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
205
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
206
|
+
DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
|
|
207
|
+
DataComparerLibrary.Compare Text Variable With File ${actual_text_input} C:\\Users\\expected.txt
|
|
208
|
+
DataComparerLibrary.Compare Text File With Text Variable C:\\Users\\actual.txt ${expected_text_input}
|
|
209
|
+
DataComparerLibrary.Compare Text Variables ${actual_text_input} ${expected_text_input}
|
|
210
|
+
|
|
211
|
+
|
|
188
212
|
|
|
189
213
|
DataSorter
|
|
190
214
|
==========
|
|
@@ -22,7 +22,7 @@ with open(join(this_directory, 'src', 'DataComparerLibrary', 'version.py')) as f
|
|
|
22
22
|
def main():
|
|
23
23
|
setup(name='DataComparerLibrary',
|
|
24
24
|
version=VERSION,
|
|
25
|
-
description="For comparing csv-files
|
|
25
|
+
description="For comparing csv-files, 2d-array with a csv-file or 2d-arrays. For comparing text-files, text variable with a text-file or text variables. Including a sorting module.",
|
|
26
26
|
long_description=README,
|
|
27
27
|
long_description_content_type="text/x-rst",
|
|
28
28
|
url="",
|
|
@@ -38,6 +38,8 @@ def main():
|
|
|
38
38
|
"Programming Language :: Python :: 3.9",
|
|
39
39
|
"Programming Language :: Python :: 3.10",
|
|
40
40
|
"Programming Language :: Python :: 3.11",
|
|
41
|
+
"Programming Language :: Python :: 3.12",
|
|
42
|
+
"Programming Language :: Python :: 3.13",
|
|
41
43
|
],
|
|
42
44
|
keywords='robotframework testing test-automation datacompare',
|
|
43
45
|
package_dir={'': 'src'},
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import fnmatch
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from DataComparerLibrary.datetimehandler import DatetimeHandler
|
|
5
|
+
from DataComparerLibrary.report import Report
|
|
6
|
+
from DataComparerLibrary.tools import Tools
|
|
7
|
+
|
|
8
|
+
class ArrayComparer:
|
|
9
|
+
def compare_data(self, actual_data, expected_data_including_templates, template_literals_dict):
|
|
10
|
+
difference_found = False
|
|
11
|
+
#
|
|
12
|
+
if actual_data and type(actual_data[0]) is not list: # only a single row
|
|
13
|
+
actual_data = [actual_data,] # add row to tuple of lenght 1
|
|
14
|
+
#
|
|
15
|
+
if expected_data_including_templates and type(expected_data_including_templates[0]) is not list: # only a single row
|
|
16
|
+
expected_data_including_templates = [expected_data_including_templates,] # add row to tuple of lenght 1
|
|
17
|
+
|
|
18
|
+
number_of_rows_actual_data = len(actual_data)
|
|
19
|
+
number_of_rows_expected_data = len(expected_data_including_templates)
|
|
20
|
+
|
|
21
|
+
number_of_rows = max(number_of_rows_actual_data, number_of_rows_expected_data)
|
|
22
|
+
|
|
23
|
+
Report.show_2d_array(self, "Actual data", actual_data, 20)
|
|
24
|
+
Report.show_2d_array(self, "Expected data", expected_data_including_templates, 20)
|
|
25
|
+
|
|
26
|
+
Report().show_header_differences_actual_and_expected_data()
|
|
27
|
+
|
|
28
|
+
for row_nr in range(number_of_rows):
|
|
29
|
+
if row_nr >= number_of_rows_actual_data:
|
|
30
|
+
difference_found = True
|
|
31
|
+
if len(expected_data_including_templates[row_nr]) == 0:
|
|
32
|
+
Report.show_differences_comparation_result(self, row_nr, 0, "", "", "Row actual data is not PRESENT. Row expected data is EMPTY.")
|
|
33
|
+
else:
|
|
34
|
+
Report.show_differences_comparation_result(self, row_nr, 0, "", expected_data_including_templates[row_nr][0], "Row actual data is not PRESENT.")
|
|
35
|
+
continue
|
|
36
|
+
#
|
|
37
|
+
if row_nr >= number_of_rows_expected_data:
|
|
38
|
+
difference_found = True
|
|
39
|
+
if len(actual_data[row_nr]) == 0:
|
|
40
|
+
Report.show_differences_comparation_result(self, row_nr, 0, "", "", "Row actual data is EMPTY. Row expected data is not PRESENT.")
|
|
41
|
+
else:
|
|
42
|
+
Report.show_differences_comparation_result(self, row_nr, 0, actual_data[row_nr][0], "", "Row expected data is not PRESENT.")
|
|
43
|
+
continue
|
|
44
|
+
#
|
|
45
|
+
number_of_columns_actual_data = len(actual_data[row_nr])
|
|
46
|
+
number_of_columns_expected_data = len(expected_data_including_templates[row_nr])
|
|
47
|
+
|
|
48
|
+
number_of_columns = max(number_of_columns_actual_data, number_of_columns_expected_data)
|
|
49
|
+
|
|
50
|
+
for column_nr in range(number_of_columns):
|
|
51
|
+
expected_data_including_date_template = None
|
|
52
|
+
expected_data_with_wildcard = None
|
|
53
|
+
skip_exception_rule_used = False
|
|
54
|
+
#
|
|
55
|
+
if column_nr >= number_of_columns_actual_data:
|
|
56
|
+
difference_found = True
|
|
57
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, "", expected_data_including_templates[row_nr][column_nr], "Column actual data is not PRESENT.")
|
|
58
|
+
continue
|
|
59
|
+
#
|
|
60
|
+
if column_nr >= number_of_columns_expected_data:
|
|
61
|
+
difference_found = True
|
|
62
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], "", "Column expected data is not PRESENT.")
|
|
63
|
+
continue
|
|
64
|
+
#
|
|
65
|
+
if actual_data[row_nr][column_nr] != expected_data_including_templates[row_nr][column_nr]:
|
|
66
|
+
# Replace literal templates with fixed external strings.
|
|
67
|
+
if template_literals_dict:
|
|
68
|
+
for i in range(0, len(template_literals_dict)):
|
|
69
|
+
# key = list(template_literals_dict.keys())[i]
|
|
70
|
+
# value = list(template_literals_dict.values())[i]
|
|
71
|
+
# print("key: ", key)
|
|
72
|
+
# print("value: ", value)
|
|
73
|
+
expected_data_including_templates[row_nr][column_nr] = expected_data_including_templates[row_nr][column_nr].replace(list(template_literals_dict.keys())[i], list(template_literals_dict.values())[i])
|
|
74
|
+
# print("actual_data[row_nr][column_nr]: \n", actual_data[row_nr][column_nr])
|
|
75
|
+
# print("expected_data_including_templates[row_nr][column_nr]: \n", expected_data_including_templates[row_nr][column_nr])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Verify if difference is a matter of string versus integer representation.
|
|
79
|
+
if str(actual_data[row_nr][column_nr]) == str(expected_data_including_templates[row_nr][column_nr]):
|
|
80
|
+
if isinstance(actual_data[row_nr][column_nr], int) and isinstance(expected_data_including_templates[row_nr][column_nr], str):
|
|
81
|
+
difference_found = True
|
|
82
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. Actual data is an integer while expected data is a string.")
|
|
83
|
+
elif isinstance(actual_data[row_nr][column_nr], str) and isinstance(expected_data_including_templates[row_nr][column_nr], int):
|
|
84
|
+
difference_found = True
|
|
85
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. Actual data is a string while expected data is an integer.")
|
|
86
|
+
continue
|
|
87
|
+
#
|
|
88
|
+
# If data in actual and expected field doesn't match, check if a template has been used in expected data.
|
|
89
|
+
match expected_data_including_templates[row_nr][column_nr].upper():
|
|
90
|
+
case "{PRESENT}":
|
|
91
|
+
if not actual_data[row_nr][column_nr]:
|
|
92
|
+
# No data is present in actual data field.
|
|
93
|
+
difference_found = True
|
|
94
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not PRESENT")
|
|
95
|
+
#
|
|
96
|
+
case "{EMPTY}":
|
|
97
|
+
if actual_data[row_nr][column_nr]:
|
|
98
|
+
# Actual data field is not empty.
|
|
99
|
+
difference_found = True
|
|
100
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not EMPTY")
|
|
101
|
+
#
|
|
102
|
+
case "{INTEGER}":
|
|
103
|
+
if isinstance(actual_data[row_nr][column_nr], int):
|
|
104
|
+
# A real integer.
|
|
105
|
+
continue
|
|
106
|
+
#
|
|
107
|
+
# Verify if string is integer.
|
|
108
|
+
if not actual_data[row_nr][column_nr].isdigit():
|
|
109
|
+
# Not positive integer field.
|
|
110
|
+
difference_found = True
|
|
111
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not INTEGER.")
|
|
112
|
+
#
|
|
113
|
+
case "{SKIP}":
|
|
114
|
+
pass
|
|
115
|
+
case _:
|
|
116
|
+
if "{SKIP}" in expected_data_including_templates[row_nr][column_nr].upper() or "{DATETIME_FORMAT():YYYYMMDDHHMMSSFF6}" in expected_data_including_templates[row_nr][column_nr].upper():
|
|
117
|
+
if expected_data_including_templates[row_nr][column_nr].upper() == "{SKIP}":
|
|
118
|
+
# Complete actual data field will be skipped for verification.
|
|
119
|
+
pass
|
|
120
|
+
else:
|
|
121
|
+
# Part(s) of the actual data field will be skipped for verification.
|
|
122
|
+
# Replace {SKIP}, ignoring cases, by wildcard *.
|
|
123
|
+
# compiled = re.compile(re.escape("{SKIP}"), re.IGNORECASE)
|
|
124
|
+
# expected_data_with_wildcard = compiled.sub("*", expected_data_including_templates[row_nr][column_nr])
|
|
125
|
+
compiled = re.compile(re.escape("{SKIP}"), re.IGNORECASE)
|
|
126
|
+
compiled2 = re.compile(re.escape("{DATETIME_FORMAT():YYYYMMDDHHMMSSFF6}"), re.IGNORECASE)
|
|
127
|
+
expected_data_with_wildcard = compiled2.sub("*", compiled.sub("*", expected_data_including_templates[row_nr][column_nr]))
|
|
128
|
+
#
|
|
129
|
+
if fnmatch.fnmatch(actual_data[row_nr][column_nr], expected_data_with_wildcard):
|
|
130
|
+
skip_exception_rule_used = True
|
|
131
|
+
continue
|
|
132
|
+
#
|
|
133
|
+
if expected_data_with_wildcard is None:
|
|
134
|
+
# Wildcards not used.
|
|
135
|
+
expected_data_including_date_template = expected_data_including_templates[row_nr][column_nr]
|
|
136
|
+
else:
|
|
137
|
+
expected_data_including_date_template = expected_data_with_wildcard
|
|
138
|
+
#
|
|
139
|
+
if "{NOW()" in expected_data_including_templates[row_nr][column_nr].upper():
|
|
140
|
+
matches = ["{NOW():", "{NOW()+", "{NOW()-"]
|
|
141
|
+
if all([x not in expected_data_including_templates[row_nr][column_nr].upper() for x in matches]):
|
|
142
|
+
difference_found = True
|
|
143
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOW() has been found in expected data field, but format is incorrect.")
|
|
144
|
+
continue
|
|
145
|
+
#
|
|
146
|
+
expected_data = DatetimeHandler.replace_date_template_in_expected_data(self, expected_data_including_date_template)
|
|
147
|
+
#
|
|
148
|
+
if expected_data == -1:
|
|
149
|
+
difference_found = True
|
|
150
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOW() has been found in expected data field, but format is incorrect.")
|
|
151
|
+
else:
|
|
152
|
+
if not fnmatch.fnmatch(actual_data[row_nr][column_nr], expected_data):
|
|
153
|
+
# No match despite using of wildcard(s).
|
|
154
|
+
difference_found = True
|
|
155
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Date template format displayed. See also next message line.")
|
|
156
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data, "There is a difference between actual and expected data.")
|
|
157
|
+
continue
|
|
158
|
+
#
|
|
159
|
+
elif "{NOT(" in expected_data_including_templates[row_nr][column_nr].upper():
|
|
160
|
+
try:
|
|
161
|
+
unwanted_expected_data = ArrayComparer.__get_unwanted_expected_data(self, expected_data_including_date_template)
|
|
162
|
+
#
|
|
163
|
+
if actual_data[row_nr][column_nr] == unwanted_expected_data:
|
|
164
|
+
# Unwanted match.
|
|
165
|
+
difference_found = True
|
|
166
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOT() template format displayed. See also next message line.")
|
|
167
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], unwanted_expected_data, "Actual and expected data are equal. However actual data should NOT be equal to the expected data!!!")
|
|
168
|
+
except Exception as exception_message:
|
|
169
|
+
# print(f"An exception occurred: {exception_message}")
|
|
170
|
+
difference_found = True
|
|
171
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOT() has been found in expected data field, but format is incorrect.")
|
|
172
|
+
#
|
|
173
|
+
else:
|
|
174
|
+
if not skip_exception_rule_used:
|
|
175
|
+
# No exceptions.
|
|
176
|
+
difference_found = True
|
|
177
|
+
Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. No exception rule has been used.")
|
|
178
|
+
#
|
|
179
|
+
if difference_found:
|
|
180
|
+
print("\n\n\n")
|
|
181
|
+
raise Exception("There is a difference between actual and expected data. See detail information.")
|
|
182
|
+
else:
|
|
183
|
+
print("There are no differences between actual and expected data found.")
|
|
184
|
+
print("\n\n\n")
|
|
185
|
+
|
|
186
|
+
#Report().show_footer_comparation_result()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def __get_unwanted_expected_data(self, expected_data_field_including_date_template):
|
|
190
|
+
position_open_brace = expected_data_field_including_date_template.find("{NOT(")
|
|
191
|
+
position_close_brace = expected_data_field_including_date_template.find(")}", position_open_brace)
|
|
192
|
+
#
|
|
193
|
+
if position_open_brace == -1:
|
|
194
|
+
#print("position_open_brace:", position_open_brace)
|
|
195
|
+
raise Exception()
|
|
196
|
+
#
|
|
197
|
+
if position_close_brace == -1:
|
|
198
|
+
#print("position_close_brace:", position_close_brace)
|
|
199
|
+
raise Exception()
|
|
200
|
+
#
|
|
201
|
+
unwanted_expected_data = expected_data_field_including_date_template[position_open_brace+5:position_close_brace]
|
|
202
|
+
#
|
|
203
|
+
if Tools.is_integer(self, unwanted_expected_data):
|
|
204
|
+
unwanted_expected_data = int(unwanted_expected_data)
|
|
205
|
+
return unwanted_expected_data
|
|
206
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Script for comparing csv-files, 2d-array with a csv-file or 2d-arrays and for comparing text-files, text variable with a text-file or text variables.
|
|
2
|
+
#
|
|
3
|
+
import csv
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from DataComparerLibrary.arraycomparer import ArrayComparer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DataComparer:
|
|
10
|
+
def compare_data_2d_array_with_file(self, actual_data, expected_file, delimiter_expected_data=",", quotechar_expected_data='"', template_literals_dict=None):
|
|
11
|
+
self.__check_if_actual_data_is_present(actual_data)
|
|
12
|
+
self.__check_if_expected_file_is_present(expected_file)
|
|
13
|
+
#
|
|
14
|
+
expected_data = self.__open_csv_input_file(expected_file, delimiter_expected_data, quotechar_expected_data)
|
|
15
|
+
#
|
|
16
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def compare_data_file_with_2d_array(self, actual_file, expected_data, delimiter_actual_data=",", quotechar_actual_data='"', template_literals_dict=None):
|
|
20
|
+
self.__check_if_actual_file_is_present(actual_file)
|
|
21
|
+
self.__check_if_expected_data_is_present(expected_data)
|
|
22
|
+
#
|
|
23
|
+
actual_data = self.__open_csv_input_file(actual_file, delimiter_actual_data, quotechar_actual_data)
|
|
24
|
+
#
|
|
25
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def compare_data_2d_arrays(self, actual_data, expected_data, template_literals_dict=None):
|
|
29
|
+
self.__check_if_actual_data_is_present(actual_data)
|
|
30
|
+
self.__check_if_expected_data_is_present(expected_data)
|
|
31
|
+
#
|
|
32
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def compare_data_files(self, actual_file, expected_file, delimiter_actual_data=",", delimiter_expected_data=",", quotechar_actual_data='"', quotechar_expected_data='"', template_literals_dict=None):
|
|
36
|
+
self.__check_if_actual_file_is_present(actual_file)
|
|
37
|
+
self.__check_if_expected_file_is_present(expected_file)
|
|
38
|
+
#
|
|
39
|
+
actual_data = self.__open_csv_input_file(actual_file, delimiter_actual_data, quotechar_actual_data)
|
|
40
|
+
expected_data = self.__open_csv_input_file(expected_file, delimiter_expected_data, quotechar_expected_data)
|
|
41
|
+
#
|
|
42
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def compare_text_variable_with_text_file(self, actual_text, expected_file, template_literals_dict=None):
|
|
46
|
+
self.__check_if_actual_data_is_present(actual_text)
|
|
47
|
+
self.__check_if_expected_file_is_present(expected_file)
|
|
48
|
+
#
|
|
49
|
+
actual_data = self.__split_text_into_textline_array(actual_text)
|
|
50
|
+
expected_data = self.__split_textfile_into_textline_array(expected_file)
|
|
51
|
+
#
|
|
52
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def compare_text_file_with_text_variable(self, actual_file, expected_text, template_literals_dict=None):
|
|
56
|
+
self.__check_if_actual_file_is_present(actual_file)
|
|
57
|
+
self.__check_if_expected_data_is_present(expected_text)
|
|
58
|
+
#
|
|
59
|
+
actual_data = self.__split_textfile_into_textline_array(actual_file)
|
|
60
|
+
expected_data = self.__split_text_into_textline_array(expected_text)
|
|
61
|
+
#
|
|
62
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def compare_text_variables(self, actual_text, expected_text, template_literals_dict=None):
|
|
66
|
+
self.__check_if_actual_data_is_present(actual_text)
|
|
67
|
+
self.__check_if_expected_data_is_present(expected_text)
|
|
68
|
+
#
|
|
69
|
+
actual_data = self.__split_text_into_textline_array(actual_text)
|
|
70
|
+
expected_data = self.__split_text_into_textline_array(expected_text)
|
|
71
|
+
#
|
|
72
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def compare_text_files(self, actual_file, expected_file, template_literals_dict=None):
|
|
76
|
+
self.__check_if_actual_file_is_present(actual_file)
|
|
77
|
+
self.__check_if_expected_file_is_present(expected_file)
|
|
78
|
+
#
|
|
79
|
+
actual_data = self.__split_textfile_into_textline_array(actual_file)
|
|
80
|
+
expected_data = self.__split_textfile_into_textline_array(expected_file)
|
|
81
|
+
#
|
|
82
|
+
ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def __check_if_actual_data_is_present(self, data):
|
|
87
|
+
if data == None:
|
|
88
|
+
raise Exception("Actual Input data unknown.")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def __check_if_expected_data_is_present(self, data):
|
|
92
|
+
if data == None:
|
|
93
|
+
raise Exception("Expected Input data unknown.")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def __check_if_actual_file_is_present(self, file):
|
|
97
|
+
if os.path.exists(file):
|
|
98
|
+
print("actual_file: ", file)
|
|
99
|
+
else:
|
|
100
|
+
raise Exception("Actual Input file doesn't exists: ", file)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def __check_if_expected_file_is_present(self, file):
|
|
104
|
+
if os.path.exists(file):
|
|
105
|
+
print("expected_file: ", file)
|
|
106
|
+
else:
|
|
107
|
+
raise Exception("Expected Input file doesn't exists: ", file)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def __open_csv_input_file(self, input_file, delimiter_data=",", quotechar_data='"'):
|
|
111
|
+
with open(input_file, mode='rt', encoding='utf-8') as input_file:
|
|
112
|
+
if len(delimiter_data) == 1:
|
|
113
|
+
data = list(csv.reader(input_file, delimiter=delimiter_data, quotechar=quotechar_data))
|
|
114
|
+
else:
|
|
115
|
+
data = list(csv.reader((line.replace(delimiter_data, chr(255)) for line in input_file), delimiter=chr(255), quotechar=quotechar_data))
|
|
116
|
+
#
|
|
117
|
+
return data
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def __split_text_into_textline_array(self, text):
|
|
121
|
+
data = []
|
|
122
|
+
for line in text.split('\n'):
|
|
123
|
+
data.append(line.strip('\n').split(chr(255)))
|
|
124
|
+
#
|
|
125
|
+
return data
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def __split_textfile_into_textline_array(self, input_file):
|
|
129
|
+
with open(input_file, mode='rt', encoding='utf-8') as input_file:
|
|
130
|
+
data = []
|
|
131
|
+
for line in input_file.readlines():
|
|
132
|
+
data.append(line.strip('\n').split(chr(255)))
|
|
133
|
+
#
|
|
134
|
+
return data
|
|
135
|
+
|