or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-pytest-sugar

Pytest plugin that changes the default look and feel of pytest with progress bar and enhanced visual output

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/pytest-sugar@1.1.x

To install, run

npx @tessl/cli install tessl/pypi-pytest-sugar@1.1.0

index.mddocs/

pytest-sugar

A pytest plugin that changes the default visual appearance of pytest test execution. It provides a progress bar during test runs, displays test failures instantly as they occur rather than at the end, improves overall test result formatting with colored output, and adds visual enhancements to make test output more readable and informative.

Package Information

  • Package Name: pytest-sugar
  • Package Type: pytest plugin
  • Language: Python
  • Installation: pip install pytest-sugar

Core Imports

pytest-sugar is automatically activated when installed via pytest's plugin system:

# No explicit imports required - plugin auto-activates
# Test your code normally with pytest

For programmatic access to components:

from pytest_sugar import SugarTerminalReporter, Theme, strip_colors

Basic Usage

pytest-sugar works automatically once installed. Simply run your tests:

# Basic test execution with pytest-sugar enabled
pytest

# Verbose output (one test per line)
pytest --verbose

# Disable pytest-sugar
pytest -p no:sugar

# Force pytest-sugar in non-terminal environments
pytest --force-sugar

Configuration via config files:

# pytest-sugar.conf or ~/.pytest-sugar.conf
[theme]
success = green
fail = red
skipped = blue
progressbar = green

[sugar]
progressbar_length = 20%

Architecture

pytest-sugar integrates with pytest's plugin architecture through:

  • Plugin Registration: Automatic registration via pytest11 entry point
  • Hook System: Implements pytest's hook functions to customize test reporting
  • Terminal Reporter Replacement: Replaces pytest's default TerminalReporter with SugarTerminalReporter
  • Theme System: Configurable visual themes for colors and symbols
  • Progress Bar: Real-time progress visualization during test execution

Capabilities

Plugin Configuration

Core plugin configuration and initialization functions that integrate with pytest's hook system.

def pytest_addoption(parser: Parser) -> None:
    """
    Add command-line options to pytest.
    
    Adds pytest-sugar specific options:
    --old-summary: Show full tracebacks instead of one-line summaries
    --force-sugar: Force sugar output even when not in terminal
    --sugar-trace-dir: Directory for Playwright trace files
    --sugar-no-trace: Disable Playwright trace file detection
    
    Parameters:
    - parser: Parser - pytest argument parser
    """

def pytest_configure(config) -> None:
    """
    Configure pytest-sugar plugin (trylast=True).
    
    Replaces default terminal reporter with SugarTerminalReporter
    when running in terminal or when forced.
    
    Parameters:
    - config: Config - pytest configuration object
    """

def pytest_sessionstart(session: Session) -> None:
    """
    Called when pytest session starts.
    
    Loads theme configuration from config files and initializes
    global theme settings.
    
    Parameters:
    - session: Session - pytest session object
    """

Test Collection and Progress Tracking

Functions that handle test collection completion and maintain test count for progress tracking.

def pytest_collection_finish(session: Session) -> None:
    """
    Called when test collection is finished.
    
    Sets the total test count on the terminal reporter for
    progress bar calculations.
    
    Parameters:
    - session: Session - pytest session object
    """

def pytest_deselected(items: Sequence[Item]) -> None:
    """
    Called when tests are deselected.
    
    Updates the test count to exclude deselected tests from
    progress calculations.
    
    Parameters:
    - items: Sequence[Item] - deselected test items
    """

Test Status Reporting

Customizes how test results are visually represented with colored symbols and status indicators.

def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str]]:
    """
    Customize test status reporting with colored symbols.
    
    Returns custom status representation with colors and symbols
    based on test outcome (passed, failed, skipped, etc.).
    
    Parameters:
    - report: BaseReport - test execution report
    
    Returns:
    Optional[Tuple[str, str, str]] - (category, letter, word) or None
    """

Terminal Reporter

Enhanced terminal reporter that provides real-time progress visualization and improved test output formatting.

class SugarTerminalReporter:
    """
    Custom terminal reporter that replaces pytest's default TerminalReporter.
    
    Provides enhanced visual output with progress bar, instant failure display,
    and improved formatting.
    """
    
    def __init__(self, config: Config, file: Union[TextIO, None] = None) -> None:
        """
        Initialize the sugar terminal reporter.
        
        Parameters:
        - config: Config - pytest configuration object
        - file: Union[TextIO, None] - output file stream (optional)
        """
    
    def reset_tracked_lines(self) -> None:
        """Reset line tracking state for display management."""
    
    def pytest_collectreport(self, report: CollectReport) -> None:
        """
        Handle collection reports and display collection failures.
        
        Parameters:
        - report: CollectReport - collection report from pytest
        """
    
    def pytest_sessionstart(self, session: Session) -> None:
        """
        Handle session start and display header information.
        
        Parameters:
        - session: Session - pytest session object
        """
    
    def write_fspath_result(self, nodeid: str, res, **markup: bool) -> None:
        """
        Override to disable default file path result writing (no-op).
        
        pytest-sugar handles its own file path and result display formatting,
        so this method is overridden to prevent default behavior.
        
        Parameters:
        - nodeid: str - test node identifier
        - res: test result
        - **markup: bool - markup options (ignored)
        """
    
    def insert_progress(self, report: Union[CollectReport, TestReport]) -> None:
        """
        Insert progress bar into current terminal line.
        
        Creates and displays the progress bar with current test completion
        percentage and visual indicators for passed/failed tests.
        
        Parameters:
        - report: Union[CollectReport, TestReport] - test or collection report
        """
    
    def overwrite(self, line: str, rel_line_num: int) -> None:
        """
        Overwrite terminal line at relative position.
        
        Parameters:
        - line: str - text to write
        - rel_line_num: int - relative line number offset
        """
    
    def get_max_column_for_test_status(self) -> int:
        """
        Get maximum column width available for test status display.
        
        Returns:
        int - maximum column width for test status
        """
    
    def begin_new_line(self, report: Union[CollectReport, TestReport], print_filename: bool) -> None:
        """
        Start a new display line for test output.
        
        Parameters:
        - report: Union[CollectReport, TestReport] - test or collection report
        - print_filename: bool - whether to print the filename
        """
    
    def reached_last_column_for_test_status(self, report: Union[CollectReport, TestReport]) -> bool:
        """
        Check if the current line has reached maximum width.
        
        Parameters:
        - report: Union[CollectReport, TestReport] - test or collection report
        
        Returns:
        bool - True if line is at maximum width
        """
    
    def report_key(self, report: Union[CollectReport, TestReport]) -> Any:
        """
        Get key to identify which line the report should write to.
        
        Parameters:
        - report: Union[CollectReport, TestReport] - test or collection report
        
        Returns:
        Any - key for grouping reports by display line
        """
    
    def pytest_runtest_logstart(self, nodeid, location) -> None:
        """
        Handle test execution start logging (override to disable default behavior).
        
        Prevents pytest's default location line printing since pytest-sugar
        already displays module names and test names in verbose mode.
        
        Parameters:
        - nodeid: test node identifier
        - location: test location information
        """
    
    def pytest_runtest_logfinish(self, nodeid: str) -> None:
        """
        Handle test execution finish logging (override to disable default progress).
        
        Prevents pytest's default progress display since pytest-sugar
        provides its own progress bar implementation.
        
        Parameters:
        - nodeid: str - test node identifier
        """
    
    def pytest_runtest_logreport(self, report: TestReport) -> None:
        """
        Handle test execution reports and update display.
        
        Processes test results, updates progress bar, and displays
        test status with appropriate symbols and colors.
        
        Parameters:
        - report: TestReport - test execution report
        """
    
    def count(self, key: str, when: tuple = ("call",)) -> int:
        """
        Count test results by status and execution phase.
        
        Parameters:
        - key: str - result status key (passed, failed, skipped, etc.)
        - when: tuple - execution phases to include (default: ("call",))
        
        Returns:
        int - count of matching results
        """
    
    def summary_stats(self) -> None:
        """Display final test result summary with counts and Playwright trace information."""
    
    def _get_decoded_crashline(self, report: CollectReport) -> str:
        """
        Get decoded crash line from test report.
        
        Handles encoding issues when extracting crash line information
        from test failure reports.
        
        Parameters:
        - report: CollectReport - collection or test report
        
        Returns:
        str - decoded crash line text
        """
    
    def _get_lineno_from_report(self, report: CollectReport) -> int:
        """
        Extract line number from test report.
        
        Attempts multiple strategies to extract the line number where
        a test failure occurred, including doctest and regular test failures.
        
        Parameters:
        - report: CollectReport - collection or test report
        
        Returns:
        int - line number where failure occurred
        """
    
    def _find_playwright_trace(self, report: TestReport) -> Optional[str]:
        """
        Find Playwright trace file associated with a specific test report.
        
        Identifies the location of trace files using the test report's node ID
        and configuration options. Provides commands to view traces for failed tests.
        
        Parameters:
        - report: TestReport - test report containing node ID and failure details
        
        Returns:
        Optional[str] - command to view Playwright trace or None if not found/disabled
        """
    
    @staticmethod
    def _convert_node_to_trace_name(nodeid: str) -> str:
        """
        Convert pytest node ID to trace directory name format.
        
        Transforms pytest node identifiers into the expected trace directory
        naming convention used by Playwright.
        
        Parameters:
        - nodeid: str - pytest node identifier
        
        Returns:
        str - trace directory name
        """
    
    def summary_failures(self) -> None:
        """Override to prevent default failure summary (handled via instant display)."""
    
    def summary_errors(self) -> None:
        """Override to prevent default error summary (handled via instant display)."""
    
    def print_failure(self, report: Union[CollectReport, TestReport]) -> None:
        """
        Print test failure information immediately when failure occurs.
        
        Parameters:
        - report: Union[CollectReport, TestReport] - failed test report
        """

Theme System

Configurable theme system for customizing visual appearance of test output.

class Theme:
    """
    Data class for customizing visual appearance and symbols.
    
    Configurable through pytest-sugar.conf files.
    """
    
    # Color configuration
    header: Optional[str] = "magenta"
    skipped: Optional[str] = "blue"
    success: Optional[str] = "green"
    warning: Optional[str] = "yellow"
    fail: Optional[str] = "red"
    error: Optional[str] = "red"
    xfailed: Optional[str] = "green"
    xpassed: Optional[str] = "red"
    progressbar: Optional[str] = "green"
    progressbar_fail: Optional[str] = "red"
    progressbar_background: Optional[str] = "grey"
    path: Optional[str] = "cyan"
    name: Optional[str] = None
    unknown: Optional[str] = "blue"
    rerun: Optional[str] = "blue"
    
    # Symbol configuration
    symbol_passed: str = "✓"
    symbol_skipped: str = "s"
    symbol_failed: str = "⨯"
    symbol_failed_not_call: str = "ₓ"
    symbol_xfailed_skipped: str = "x"
    symbol_xfailed_failed: str = "X"
    symbol_unknown: str = "?"
    symbol_rerun: Optional[str] = "R"
    
    def __getitem__(self, x):
        """Access theme attributes by key for dynamic lookup."""

Distributed Testing Support

Support for pytest-xdist distributed testing plugin.

class DeferredXdistPlugin:
    """Plugin to handle pytest-xdist integration for distributed testing."""
    
    def pytest_xdist_node_collection_finished(self, node, ids) -> None:
        """
        Handle distributed collection completion.
        
        Updates test count when using pytest-xdist for parallel test execution.
        
        Parameters:
        - node: xdist node object
        - ids: list of test IDs collected by the node
        """

Utility Functions

Helper functions for text processing and display calculations.

def flatten(seq) -> Generator[Any, None, None]:
    """
    Flatten nested sequences into a single generator.
    
    Recursively flattens lists and tuples within the input sequence.
    
    Parameters:
    - seq: sequence to flatten (can contain nested lists/tuples)
    
    Yields:
    Any - flattened items from the input sequence
    """

def strip_colors(text: str) -> str:
    """
    Remove ANSI color codes from text strings.
    
    Uses regex to remove ANSI escape sequences for color formatting,
    useful for text processing and length calculations.
    
    Parameters:
    - text: str - text containing ANSI color codes
    
    Returns:
    str - text with color codes removed
    """

def real_string_length(string: str) -> int:
    """
    Calculate the real display length of a string after removing color codes.
    
    Determines actual character width for proper terminal alignment
    by first stripping ANSI color codes.
    
    Parameters:
    - string: str - string potentially containing color codes
    
    Returns:
    int - actual display length without color codes
    """

Command Line Options

pytest-sugar adds several command-line options to customize its behavior:

# Show detailed test failures instead of one-line tracebacks
pytest --old-summary

# Force pytest-sugar output even if not in a real terminal
pytest --force-sugar

# Specify directory for Playwright trace files (default: test-results)
pytest --sugar-trace-dir custom-traces

# Disable Playwright trace file detection and display
pytest --sugar-no-trace

Configuration

Config File Format

Create pytest-sugar.conf in your project root or ~/.pytest-sugar.conf in your home directory:

[theme]
# Color customization (use color names or None to disable)
success = green
fail = red
skipped = blue
warning = yellow
error = red
xfailed = green
xpassed = red
progressbar = green
progressbar_fail = red
progressbar_background = grey
path = cyan
name = 
unknown = blue
rerun = blue

# Symbol customization
symbol_passed = ✓
symbol_skipped = s
symbol_failed = ⨯
symbol_failed_not_call = ₓ
symbol_xfailed_skipped = x
symbol_xfailed_failed = X
symbol_unknown = ?
symbol_rerun = R

[sugar]
# Progress bar length (integer or percentage)
progressbar_length = 20%

Playwright Integration

pytest-sugar automatically detects and displays Playwright trace files for failed tests:

  • Searches for trace files in the configured directory (default: test-results)
  • Converts pytest node IDs to trace directory names
  • Displays trace file paths and view commands in failure output
  • Can be disabled with --sugar-no-trace option

Types

# Type definitions from typing module used in API signatures
from typing import Any, Dict, Generator, List, Optional, Sequence, TextIO, Tuple, Union

# pytest imports for type annotations
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.main import Session
from _pytest.nodes import Item
from _pytest.reports import BaseReport, CollectReport, TestReport
from _pytest.terminal import TerminalReporter

# External dependencies
from termcolor import colored

Constants

__version__: str = "1.1.1"
LEN_RIGHT_MARGIN: int = 0
LEN_PROGRESS_PERCENTAGE: int = 5
LEN_PROGRESS_BAR_SETTING: str = "10"
LEN_PROGRESS_BAR: Optional[int] = None
THEME: Theme  # Global theme instance
PROGRESS_BAR_BLOCKS: List[str]  # Unicode progress bar characters
IS_SUGAR_ENABLED: bool = False  # Global enable flag