robotframework-logxml2chunks 1.0.0__tar.gz → 1.1.1__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.
Files changed (28) hide show
  1. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/LogXML2Chunks/LogXML2Chunks.py +37 -17
  2. {robotframework_logxml2chunks-1.0.0/robotframework_logxml2chunks.egg-info → robotframework_logxml2chunks-1.1.1}/PKG-INFO +15 -1
  3. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/README.md +14 -0
  4. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1/robotframework_logxml2chunks.egg-info}/PKG-INFO +15 -1
  5. robotframework_logxml2chunks-1.1.1/robotframework_logxml2chunks.egg-info/SOURCES.txt +14 -0
  6. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/setup.py +1 -1
  7. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/tests/test_logxml2chunks.py +8 -1
  8. robotframework_logxml2chunks-1.0.0/requirements.txt +0 -4
  9. robotframework_logxml2chunks-1.0.0/robotframework_logxml2chunks.egg-info/SOURCES.txt +0 -25
  10. robotframework_logxml2chunks-1.0.0/tests/__init__.py +0 -3
  11. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/1_Example_Test_1_s1-t1.xml +0 -45
  12. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/1_Example_Test_1_s1-t1_log.html +0 -2457
  13. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/2_Example_Test_2_s1-t2.xml +0 -45
  14. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/2_Example_Test_2_s1-t2_log.html +0 -2457
  15. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/3_Example_Test_3_s1-t3.xml +0 -45
  16. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/3_Example_Test_3_s1-t3_log.html +0 -2457
  17. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/4_Example_Test_4_s1-t4.xml +0 -45
  18. robotframework_logxml2chunks-1.0.0/tests/example_logs/chunks/4_Example_Test_4_s1-t4_log.html +0 -2457
  19. robotframework_logxml2chunks-1.0.0/tests/example_logs/example.robot +0 -57
  20. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/LICENSE +0 -0
  21. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/LogXML2Chunks/__init__.py +0 -0
  22. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/LogXML2Chunks/cli.py +0 -0
  23. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/robotframework_logxml2chunks.egg-info/dependency_links.txt +0 -0
  24. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/robotframework_logxml2chunks.egg-info/entry_points.txt +0 -0
  25. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/robotframework_logxml2chunks.egg-info/not-zip-safe +0 -0
  26. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/robotframework_logxml2chunks.egg-info/requires.txt +0 -0
  27. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/robotframework_logxml2chunks.egg-info/top_level.txt +0 -0
  28. {robotframework_logxml2chunks-1.0.0 → robotframework_logxml2chunks-1.1.1}/setup.cfg +0 -0
@@ -13,10 +13,25 @@ import os
13
13
  import sys
14
14
  import copy
15
15
  import re
16
+ import hashlib
16
17
  from pathlib import Path
17
18
 
18
19
  class LogXML2Chunks:
19
20
 
21
+ def __init__(self, debug=True):
22
+ """
23
+ Initialize LogXML2Chunks instance.
24
+
25
+ Args:
26
+ debug: Enable debug output (default: True)
27
+ """
28
+ self.debug = debug
29
+
30
+ def _debug_print(self, *args, **kwargs):
31
+ """Print only if debug mode is enabled."""
32
+ if self.debug:
33
+ print(*args, **kwargs)
34
+
20
35
  def _extract_steps_from_documentation(self, doc_text):
21
36
  """
22
37
  Extract steps from test documentation.
@@ -169,6 +184,10 @@ class LogXML2Chunks:
169
184
  if potential_log.exists():
170
185
  log_filepath = str(potential_log)
171
186
 
187
+ # Calculate checksum based on test_name and documentation
188
+ checksum_data = f"{test_name}{test_doc}".encode('utf-8')
189
+ checksum = hashlib.md5(checksum_data).hexdigest()
190
+
172
191
  # Build result dictionary
173
192
  result = {
174
193
  'index': idx,
@@ -179,9 +198,10 @@ class LogXML2Chunks:
179
198
  'steps': test_steps,
180
199
  'source': test_source,
181
200
  'xml_file': str(xml_filepath),
201
+ 'checksum': checksum,
182
202
  'success': True
183
- }
184
-
203
+ }
204
+
185
205
  # Add log file if it exists
186
206
  if log_filepath:
187
207
  result['log_file'] = log_filepath
@@ -222,33 +242,33 @@ class LogXML2Chunks:
222
242
 
223
243
  # Check if folder exists
224
244
  if not folder.exists():
225
- print(f"Error: Folder does not exist: {folder_path}")
245
+ self._debug_print(f"Error: Folder does not exist: {folder_path}")
226
246
  return results
227
247
 
228
248
  if not folder.is_dir():
229
- print(f"Error: Path is not a directory: {folder_path}")
249
+ self._debug_print(f"Error: Path is not a directory: {folder_path}")
230
250
  return results
231
251
 
232
252
  # Find all XML files in the folder
233
253
  xml_files = sorted(folder.glob('*.xml'))
234
254
 
235
255
  if not xml_files:
236
- print(f"Warning: No XML files found in {folder_path}")
256
+ self._debug_print(f"Warning: No XML files found in {folder_path}")
237
257
  return results
238
258
 
239
- print(f"Found {len(xml_files)} XML files in {folder_path}")
259
+ self._debug_print(f"Found {len(xml_files)} XML files in {folder_path}")
240
260
 
241
261
  # Process each XML file
242
262
  for xml_file in xml_files:
243
- print(f" Processing: {xml_file.name}")
263
+ self._debug_print(f" Processing: {xml_file.name}")
244
264
  chunk_data = self.get_data_from_chunk(str(xml_file))
245
265
  results.append(chunk_data)
246
266
 
247
267
  # Print status
248
268
  if chunk_data.get('success', False):
249
- print(f" ✓ {chunk_data.get('test_name', 'Unknown')} - {chunk_data.get('status', 'Unknown')}")
269
+ self._debug_print(f" ✓ {chunk_data.get('test_name', 'Unknown')} - {chunk_data.get('status', 'Unknown')}")
250
270
  else:
251
- print(f" ✗ Error: {chunk_data.get('error', 'Unknown error')}")
271
+ self._debug_print(f" ✗ Error: {chunk_data.get('error', 'Unknown error')}")
252
272
 
253
273
  return results
254
274
 
@@ -275,7 +295,7 @@ class LogXML2Chunks:
275
295
  for test in suite.findall('test'):
276
296
  test_cases.append((suite, test))
277
297
 
278
- print(f"Found {len(test_cases)} test cases")
298
+ self._debug_print(f"Found {len(test_cases)} test cases")
279
299
 
280
300
  # Extract each test case
281
301
  for idx, (suite, test) in enumerate(test_cases, 1):
@@ -287,7 +307,7 @@ class LogXML2Chunks:
287
307
  xml_filename = f"{idx}_{safe_name}_{test_id}.xml"
288
308
  xml_filepath = output_path / xml_filename
289
309
 
290
- print(f"\n[{idx}/{len(test_cases)}] Processing: {test_name}")
310
+ self._debug_print(f"\n[{idx}/{len(test_cases)}] Processing: {test_name}")
291
311
 
292
312
  # Create a new XML document with only this test case
293
313
  new_root = ET.Element('robot', root.attrib)
@@ -360,7 +380,7 @@ class LogXML2Chunks:
360
380
  ET.indent(new_tree, space=' ')
361
381
  new_tree.write(xml_filepath, encoding='UTF-8', xml_declaration=True)
362
382
 
363
- print(f" ✓ Created XML: {xml_filepath}")
383
+ self._debug_print(f" ✓ Created XML: {xml_filepath}")
364
384
 
365
385
  # Generate HTML report using rebot
366
386
  # html_filename = f"{safe_name}_{test_id}.html"
@@ -388,13 +408,13 @@ class LogXML2Chunks:
388
408
  # With --NoStatusRC, rebot returns 0 on success regardless of test results
389
409
  # Only non-zero codes indicate actual errors (invalid data, missing files, etc.)
390
410
  if result.returncode == 0:
391
- print(f" ✓ Generated log: {log_filepath}")
411
+ self._debug_print(f" ✓ Generated log: {log_filepath}")
392
412
  else:
393
- print(f" ✗ Failed to generate report (exit code: {result.returncode})")
413
+ self._debug_print(f" ✗ Failed to generate report (exit code: {result.returncode})")
394
414
  if result.stderr:
395
- print(f" Error: {result.stderr}")
415
+ self._debug_print(f" Error: {result.stderr}")
396
416
 
397
417
  except FileNotFoundError:
398
- print(f" ✗ Error: rebot command not found. Please install robotframework.")
418
+ self._debug_print(f" ✗ Error: rebot command not found. Please install robotframework.")
399
419
  except Exception as e:
400
- print(f" ✗ Error generating report: {str(e)}, index number = {idx}")
420
+ self._debug_print(f" ✗ Error generating report: {str(e)}, index number = {idx}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-logxml2chunks
3
- Version: 1.0.0
3
+ Version: 1.1.1
4
4
  Summary: Extract individual test cases from Robot Framework output.xml into separate chunks
5
5
  Home-page: https://github.com/ajadach/robotframework-LogXML2Chunks
6
6
  Author: Artur Jadach
@@ -120,11 +120,25 @@ The `split_to_chunks()` method returns a list of dictionaries with:
120
120
  'source': '/path/to/test.robot', # Source file path
121
121
  'xml_file': Path('...'), # Generated XML file path
122
122
  'log_file': Path('...'), # Generated log file path
123
+ 'checksum': 'a1b2c3d4...', # MD5 checksum of test_name + documentation
123
124
  'success': True, # Whether generation succeeded
124
125
  'error': None # Error message if failed
125
126
  }
126
127
  ```
127
128
 
129
+ ### Checksum Field
130
+
131
+ The `checksum` field is automatically calculated for each test case using MD5 hash of the concatenated `test_name` and `documentation`. This provides a unique identifier for tracking test case changes:
132
+
133
+ - **Format**: 32-character hexadecimal string
134
+ - **Algorithm**: MD5
135
+ - **Input**: `test_name + documentation`
136
+ - **Use cases**:
137
+ - Detect documentation changes
138
+ - Track test case modifications
139
+ - Integration with external test management systems
140
+ - Version control of test cases
141
+
128
142
  ## Step Extraction
129
143
 
130
144
  The library automatically extracts steps from test documentation that follow this format:
@@ -80,11 +80,25 @@ The `split_to_chunks()` method returns a list of dictionaries with:
80
80
  'source': '/path/to/test.robot', # Source file path
81
81
  'xml_file': Path('...'), # Generated XML file path
82
82
  'log_file': Path('...'), # Generated log file path
83
+ 'checksum': 'a1b2c3d4...', # MD5 checksum of test_name + documentation
83
84
  'success': True, # Whether generation succeeded
84
85
  'error': None # Error message if failed
85
86
  }
86
87
  ```
87
88
 
89
+ ### Checksum Field
90
+
91
+ The `checksum` field is automatically calculated for each test case using MD5 hash of the concatenated `test_name` and `documentation`. This provides a unique identifier for tracking test case changes:
92
+
93
+ - **Format**: 32-character hexadecimal string
94
+ - **Algorithm**: MD5
95
+ - **Input**: `test_name + documentation`
96
+ - **Use cases**:
97
+ - Detect documentation changes
98
+ - Track test case modifications
99
+ - Integration with external test management systems
100
+ - Version control of test cases
101
+
88
102
  ## Step Extraction
89
103
 
90
104
  The library automatically extracts steps from test documentation that follow this format:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-logxml2chunks
3
- Version: 1.0.0
3
+ Version: 1.1.1
4
4
  Summary: Extract individual test cases from Robot Framework output.xml into separate chunks
5
5
  Home-page: https://github.com/ajadach/robotframework-LogXML2Chunks
6
6
  Author: Artur Jadach
@@ -120,11 +120,25 @@ The `split_to_chunks()` method returns a list of dictionaries with:
120
120
  'source': '/path/to/test.robot', # Source file path
121
121
  'xml_file': Path('...'), # Generated XML file path
122
122
  'log_file': Path('...'), # Generated log file path
123
+ 'checksum': 'a1b2c3d4...', # MD5 checksum of test_name + documentation
123
124
  'success': True, # Whether generation succeeded
124
125
  'error': None # Error message if failed
125
126
  }
126
127
  ```
127
128
 
129
+ ### Checksum Field
130
+
131
+ The `checksum` field is automatically calculated for each test case using MD5 hash of the concatenated `test_name` and `documentation`. This provides a unique identifier for tracking test case changes:
132
+
133
+ - **Format**: 32-character hexadecimal string
134
+ - **Algorithm**: MD5
135
+ - **Input**: `test_name + documentation`
136
+ - **Use cases**:
137
+ - Detect documentation changes
138
+ - Track test case modifications
139
+ - Integration with external test management systems
140
+ - Version control of test cases
141
+
128
142
  ## Step Extraction
129
143
 
130
144
  The library automatically extracts steps from test documentation that follow this format:
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ LogXML2Chunks/LogXML2Chunks.py
5
+ LogXML2Chunks/__init__.py
6
+ LogXML2Chunks/cli.py
7
+ robotframework_logxml2chunks.egg-info/PKG-INFO
8
+ robotframework_logxml2chunks.egg-info/SOURCES.txt
9
+ robotframework_logxml2chunks.egg-info/dependency_links.txt
10
+ robotframework_logxml2chunks.egg-info/entry_points.txt
11
+ robotframework_logxml2chunks.egg-info/not-zip-safe
12
+ robotframework_logxml2chunks.egg-info/requires.txt
13
+ robotframework_logxml2chunks.egg-info/top_level.txt
14
+ tests/test_logxml2chunks.py
@@ -10,7 +10,7 @@ long_description = (this_directory / "README.md").read_text(encoding='utf-8')
10
10
 
11
11
  setup(
12
12
  name='robotframework-logxml2chunks',
13
- version='1.0.0',
13
+ version='1.1.1',
14
14
  author='Artur Jadach',
15
15
  author_email='artur.k.ziolkowski@example.com',
16
16
  description='Extract individual test cases from Robot Framework output.xml into separate chunks',
@@ -47,7 +47,7 @@ class TestLogXML2Chunks:
47
47
 
48
48
  # Verify all required fields are present
49
49
  required_fields = ['index', 'test_name', 'test_id', 'status', 'documentation',
50
- 'steps', 'source', 'xml_file', 'success']
50
+ 'steps', 'source', 'xml_file', 'checksum', 'success']
51
51
  for field in required_fields:
52
52
  assert field in result, f"Field '{field}' should be present in result"
53
53
 
@@ -57,6 +57,12 @@ class TestLogXML2Chunks:
57
57
  assert result['status'] == 'PASS', f"Expected 'PASS', got '{result['status']}'"
58
58
  assert result['index'] == 1, f"Expected index 1, got {result['index']}"
59
59
 
60
+ # Verify checksum is present and valid
61
+ assert 'checksum' in result, "checksum field should be present"
62
+ assert isinstance(result['checksum'], str), "checksum should be a string"
63
+ assert len(result['checksum']) == 32, f"checksum should be 32 characters (MD5), got {len(result['checksum'])}"
64
+ assert result['checksum'].isalnum(), "checksum should be alphanumeric"
65
+
60
66
  # Verify source path
61
67
  assert 'example.robot' in result['source'], f"Source should contain 'example.robot', got '{result['source']}'"
62
68
 
@@ -124,6 +130,7 @@ class TestLogXML2Chunks:
124
130
  assert 'steps' in result
125
131
  assert 'source' in result
126
132
  assert 'xml_file' in result
133
+ assert 'checksum' in result
127
134
  assert 'success' in result
128
135
  assert result['success'] is True
129
136
 
@@ -1,4 +0,0 @@
1
- # Production dependencies
2
- robotframework>=4.0
3
- pytest>=7.0
4
- pytest-cov>=4.0
@@ -1,25 +0,0 @@
1
- LICENSE
2
- README.md
3
- requirements.txt
4
- setup.py
5
- LogXML2Chunks/LogXML2Chunks.py
6
- LogXML2Chunks/__init__.py
7
- LogXML2Chunks/cli.py
8
- robotframework_logxml2chunks.egg-info/PKG-INFO
9
- robotframework_logxml2chunks.egg-info/SOURCES.txt
10
- robotframework_logxml2chunks.egg-info/dependency_links.txt
11
- robotframework_logxml2chunks.egg-info/entry_points.txt
12
- robotframework_logxml2chunks.egg-info/not-zip-safe
13
- robotframework_logxml2chunks.egg-info/requires.txt
14
- robotframework_logxml2chunks.egg-info/top_level.txt
15
- tests/__init__.py
16
- tests/test_logxml2chunks.py
17
- tests/example_logs/example.robot
18
- tests/example_logs/chunks/1_Example_Test_1_s1-t1.xml
19
- tests/example_logs/chunks/1_Example_Test_1_s1-t1_log.html
20
- tests/example_logs/chunks/2_Example_Test_2_s1-t2.xml
21
- tests/example_logs/chunks/2_Example_Test_2_s1-t2_log.html
22
- tests/example_logs/chunks/3_Example_Test_3_s1-t3.xml
23
- tests/example_logs/chunks/3_Example_Test_3_s1-t3_log.html
24
- tests/example_logs/chunks/4_Example_Test_4_s1-t4.xml
25
- tests/example_logs/chunks/4_Example_Test_4_s1-t4_log.html
@@ -1,3 +0,0 @@
1
- """
2
- Tests initialization file.
3
- """
@@ -1,45 +0,0 @@
1
- <?xml version='1.0' encoding='UTF-8'?>
2
- <robot generator="Robot 7.3.2 (Python 3.10.12 on linux)" generated="2025-11-13T17:21:50.004523" rpa="false" schemaversion="5">
3
- <suite id="s1" name="Example" source="/home/ajadach/GIT_LAB/robotframework-LogXML2Chunks/tests/example_logs/example.robot">
4
- <test id="s1-t1" name="Example Test 1" line="15">
5
- <kw name="Log" owner="BuiltIn">
6
- <msg time="2025-11-13T17:21:50.036281" level="INFO">Executing Example Test 1</msg>
7
- <arg>Executing Example Test 1</arg>
8
- <doc>Logs the given message with the given level.</doc>
9
- <status status="PASS" start="2025-11-13T17:21:50.035959" elapsed="0.000421" />
10
- </kw>
11
- <doc>Example Test 1 Documentation
12
-
13
- *Steps / Expected*
14
- - Log to HTML / pass
15
-
16
- *Expected*
17
- - Log should be successful.</doc>
18
- <tag>test_1</tag>
19
- <status status="PASS" start="2025-11-13T17:21:50.034956" elapsed="0.001694" />
20
- </test>
21
- <doc>Example suite level documentation.
22
-
23
-
24
- *Steps*
25
- - Example Test 1
26
- - Example Test 2
27
- - Example Test 3
28
- - Example Test 4
29
-
30
- *Expected*
31
- - All test cases should be successful.</doc>
32
- </suite>
33
- <statistics>
34
- <total>
35
- <stat pass="1" fail="0" skip="0">All Tests</stat>
36
- </total>
37
- <tag>
38
- <stat pass="1" fail="0" skip="0">test_1</stat>
39
- </tag>
40
- <suite>
41
- <stat name="Example" id="s1" pass="1" fail="0" skip="0" />
42
- </suite>
43
- </statistics>
44
- <errors />
45
- </robot>