0
# Utilities
1
2
Helper functions and classes for UUID generation, timestamp management, parameter extraction, string formatting, and platform detection. These utilities support the core Allure functionality and provide common operations needed by testing frameworks.
3
4
## Capabilities
5
6
### Identifier and Timestamp Generation
7
8
Functions for generating unique identifiers and timestamps used throughout the Allure system.
9
10
```python { .api }
11
def uuid4():
12
"""
13
Generate a UUID4 string.
14
15
Returns:
16
str: Random UUID4 string
17
"""
18
19
def now():
20
"""
21
Get current timestamp in milliseconds.
22
23
Returns:
24
int: Current timestamp in milliseconds since epoch
25
"""
26
27
def md5(*args):
28
"""
29
Calculate MD5 hash of arguments.
30
31
Parameters:
32
- *args: Variable arguments to hash (strings, bytes, or other objects)
33
34
Returns:
35
str: Hexadecimal MD5 hash string
36
"""
37
```
38
39
**Usage Examples:**
40
41
```python
42
from allure_commons.utils import uuid4, now, md5
43
44
# Generate unique test identifier
45
test_id = uuid4() # "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
46
47
# Get current timestamp
48
start_time = now() # 1609459200000
49
50
# Generate hash for test data
51
test_data = "user:testuser,action:login"
52
data_hash = md5(test_data) # "a1b2c3d4e5f6789..."
53
54
# Hash multiple arguments
55
multi_hash = md5("test", "data", 123) # Combined hash
56
```
57
58
### Platform and Environment Detection
59
60
Functions for detecting platform and environment information for test labeling.
61
62
```python { .api }
63
def platform_label():
64
"""
65
Get platform label for test environment.
66
67
Returns:
68
str: Platform identifier (e.g., "python3", "cpython3")
69
"""
70
71
def host_tag():
72
"""
73
Get hostname for test environment identification.
74
75
Returns:
76
str: Current hostname
77
"""
78
79
def thread_tag():
80
"""
81
Get thread identifier for concurrent test execution.
82
83
Returns:
84
str: Thread identifier in format "pid-threadname"
85
"""
86
```
87
88
**Usage Examples:**
89
90
```python
91
from allure_commons.utils import platform_label, host_tag, thread_tag
92
93
# Add environment labels to test
94
platform = platform_label() # "python3"
95
hostname = host_tag() # "test-server-01"
96
thread_id = thread_tag() # "12345-MainThread"
97
98
# Use in test labeling
99
allure.dynamic.label("platform", platform)
100
allure.dynamic.label("host", hostname)
101
allure.dynamic.label("thread", thread_id)
102
```
103
104
### Function Parameter Extraction
105
106
Advanced function for extracting and formatting function parameters for test reporting.
107
108
```python { .api }
109
def func_parameters(func, *args, **kwargs):
110
"""
111
Extract function parameters with proper formatting.
112
113
Handles various function signatures including:
114
- Regular arguments and keyword arguments
115
- Default parameter values
116
- Variable arguments (*args)
117
- Keyword arguments (**kwargs)
118
- Class methods (self/cls parameter handling)
119
120
Parameters:
121
- func (callable): Function to extract parameters from
122
- *args: Positional arguments passed to function
123
- **kwargs: Keyword arguments passed to function
124
125
Returns:
126
OrderedDict: Ordered dictionary of parameter names to string representations
127
"""
128
```
129
130
**Usage Examples:**
131
132
```python
133
from allure_commons.utils import func_parameters
134
135
def example_function(a, b, c=3, *args, **kwargs):
136
pass
137
138
# Extract parameters from function call
139
params = func_parameters(example_function, 1, 2, 4, 5, extra="value")
140
# Returns: OrderedDict([('a', '1'), ('b', '2'), ('c', '4'), ('args', '(5,)'), ('extra', "'value'")])
141
142
# Use in step decoration
143
@allure.step("Execute function with parameters")
144
def logged_function(x, y, option=None):
145
# Get parameters for logging
146
params = func_parameters(logged_function, x, y, option)
147
allure.dynamic.parameter("function_params", str(dict(params)))
148
149
# Function implementation
150
return x + y if option != "subtract" else x - y
151
```
152
153
### String Representation and Formatting
154
155
Functions for consistent string representation and safe formatting of test data.
156
157
```python { .api }
158
def represent(item):
159
"""
160
Get consistent string representation of any item.
161
162
Handles special cases for different data types:
163
- Strings: Wrapped in single quotes
164
- Bytes/bytearray: Shows type information
165
- Other objects: Uses repr()
166
167
Parameters:
168
- item: Any object to represent
169
170
Returns:
171
str: String representation of the item
172
"""
173
174
class SafeFormatter(string.Formatter):
175
"""
176
String formatter that safely handles missing keys.
177
178
Unlike standard string formatting, missing keys are left as-is
179
instead of raising KeyError.
180
"""
181
182
def get_field(self, field_name, args, kwargs):
183
"""
184
Get field value, returning placeholder for missing keys.
185
186
Parameters:
187
- field_name (str): Name of field to retrieve
188
- args (tuple): Positional arguments
189
- kwargs (dict): Keyword arguments
190
191
Returns:
192
tuple: (field_value, field_name) or (placeholder, field_name)
193
"""
194
195
def get_value(self, key, args, kwargs):
196
"""
197
Get value by key, raising SafeKeyOrIndexError for missing keys.
198
199
Parameters:
200
- key: Key to retrieve
201
- args (tuple): Positional arguments
202
- kwargs (dict): Keyword arguments
203
204
Returns:
205
Value for the key
206
207
Raises:
208
SafeKeyOrIndexError: For missing keys (handled internally)
209
"""
210
```
211
212
**Usage Examples:**
213
214
```python
215
from allure_commons.utils import represent, SafeFormatter
216
217
# Consistent string representation
218
print(represent("hello")) # "'hello'"
219
print(represent(123)) # "123"
220
print(represent(None)) # "None"
221
print(represent([1, 2, 3])) # "[1, 2, 3]"
222
print(represent(b"bytes")) # "<class 'bytes'>"
223
224
# Safe string formatting
225
formatter = SafeFormatter()
226
227
# Missing keys are preserved
228
result = formatter.format("Hello {name}, your score is {score}", name="Alice")
229
print(result) # "Hello Alice, your score is {score}"
230
231
# Use in step titles with parameters
232
@allure.step("Process user {username} with action {action}")
233
def process_user_action(username, action, extra_data=None):
234
# Step title will be formatted safely even if extra_data is referenced
235
pass
236
```
237
238
### Exception and Traceback Formatting
239
240
Functions for formatting exceptions and tracebacks for test reporting.
241
242
```python { .api }
243
def format_traceback(exc_traceback):
244
"""
245
Format exception traceback for reporting.
246
247
Parameters:
248
- exc_traceback: Exception traceback object
249
250
Returns:
251
str: Formatted traceback string or None if no traceback
252
"""
253
254
def format_exception(etype, value):
255
"""
256
Format exception type and value for reporting.
257
258
Parameters:
259
- etype: Exception type
260
- value: Exception value/instance
261
262
Returns:
263
str: Formatted exception string or None if no exception
264
"""
265
```
266
267
**Usage Examples:**
268
269
```python
270
from allure_commons.utils import format_traceback, format_exception
271
import sys
272
273
def test_with_exception_handling():
274
try:
275
# Test code that might fail
276
result = risky_operation()
277
except Exception:
278
# Capture exception information
279
exc_type, exc_value, exc_traceback = sys.exc_info()
280
281
# Format for Allure reporting
282
formatted_exception = format_exception(exc_type, exc_value)
283
formatted_traceback = format_traceback(exc_traceback)
284
285
# Attach to test
286
allure.attach(formatted_exception, "Exception Details",
287
allure.attachment_type.TEXT)
288
allure.attach(formatted_traceback, "Stack Trace",
289
allure.attachment_type.TEXT)
290
raise
291
```
292
293
### Test Plan Support
294
295
Function for reading test plan configuration from environment.
296
297
```python { .api }
298
def get_testplan():
299
"""
300
Get test plan from environment configuration.
301
302
Reads test plan from file specified by ALLURE_TESTPLAN_PATH
303
environment variable.
304
305
Returns:
306
list: List of planned test identifiers, empty if no plan file
307
"""
308
```
309
310
**Usage Example:**
311
312
```python
313
from allure_commons.utils import get_testplan
314
import os
315
316
def should_run_test(test_id):
317
"""Check if test should run based on test plan."""
318
# Set test plan file
319
os.environ["ALLURE_TESTPLAN_PATH"] = "/tmp/testplan.json"
320
321
# Get planned tests
322
planned_tests = get_testplan()
323
324
# Check if test is in plan
325
if planned_tests:
326
return test_id in [test.get('id') for test in planned_tests]
327
328
# Run all tests if no plan
329
return True
330
331
# Example test plan file format:
332
# {
333
# "tests": [
334
# {"id": "test_login", "selector": "tests.auth.test_login"},
335
# {"id": "test_logout", "selector": "tests.auth.test_logout"}
336
# ]
337
# }
338
```
339
340
### Thread-Safe Operations
341
342
Utilities designed to work correctly in multi-threaded test environments.
343
344
**Thread Safety Notes:**
345
346
- `uuid4()`: Thread-safe UUID generation
347
- `now()`: Thread-safe timestamp generation
348
- `thread_tag()`: Returns current thread identifier
349
- `func_parameters()`: Safe parameter extraction per thread
350
- All formatting functions are stateless and thread-safe
351
352
**Multi-threaded Usage Example:**
353
354
```python
355
import threading
356
from allure_commons.utils import uuid4, now, thread_tag
357
358
def threaded_test_execution():
359
"""Example of thread-safe utility usage."""
360
test_id = uuid4() # Unique per thread
361
start_time = now() # Current timestamp
362
thread_id = thread_tag() # Current thread identifier
363
364
print(f"Thread {thread_id}: Test {test_id} started at {start_time}")
365
366
# Simulate test execution
367
time.sleep(1)
368
369
end_time = now()
370
print(f"Thread {thread_id}: Test completed in {end_time - start_time}ms")
371
372
# Run multiple threads
373
threads = []
374
for i in range(5):
375
thread = threading.Thread(target=threaded_test_execution)
376
threads.append(thread)
377
thread.start()
378
379
for thread in threads:
380
thread.join()
381
```