or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

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

0

# pytest-sugar

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: pytest-sugar

7

- **Package Type**: pytest plugin

8

- **Language**: Python

9

- **Installation**: `pip install pytest-sugar`

10

11

## Core Imports

12

13

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

14

15

```python

16

# No explicit imports required - plugin auto-activates

17

# Test your code normally with pytest

18

```

19

20

For programmatic access to components:

21

22

```python

23

from pytest_sugar import SugarTerminalReporter, Theme, strip_colors

24

```

25

26

## Basic Usage

27

28

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

29

30

```bash

31

# Basic test execution with pytest-sugar enabled

32

pytest

33

34

# Verbose output (one test per line)

35

pytest --verbose

36

37

# Disable pytest-sugar

38

pytest -p no:sugar

39

40

# Force pytest-sugar in non-terminal environments

41

pytest --force-sugar

42

```

43

44

Configuration via config files:

45

46

```ini

47

# pytest-sugar.conf or ~/.pytest-sugar.conf

48

[theme]

49

success = green

50

fail = red

51

skipped = blue

52

progressbar = green

53

54

[sugar]

55

progressbar_length = 20%

56

```

57

58

## Architecture

59

60

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

61

62

- **Plugin Registration**: Automatic registration via `pytest11` entry point

63

- **Hook System**: Implements pytest's hook functions to customize test reporting

64

- **Terminal Reporter Replacement**: Replaces pytest's default `TerminalReporter` with `SugarTerminalReporter`

65

- **Theme System**: Configurable visual themes for colors and symbols

66

- **Progress Bar**: Real-time progress visualization during test execution

67

68

## Capabilities

69

70

### Plugin Configuration

71

72

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

73

74

```python { .api }

75

def pytest_addoption(parser: Parser) -> None:

76

"""

77

Add command-line options to pytest.

78

79

Adds pytest-sugar specific options:

80

--old-summary: Show full tracebacks instead of one-line summaries

81

--force-sugar: Force sugar output even when not in terminal

82

--sugar-trace-dir: Directory for Playwright trace files

83

--sugar-no-trace: Disable Playwright trace file detection

84

85

Parameters:

86

- parser: Parser - pytest argument parser

87

"""

88

89

def pytest_configure(config) -> None:

90

"""

91

Configure pytest-sugar plugin (trylast=True).

92

93

Replaces default terminal reporter with SugarTerminalReporter

94

when running in terminal or when forced.

95

96

Parameters:

97

- config: Config - pytest configuration object

98

"""

99

100

def pytest_sessionstart(session: Session) -> None:

101

"""

102

Called when pytest session starts.

103

104

Loads theme configuration from config files and initializes

105

global theme settings.

106

107

Parameters:

108

- session: Session - pytest session object

109

"""

110

```

111

112

### Test Collection and Progress Tracking

113

114

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

115

116

```python { .api }

117

def pytest_collection_finish(session: Session) -> None:

118

"""

119

Called when test collection is finished.

120

121

Sets the total test count on the terminal reporter for

122

progress bar calculations.

123

124

Parameters:

125

- session: Session - pytest session object

126

"""

127

128

def pytest_deselected(items: Sequence[Item]) -> None:

129

"""

130

Called when tests are deselected.

131

132

Updates the test count to exclude deselected tests from

133

progress calculations.

134

135

Parameters:

136

- items: Sequence[Item] - deselected test items

137

"""

138

```

139

140

### Test Status Reporting

141

142

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

143

144

```python { .api }

145

def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str]]:

146

"""

147

Customize test status reporting with colored symbols.

148

149

Returns custom status representation with colors and symbols

150

based on test outcome (passed, failed, skipped, etc.).

151

152

Parameters:

153

- report: BaseReport - test execution report

154

155

Returns:

156

Optional[Tuple[str, str, str]] - (category, letter, word) or None

157

"""

158

```

159

160

### Terminal Reporter

161

162

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

163

164

```python { .api }

165

class SugarTerminalReporter:

166

"""

167

Custom terminal reporter that replaces pytest's default TerminalReporter.

168

169

Provides enhanced visual output with progress bar, instant failure display,

170

and improved formatting.

171

"""

172

173

def __init__(self, config: Config, file: Union[TextIO, None] = None) -> None:

174

"""

175

Initialize the sugar terminal reporter.

176

177

Parameters:

178

- config: Config - pytest configuration object

179

- file: Union[TextIO, None] - output file stream (optional)

180

"""

181

182

def reset_tracked_lines(self) -> None:

183

"""Reset line tracking state for display management."""

184

185

def pytest_collectreport(self, report: CollectReport) -> None:

186

"""

187

Handle collection reports and display collection failures.

188

189

Parameters:

190

- report: CollectReport - collection report from pytest

191

"""

192

193

def pytest_sessionstart(self, session: Session) -> None:

194

"""

195

Handle session start and display header information.

196

197

Parameters:

198

- session: Session - pytest session object

199

"""

200

201

def write_fspath_result(self, nodeid: str, res, **markup: bool) -> None:

202

"""

203

Override to disable default file path result writing (no-op).

204

205

pytest-sugar handles its own file path and result display formatting,

206

so this method is overridden to prevent default behavior.

207

208

Parameters:

209

- nodeid: str - test node identifier

210

- res: test result

211

- **markup: bool - markup options (ignored)

212

"""

213

214

def insert_progress(self, report: Union[CollectReport, TestReport]) -> None:

215

"""

216

Insert progress bar into current terminal line.

217

218

Creates and displays the progress bar with current test completion

219

percentage and visual indicators for passed/failed tests.

220

221

Parameters:

222

- report: Union[CollectReport, TestReport] - test or collection report

223

"""

224

225

def overwrite(self, line: str, rel_line_num: int) -> None:

226

"""

227

Overwrite terminal line at relative position.

228

229

Parameters:

230

- line: str - text to write

231

- rel_line_num: int - relative line number offset

232

"""

233

234

def get_max_column_for_test_status(self) -> int:

235

"""

236

Get maximum column width available for test status display.

237

238

Returns:

239

int - maximum column width for test status

240

"""

241

242

def begin_new_line(self, report: Union[CollectReport, TestReport], print_filename: bool) -> None:

243

"""

244

Start a new display line for test output.

245

246

Parameters:

247

- report: Union[CollectReport, TestReport] - test or collection report

248

- print_filename: bool - whether to print the filename

249

"""

250

251

def reached_last_column_for_test_status(self, report: Union[CollectReport, TestReport]) -> bool:

252

"""

253

Check if the current line has reached maximum width.

254

255

Parameters:

256

- report: Union[CollectReport, TestReport] - test or collection report

257

258

Returns:

259

bool - True if line is at maximum width

260

"""

261

262

def report_key(self, report: Union[CollectReport, TestReport]) -> Any:

263

"""

264

Get key to identify which line the report should write to.

265

266

Parameters:

267

- report: Union[CollectReport, TestReport] - test or collection report

268

269

Returns:

270

Any - key for grouping reports by display line

271

"""

272

273

def pytest_runtest_logstart(self, nodeid, location) -> None:

274

"""

275

Handle test execution start logging (override to disable default behavior).

276

277

Prevents pytest's default location line printing since pytest-sugar

278

already displays module names and test names in verbose mode.

279

280

Parameters:

281

- nodeid: test node identifier

282

- location: test location information

283

"""

284

285

def pytest_runtest_logfinish(self, nodeid: str) -> None:

286

"""

287

Handle test execution finish logging (override to disable default progress).

288

289

Prevents pytest's default progress display since pytest-sugar

290

provides its own progress bar implementation.

291

292

Parameters:

293

- nodeid: str - test node identifier

294

"""

295

296

def pytest_runtest_logreport(self, report: TestReport) -> None:

297

"""

298

Handle test execution reports and update display.

299

300

Processes test results, updates progress bar, and displays

301

test status with appropriate symbols and colors.

302

303

Parameters:

304

- report: TestReport - test execution report

305

"""

306

307

def count(self, key: str, when: tuple = ("call",)) -> int:

308

"""

309

Count test results by status and execution phase.

310

311

Parameters:

312

- key: str - result status key (passed, failed, skipped, etc.)

313

- when: tuple - execution phases to include (default: ("call",))

314

315

Returns:

316

int - count of matching results

317

"""

318

319

def summary_stats(self) -> None:

320

"""Display final test result summary with counts and Playwright trace information."""

321

322

def _get_decoded_crashline(self, report: CollectReport) -> str:

323

"""

324

Get decoded crash line from test report.

325

326

Handles encoding issues when extracting crash line information

327

from test failure reports.

328

329

Parameters:

330

- report: CollectReport - collection or test report

331

332

Returns:

333

str - decoded crash line text

334

"""

335

336

def _get_lineno_from_report(self, report: CollectReport) -> int:

337

"""

338

Extract line number from test report.

339

340

Attempts multiple strategies to extract the line number where

341

a test failure occurred, including doctest and regular test failures.

342

343

Parameters:

344

- report: CollectReport - collection or test report

345

346

Returns:

347

int - line number where failure occurred

348

"""

349

350

def _find_playwright_trace(self, report: TestReport) -> Optional[str]:

351

"""

352

Find Playwright trace file associated with a specific test report.

353

354

Identifies the location of trace files using the test report's node ID

355

and configuration options. Provides commands to view traces for failed tests.

356

357

Parameters:

358

- report: TestReport - test report containing node ID and failure details

359

360

Returns:

361

Optional[str] - command to view Playwright trace or None if not found/disabled

362

"""

363

364

@staticmethod

365

def _convert_node_to_trace_name(nodeid: str) -> str:

366

"""

367

Convert pytest node ID to trace directory name format.

368

369

Transforms pytest node identifiers into the expected trace directory

370

naming convention used by Playwright.

371

372

Parameters:

373

- nodeid: str - pytest node identifier

374

375

Returns:

376

str - trace directory name

377

"""

378

379

def summary_failures(self) -> None:

380

"""Override to prevent default failure summary (handled via instant display)."""

381

382

def summary_errors(self) -> None:

383

"""Override to prevent default error summary (handled via instant display)."""

384

385

def print_failure(self, report: Union[CollectReport, TestReport]) -> None:

386

"""

387

Print test failure information immediately when failure occurs.

388

389

Parameters:

390

- report: Union[CollectReport, TestReport] - failed test report

391

"""

392

```

393

394

### Theme System

395

396

Configurable theme system for customizing visual appearance of test output.

397

398

```python { .api }

399

class Theme:

400

"""

401

Data class for customizing visual appearance and symbols.

402

403

Configurable through pytest-sugar.conf files.

404

"""

405

406

# Color configuration

407

header: Optional[str] = "magenta"

408

skipped: Optional[str] = "blue"

409

success: Optional[str] = "green"

410

warning: Optional[str] = "yellow"

411

fail: Optional[str] = "red"

412

error: Optional[str] = "red"

413

xfailed: Optional[str] = "green"

414

xpassed: Optional[str] = "red"

415

progressbar: Optional[str] = "green"

416

progressbar_fail: Optional[str] = "red"

417

progressbar_background: Optional[str] = "grey"

418

path: Optional[str] = "cyan"

419

name: Optional[str] = None

420

unknown: Optional[str] = "blue"

421

rerun: Optional[str] = "blue"

422

423

# Symbol configuration

424

symbol_passed: str = "✓"

425

symbol_skipped: str = "s"

426

symbol_failed: str = "⨯"

427

symbol_failed_not_call: str = "ₓ"

428

symbol_xfailed_skipped: str = "x"

429

symbol_xfailed_failed: str = "X"

430

symbol_unknown: str = "?"

431

symbol_rerun: Optional[str] = "R"

432

433

def __getitem__(self, x):

434

"""Access theme attributes by key for dynamic lookup."""

435

```

436

437

### Distributed Testing Support

438

439

Support for pytest-xdist distributed testing plugin.

440

441

```python { .api }

442

class DeferredXdistPlugin:

443

"""Plugin to handle pytest-xdist integration for distributed testing."""

444

445

def pytest_xdist_node_collection_finished(self, node, ids) -> None:

446

"""

447

Handle distributed collection completion.

448

449

Updates test count when using pytest-xdist for parallel test execution.

450

451

Parameters:

452

- node: xdist node object

453

- ids: list of test IDs collected by the node

454

"""

455

```

456

457

### Utility Functions

458

459

Helper functions for text processing and display calculations.

460

461

```python { .api }

462

def flatten(seq) -> Generator[Any, None, None]:

463

"""

464

Flatten nested sequences into a single generator.

465

466

Recursively flattens lists and tuples within the input sequence.

467

468

Parameters:

469

- seq: sequence to flatten (can contain nested lists/tuples)

470

471

Yields:

472

Any - flattened items from the input sequence

473

"""

474

475

def strip_colors(text: str) -> str:

476

"""

477

Remove ANSI color codes from text strings.

478

479

Uses regex to remove ANSI escape sequences for color formatting,

480

useful for text processing and length calculations.

481

482

Parameters:

483

- text: str - text containing ANSI color codes

484

485

Returns:

486

str - text with color codes removed

487

"""

488

489

def real_string_length(string: str) -> int:

490

"""

491

Calculate the real display length of a string after removing color codes.

492

493

Determines actual character width for proper terminal alignment

494

by first stripping ANSI color codes.

495

496

Parameters:

497

- string: str - string potentially containing color codes

498

499

Returns:

500

int - actual display length without color codes

501

"""

502

```

503

504

## Command Line Options

505

506

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

507

508

```bash

509

# Show detailed test failures instead of one-line tracebacks

510

pytest --old-summary

511

512

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

513

pytest --force-sugar

514

515

# Specify directory for Playwright trace files (default: test-results)

516

pytest --sugar-trace-dir custom-traces

517

518

# Disable Playwright trace file detection and display

519

pytest --sugar-no-trace

520

```

521

522

## Configuration

523

524

### Config File Format

525

526

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

527

528

```ini

529

[theme]

530

# Color customization (use color names or None to disable)

531

success = green

532

fail = red

533

skipped = blue

534

warning = yellow

535

error = red

536

xfailed = green

537

xpassed = red

538

progressbar = green

539

progressbar_fail = red

540

progressbar_background = grey

541

path = cyan

542

name =

543

unknown = blue

544

rerun = blue

545

546

# Symbol customization

547

symbol_passed = ✓

548

symbol_skipped = s

549

symbol_failed = ⨯

550

symbol_failed_not_call = ₓ

551

symbol_xfailed_skipped = x

552

symbol_xfailed_failed = X

553

symbol_unknown = ?

554

symbol_rerun = R

555

556

[sugar]

557

# Progress bar length (integer or percentage)

558

progressbar_length = 20%

559

```

560

561

### Playwright Integration

562

563

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

564

565

- Searches for trace files in the configured directory (default: `test-results`)

566

- Converts pytest node IDs to trace directory names

567

- Displays trace file paths and view commands in failure output

568

- Can be disabled with `--sugar-no-trace` option

569

570

## Types

571

572

```python { .api }

573

# Type definitions from typing module used in API signatures

574

from typing import Any, Dict, Generator, List, Optional, Sequence, TextIO, Tuple, Union

575

576

# pytest imports for type annotations

577

from _pytest.config import Config

578

from _pytest.config.argparsing import Parser

579

from _pytest.main import Session

580

from _pytest.nodes import Item

581

from _pytest.reports import BaseReport, CollectReport, TestReport

582

from _pytest.terminal import TerminalReporter

583

584

# External dependencies

585

from termcolor import colored

586

```

587

588

## Constants

589

590

```python { .api }

591

__version__: str = "1.1.1"

592

LEN_RIGHT_MARGIN: int = 0

593

LEN_PROGRESS_PERCENTAGE: int = 5

594

LEN_PROGRESS_BAR_SETTING: str = "10"

595

LEN_PROGRESS_BAR: Optional[int] = None

596

THEME: Theme # Global theme instance

597

PROGRESS_BAR_BLOCKS: List[str] # Unicode progress bar characters

598

IS_SUGAR_ENABLED: bool = False # Global enable flag

599

```