0
# Output Formatters
1
2
Extensible reporting system supporting multiple output formats including plain text, JSON, JUnit XML, and custom formats. Enables integration with CI/CD systems and test reporting tools.
3
4
## Capabilities
5
6
### Base Formatter Class
7
8
Abstract base class for all output formatters providing the foundation for custom formatter implementation.
9
10
```python { .api }
11
class Formatter:
12
"""
13
Base class for all output formatters.
14
15
Attributes:
16
- name: str, formatter name
17
- description: str, formatter description
18
- stream: file-like object for output
19
- config: Configuration object
20
21
Methods:
22
- uri(uri): Called when feature file is opened
23
- feature(feature): Called when feature starts
24
- background(background): Called when background starts
25
- scenario(scenario): Called when scenario starts
26
- scenario_outline(scenario_outline): Called for scenario outlines
27
- step(step): Called for each step
28
- match(match): Called when step matches definition
29
- result(result): Called with step execution result
30
- eof(): Called at end of feature file
31
- close(): Called when formatter is closed
32
"""
33
```
34
35
### Plain Text Formatter
36
37
Simple text output formatter providing basic test results without styling or colors.
38
39
```python { .api }
40
class PlainFormatter(Formatter):
41
"""
42
Simple text output formatter.
43
44
Features:
45
- Clean text output without colors
46
- Step-by-step execution display
47
- Basic pass/fail status reporting
48
- Suitable for log files and basic CI output
49
50
Output format:
51
- Feature name and description
52
- Scenario names with step results
53
- Final summary with counts
54
"""
55
```
56
57
### Pretty Formatter
58
59
Enhanced text formatter with colors, styling, and improved readability for interactive terminals.
60
61
```python { .api }
62
class PrettyFormatter(Formatter):
63
"""
64
Enhanced text formatter with colors and styling.
65
66
Features:
67
- Color-coded output (green=pass, red=fail, yellow=skip)
68
- Unicode symbols for status indicators
69
- Indented structure showing hierarchy
70
- Step timing information
71
- Multi-line text and table formatting
72
- Progress indicators during execution
73
74
Configuration:
75
- Respects --color/--no-color options
76
- Adapts to terminal capabilities
77
- Configurable indentation and symbols
78
"""
79
```
80
81
### JSON Formatter
82
83
Structured JSON output for programmatic consumption and integration with external tools.
84
85
```python { .api }
86
class JSONFormatter(Formatter):
87
"""
88
JSON output formatter for structured data.
89
90
Output structure:
91
- features: array of feature objects
92
- summary: execution statistics
93
- each feature contains scenarios array
94
- each scenario contains steps array
95
- timestamps and duration data included
96
97
Features:
98
- Machine-readable format
99
- Complete test execution data
100
- Hierarchical structure preservation
101
- Timing and status information
102
- Compatible with JSON processing tools
103
"""
104
```
105
106
### JUnit XML Formatter
107
108
JUnit-compatible XML output for integration with CI/CD systems and test reporting tools.
109
110
```python { .api }
111
class JUnitFormatter(Formatter):
112
"""
113
JUnit XML format for CI/CD integration.
114
115
Output structure:
116
- testsuite elements for features
117
- testcase elements for scenarios
118
- failure/error elements for failed steps
119
- properties for metadata
120
- system-out/system-err for captured output
121
122
Features:
123
- Standard JUnit XML schema compliance
124
- Integration with Jenkins, Azure DevOps, etc.
125
- Test timing and classification
126
- Failure details and stack traces
127
- Support for test suites and test cases
128
"""
129
```
130
131
### Progress Formatters
132
133
Compact progress indicators showing execution status without detailed output.
134
135
```python { .api }
136
class ProgressFormatter(Formatter):
137
"""
138
Simple progress bar formatter.
139
140
Output:
141
- Single line progress indicator
142
- Colored dots for step status (. = pass, F = fail, S = skip)
143
- Final summary with statistics
144
- Minimal screen space usage
145
"""
146
147
class Progress2Formatter(Formatter):
148
"""
149
Compact progress display with scenario names.
150
151
Output:
152
- Scenario names with pass/fail status
153
- Compact multi-line format
154
- Step count and timing summary
155
"""
156
157
class Progress3Formatter(Formatter):
158
"""
159
Detailed progress display with feature organization.
160
161
Output:
162
- Feature and scenario hierarchy
163
- Step-level progress indicators
164
- Detailed timing and status information
165
"""
166
```
167
168
### Specialty Formatters
169
170
Formatters for specific use cases and development workflows.
171
172
```python { .api }
173
class TagsFormatter(Formatter):
174
"""
175
Lists all available tags in the feature files.
176
177
Output:
178
- Alphabetically sorted tag list
179
- Usage count for each tag
180
- Feature/scenario association
181
- Useful for tag management and discovery
182
"""
183
184
class StepsFormatter(Formatter):
185
"""
186
Lists all defined step definitions.
187
188
Output:
189
- Step pattern listing
190
- File location information
191
- Parameter type information
192
- Helps identify unused or duplicate steps
193
"""
194
195
class StepsCatalogFormatter(Formatter):
196
"""
197
Detailed step definitions catalog with documentation.
198
199
Output:
200
- Step patterns with descriptions
201
- Parameter documentation
202
- Usage examples from docstrings
203
- Source code locations
204
- Complete step reference documentation
205
"""
206
207
class RerunFormatter(Formatter):
208
"""
209
Generates rerun information for failed scenarios.
210
211
Output:
212
- File:line references for failed scenarios
213
- Command-line options for rerunning
214
- Tag expressions for failed tests
215
- Useful for CI/CD retry logic
216
"""
217
```
218
219
## Formatter Usage
220
221
### Command Line Configuration
222
```bash
223
# Single formatter
224
behave --format pretty
225
226
# Multiple formatters
227
behave --format pretty --format json
228
229
# Formatter with output file
230
behave --format json --outfile results.json
231
232
# Multiple formatters with separate files
233
behave --format pretty --format json:results.json --format junit:junit.xml
234
235
# Formatter-specific options
236
behave --format progress2 --no-timings
237
```
238
239
### Configuration File Setup
240
```ini
241
# .behaverc
242
[behave]
243
format = pretty,json
244
outdir = reports
245
outfiles = ,results.json
246
```
247
248
## Custom Formatters
249
250
### Creating Custom Formatters
251
```python
252
from behave.formatter.base import Formatter
253
254
class CustomFormatter(Formatter):
255
"""Custom formatter for specific reporting needs."""
256
257
name = 'custom'
258
description = 'Custom formatter for special requirements'
259
260
def __init__(self, stream_opener, config):
261
super().__init__(stream_opener, config)
262
self.current_feature = None
263
self.statistics = {
264
'features': 0,
265
'scenarios': 0,
266
'steps': 0,
267
'passed': 0,
268
'failed': 0,
269
'skipped': 0
270
}
271
272
def feature(self, feature):
273
self.current_feature = feature
274
self.statistics['features'] += 1
275
self.stream.write(f"Feature: {feature.name}\n")
276
277
def scenario(self, scenario):
278
self.statistics['scenarios'] += 1
279
self.stream.write(f" Scenario: {scenario.name}\n")
280
281
def step(self, step):
282
self.statistics['steps'] += 1
283
status_char = {
284
'passed': '✓',
285
'failed': '✗',
286
'skipped': '-',
287
'undefined': '?'
288
}.get(step.status, ' ')
289
290
self.stream.write(f" {status_char} {step.name}\n")
291
self.statistics[step.status] += 1
292
293
def close(self):
294
# Write summary
295
self.stream.write("\nSummary:\n")
296
for key, value in self.statistics.items():
297
self.stream.write(f" {key}: {value}\n")
298
```
299
300
### Registering Custom Formatters
301
```python
302
# In environment.py or plugin file
303
def before_all(context):
304
# Register custom formatter
305
from behave.formatter._registry import format_registry
306
format_registry.register('custom', CustomFormatter)
307
```
308
309
## Formatter Integration
310
311
### With CI/CD Systems
312
```bash
313
# Jenkins integration
314
behave --format junit --junit-directory $WORKSPACE/test-reports
315
316
# GitHub Actions
317
behave --format json --outfile test-results.json
318
319
# Azure DevOps
320
behave --format junit --junit-directory $(Agent.TempDirectory)/test-results
321
```
322
323
### With Test Reporting Tools
324
```bash
325
# Allure integration
326
behave --format allure_behave.formatter:AllureFormatter --outdir allure-results
327
328
# ReportPortal integration
329
behave --format reportportal_behave:Formatter
330
331
# Custom dashboard integration
332
behave --format json --outfile dashboard-data.json
333
```
334
335
### Output Capture Integration
336
```python
337
# Formatter with output capture
338
class CaptureFormatter(Formatter):
339
def step(self, step):
340
if hasattr(step, 'captured'):
341
self.stream.write(f"Captured output: {step.captured}\n")
342
343
if hasattr(step, 'error_message') and step.error_message:
344
self.stream.write(f"Error: {step.error_message}\n")
345
```
346
347
## Formatter Examples
348
349
### HTML Report Formatter
350
```python
351
class HTMLFormatter(Formatter):
352
"""Generates HTML test reports."""
353
354
def __init__(self, stream_opener, config):
355
super().__init__(stream_opener, config)
356
self.features = []
357
358
def feature(self, feature):
359
self.features.append(feature)
360
361
def close(self):
362
html_content = self.generate_html_report(self.features)
363
self.stream.write(html_content)
364
365
def generate_html_report(self, features):
366
# Generate HTML report from features data
367
return f"""
368
<html>
369
<head><title>Test Report</title></head>
370
<body>
371
<h1>Behave Test Report</h1>
372
<!-- Feature and scenario details -->
373
</body>
374
</html>
375
"""
376
```
377
378
### Slack Notification Formatter
379
```python
380
class SlackFormatter(Formatter):
381
"""Sends test results to Slack."""
382
383
def close(self):
384
summary = self.calculate_summary()
385
message = f"Test Results: {summary['passed']} passed, {summary['failed']} failed"
386
self.send_to_slack(message)
387
388
def send_to_slack(self, message):
389
# Implementation for Slack webhook
390
pass
391
```
392
393
### Database Logger Formatter
394
```python
395
class DatabaseFormatter(Formatter):
396
"""Logs test results to database."""
397
398
def __init__(self, stream_opener, config):
399
super().__init__(stream_opener, config)
400
self.db_connection = self.setup_database()
401
402
def scenario(self, scenario):
403
self.log_scenario_to_database(scenario)
404
405
def step(self, step):
406
self.log_step_to_database(step)
407
```