0
# Output Formatting
1
2
Green's output formatting system provides color-coded terminal output with hierarchical display, multiple verbosity levels, and customizable formatting options for enhanced test result readability.
3
4
## Capabilities
5
6
### Green Stream
7
8
Enhanced output stream wrapper that provides Green's signature clean, colorful formatting with proper handling of multi-line output and hierarchical test display.
9
10
```python { .api }
11
class GreenStream:
12
"""
13
Enhanced output stream wrapper for Green's formatted output.
14
15
Wraps standard output streams to provide Green's clean, hierarchical
16
test output with color coding and proper formatting.
17
"""
18
19
def __init__(self, stream, override_appveyor=False, disable_windows=False, disable_unidecode=False):
20
"""
21
Initialize enhanced output stream.
22
23
Args:
24
stream: Base output stream (typically sys.stdout or sys.stderr)
25
override_appveyor (bool): Override AppVeyor-specific behavior
26
disable_windows (bool): Disable Windows-specific formatting
27
disable_unidecode (bool): Disable Unicode to ASCII conversion
28
29
Example:
30
import sys
31
from green.output import GreenStream
32
33
stream = GreenStream(sys.stdout)
34
stream.writeln("Test output with Green formatting")
35
"""
36
37
def write(self, text):
38
"""
39
Write text to the stream with Green formatting.
40
41
Args:
42
text (str): Text to write, may contain color codes and formatting
43
44
Handles color codes, Unicode characters, and Windows compatibility.
45
"""
46
47
def writeln(self, text=''):
48
"""
49
Write a line of text with newline.
50
51
Args:
52
text (str): Text to write, defaults to empty string for blank line
53
54
Example:
55
stream.writeln("Test: test_example")
56
stream.writeln() # Blank line
57
"""
58
59
def writelines(self, lines):
60
"""
61
Write multiple lines of text.
62
63
Args:
64
lines (iterable): Iterable of strings to write as separate lines
65
"""
66
67
def formatText(self, text, indent=0, outcome_char=''):
68
"""
69
Format multi-line text with Green's hierarchical styling.
70
71
Args:
72
text (str): Text to format (may contain multiple lines)
73
indent (int): Indentation level for hierarchical display
74
outcome_char (str): Character indicating test outcome ('.', 'F', 'E', etc.)
75
76
Returns:
77
str: Formatted text with proper indentation and outcome indicators
78
79
Example:
80
formatted = stream.formatText("Multi-line\\ntest output", indent=2, outcome_char='.')
81
stream.write(formatted)
82
"""
83
84
def formatLine(self, line, indent=0, outcome_char=''):
85
"""
86
Format a single line with outcome character and indentation.
87
88
Args:
89
line (str): Single line of text to format
90
indent (int): Indentation level
91
outcome_char (str): Test outcome character
92
93
Returns:
94
str: Formatted line with proper alignment
95
96
Example:
97
formatted = stream.formatLine("test_example", indent=1, outcome_char='.')
98
# Returns: ". test_example"
99
"""
100
101
def flush(self):
102
"""Flush the underlying stream."""
103
104
def isatty(self):
105
"""
106
Check if stream is connected to a terminal.
107
108
Returns:
109
bool: True if stream is a TTY (supports colors)
110
"""
111
```
112
113
### Colors
114
115
Terminal color formatting system that provides both basic colors and semantic color methods for different test outcomes.
116
117
```python { .api }
118
class Colors:
119
"""
120
Terminal color formatting for Green's output.
121
122
Provides color methods for different test outcomes and general formatting,
123
with automatic terminal capability detection.
124
"""
125
126
def __init__(self, termcolor=None):
127
"""
128
Initialize color formatter.
129
130
Args:
131
termcolor (bool, optional): Force color on/off. If None, auto-detects
132
terminal color support.
133
134
Example:
135
# Auto-detect color support
136
colors = Colors()
137
138
# Force colors on
139
colors = Colors(termcolor=True)
140
141
# Force colors off
142
colors = Colors(termcolor=False)
143
"""
144
145
# Basic color methods
146
def green(self, text):
147
"""
148
Format text in green color.
149
150
Args:
151
text (str): Text to color
152
153
Returns:
154
str: Text with green color codes (if terminal supports colors)
155
"""
156
157
def red(self, text):
158
"""Format text in red color."""
159
160
def blue(self, text):
161
"""Format text in blue color."""
162
163
def yellow(self, text):
164
"""Format text in yellow color."""
165
166
def bold(self, text):
167
"""Format text in bold."""
168
169
# Semantic color methods for test outcomes
170
def passing(self, text):
171
"""
172
Format text for passing tests (typically green).
173
174
Args:
175
text (str): Text to format
176
177
Returns:
178
str: Formatted text indicating success
179
180
Example:
181
colors = Colors()
182
print(colors.passing("✓ test_login_success"))
183
"""
184
185
def failing(self, text):
186
"""Format text for failing tests (typically red)."""
187
188
def error(self, text):
189
"""Format text for test errors (typically red/bold)."""
190
191
def skipped(self, text):
192
"""Format text for skipped tests (typically yellow)."""
193
194
def unexpectedSuccess(self, text):
195
"""Format text for unexpected successes (typically cyan)."""
196
197
def expectedFailure(self, text):
198
"""Format text for expected failures (typically yellow)."""
199
200
def moduleName(self, text):
201
"""Format text for test module names (typically bold)."""
202
203
def className(self, text):
204
"""Format text for test class names (typically bold)."""
205
```
206
207
### Debug Output
208
209
Debug output function for development and troubleshooting purposes.
210
211
```python { .api }
212
def debug(message, level=1):
213
"""
214
Output debug message if debug level is sufficient.
215
216
Args:
217
message (str): Debug message to output
218
level (int): Debug level required for this message (default: 1)
219
220
The global debug_level variable controls which messages are shown.
221
Only messages with level <= debug_level are displayed.
222
223
Example:
224
import green.output
225
green.output.debug_level = 2
226
227
debug("Basic debug info", level=1) # Will be shown
228
debug("Detailed debug info", level=2) # Will be shown
229
debug("Verbose debug info", level=3) # Will NOT be shown
230
"""
231
```
232
233
## Usage Examples
234
235
### Basic Stream Usage
236
237
```python
238
from green.output import GreenStream, Colors
239
import sys
240
241
# Create enhanced stream
242
stream = GreenStream(sys.stdout)
243
colors = Colors()
244
245
# Write formatted output
246
stream.writeln(colors.moduleName("test_module"))
247
stream.writeln(colors.className(" TestClass"))
248
stream.writeln(colors.passing(". test_method_passes"))
249
stream.writeln(colors.failing("F test_method_fails"))
250
stream.writeln(colors.error("E test_method_error"))
251
stream.writeln(colors.skipped("s test_method_skipped"))
252
```
253
254
### Hierarchical Output Formatting
255
256
```python
257
from green.output import GreenStream
258
259
stream = GreenStream(sys.stdout)
260
261
# Format hierarchical test output
262
module_text = "test_authentication"
263
class_text = "AuthenticationTest"
264
test_text = "test_login_with_valid_credentials"
265
266
# Format with different indentation levels
267
formatted_module = stream.formatLine(module_text, indent=0)
268
formatted_class = stream.formatLine(class_text, indent=1)
269
formatted_test = stream.formatLine(test_text, indent=2, outcome_char='.')
270
271
stream.write(formatted_module)
272
stream.write(formatted_class)
273
stream.write(formatted_test)
274
```
275
276
### Multi-line Output Handling
277
278
```python
279
from green.output import GreenStream
280
281
stream = GreenStream(sys.stdout)
282
283
# Handle multi-line error messages
284
error_message = """Traceback (most recent call last):
285
File "test_module.py", line 25, in test_example
286
self.assertEqual(expected, actual)
287
AssertionError: 'expected' != 'actual'"""
288
289
# Format with proper indentation
290
formatted_error = stream.formatText(error_message, indent=3, outcome_char='F')
291
stream.write(formatted_error)
292
```
293
294
### Custom Color Schemes
295
296
```python
297
from green.output import Colors
298
299
# Force colors on for non-TTY output (e.g., file redirection)
300
colors = Colors(termcolor=True)
301
302
# Create custom color combinations
303
def custom_warning(text):
304
return colors.yellow(colors.bold(text))
305
306
def custom_success(text):
307
return colors.green(colors.bold(text))
308
309
def custom_critical(text):
310
return colors.red(colors.bold(text))
311
312
# Use custom colors
313
print(custom_warning("Warning: deprecated test method"))
314
print(custom_success("All integration tests passed"))
315
print(custom_critical("Critical test failure detected"))
316
```
317
318
### Debug Output Configuration
319
320
```python
321
import green.output
322
323
# Set debug level
324
green.output.debug_level = 2
325
326
# Different levels of debug output
327
green.output.debug("Loading test configuration", level=1)
328
green.output.debug("Found 25 test files", level=1)
329
green.output.debug("Parsing test file: test_auth.py", level=2)
330
green.output.debug("Internal parser state: {...}", level=3) # Won't show
331
```
332
333
### Stream Integration with Test Results
334
335
```python
336
from green.output import GreenStream, Colors
337
from green.result import GreenTestResult
338
339
class ColoredTestResult(GreenTestResult):
340
"""Test result with custom colored output."""
341
342
def __init__(self, args, stream):
343
# Ensure we have a GreenStream
344
if not isinstance(stream, GreenStream):
345
stream = GreenStream(stream)
346
super().__init__(args, stream)
347
self.colors = Colors()
348
349
def addSuccess(self, test, test_time=None):
350
super().addSuccess(test, test_time)
351
# Custom success output
352
if test_time:
353
self.stream.writeln(self.colors.passing(
354
f". {test} ({test_time:.3f}s)"
355
))
356
else:
357
self.stream.writeln(self.colors.passing(f". {test}"))
358
359
def addFailure(self, test, err, test_time=None):
360
super().addFailure(test, err, test_time)
361
# Custom failure output
362
self.stream.writeln(self.colors.failing(f"F {test}"))
363
formatted_error = self.stream.formatText(str(err[1]), indent=4)
364
self.stream.write(self.colors.failing(formatted_error))
365
```
366
367
### Platform-Specific Formatting
368
369
```python
370
from green.output import GreenStream
371
import sys
372
import os
373
374
# Configure for different platforms
375
if os.name == 'nt': # Windows
376
stream = GreenStream(sys.stdout, disable_windows=False)
377
elif sys.platform == 'win32' and 'APPVEYOR' in os.environ: # AppVeyor CI
378
stream = GreenStream(sys.stdout, override_appveyor=True)
379
else: # Unix-like systems
380
stream = GreenStream(sys.stdout)
381
382
# Stream automatically handles platform differences
383
stream.writeln("Test output formatted for current platform")
384
```
385
386
### Custom Output Formatters
387
388
```python
389
from green.output import GreenStream, Colors
390
391
class VerboseFormatter:
392
"""Custom formatter for verbose test output."""
393
394
def __init__(self, stream):
395
self.stream = GreenStream(stream) if not isinstance(stream, GreenStream) else stream
396
self.colors = Colors()
397
398
def format_test_start(self, test):
399
"""Format test start message."""
400
timestamp = time.strftime("%H:%M:%S")
401
formatted = f"[{timestamp}] Starting: {test}"
402
self.stream.writeln(self.colors.blue(formatted))
403
404
def format_test_success(self, test, duration):
405
"""Format successful test completion."""
406
formatted = f"✓ {test} ({duration:.3f}s)"
407
self.stream.writeln(self.colors.passing(formatted))
408
409
def format_test_failure(self, test, error, duration):
410
"""Format test failure."""
411
formatted = f"✗ {test} ({duration:.3f}s)"
412
self.stream.writeln(self.colors.failing(formatted))
413
414
# Format error details
415
error_text = self.stream.formatText(str(error), indent=2)
416
self.stream.writeln(self.colors.failing(error_text))
417
418
def format_summary(self, total, passed, failed, errors, skipped):
419
"""Format test run summary."""
420
self.stream.writeln()
421
self.stream.writeln(self.colors.bold("Test Summary:"))
422
self.stream.writeln(f" Total: {total}")
423
self.stream.writeln(self.colors.passing(f" Passed: {passed}"))
424
if failed:
425
self.stream.writeln(self.colors.failing(f" Failed: {failed}"))
426
if errors:
427
self.stream.writeln(self.colors.error(f" Errors: {errors}"))
428
if skipped:
429
self.stream.writeln(self.colors.skipped(f" Skipped: {skipped}"))
430
431
# Usage
432
formatter = VerboseFormatter(sys.stdout)
433
formatter.format_test_start("test_example")
434
formatter.format_test_success("test_example", 0.025)
435
```
436
437
## Output Verbosity Levels
438
439
Green supports multiple verbosity levels that affect output formatting:
440
441
### Level 0 (Quiet): Minimal Output
442
- Only final summary
443
- Error/failure details
444
- No individual test indicators
445
446
### Level 1 (Default): Standard Output
447
- Test outcome characters (., F, E, s, x, u)
448
- Module/class hierarchy
449
- Summary statistics
450
451
### Level 2 (Verbose): Detailed Output
452
- Test names instead of just characters
453
- Test docstrings when available
454
- Timing information
455
456
### Level 3 (Very Verbose): Maximum Detail
457
- File locations for tests
458
- Detailed execution information
459
- Debug timing data
460
461
### Level 4 (Debug): Development Output
462
- Internal Green debugging information
463
- Process execution details
464
- Coverage integration debugging
465
466
## Color Support
467
468
Green automatically detects terminal color support and adjusts output accordingly:
469
470
- **TTY terminals**: Full color support
471
- **Non-TTY (pipes/files)**: Colors disabled by default
472
- **CI environments**: Configurable color behavior
473
- **Windows**: Enhanced Windows console support
474
- **Override**: Manual color control via configuration