or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-pytest-rerunfailures

pytest plugin to re-run tests to eliminate flaky failures

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

To install, run

npx @tessl/cli install tessl/pypi-pytest-rerunfailures@16.0.0

0

# pytest-rerunfailures

1

2

A pytest plugin that automatically re-runs failed tests to eliminate intermittent failures and flaky test behavior. It provides comprehensive command-line options for controlling test reruns including global rerun counts, selective rerun filtering based on exception patterns, configurable delays between reruns, and marker-based test decoration for individual test control.

3

4

## Package Information

5

6

- **Package Name**: pytest-rerunfailures

7

- **Package Type**: pytest plugin

8

- **Language**: Python

9

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

10

- **Requirements**: Python >=3.9, pytest >=7.4 (!=8.2.2)

11

- **Optional**: pytest-xdist >=2.3.0 for crash recovery

12

13

## Core Imports

14

15

The plugin is automatically discovered by pytest when installed. No explicit imports are needed for basic usage.

16

17

For accessing plugin internals programmatically:

18

19

```python

20

import pytest_rerunfailures

21

```

22

23

## Basic Usage

24

25

### Command Line Usage

26

27

Re-run all test failures up to 5 times:

28

29

```bash

30

pytest --reruns 5

31

```

32

33

Add 1-second delay between reruns:

34

35

```bash

36

pytest --reruns 5 --reruns-delay 1

37

```

38

39

Only rerun specific error types:

40

41

```bash

42

pytest --reruns 3 --only-rerun AssertionError --only-rerun ValueError

43

```

44

45

Skip reruns for specific error types:

46

47

```bash

48

pytest --reruns 3 --rerun-except ConnectionError

49

```

50

51

### Marker Usage

52

53

Mark individual tests for reruns:

54

55

```python

56

import pytest

57

58

@pytest.mark.flaky(reruns=5)

59

def test_sometimes_fails():

60

import random

61

assert random.choice([True, False])

62

63

@pytest.mark.flaky(reruns=3, reruns_delay=2)

64

def test_with_delay():

65

# Will be retried up to 3 times with 2-second delays

66

pass

67

68

@pytest.mark.flaky(reruns=2, condition="sys.platform.startswith('win32')")

69

def test_windows_only_reruns():

70

# Only reruns on Windows

71

pass

72

```

73

74

## Capabilities

75

76

### Command Line Options

77

78

Global configuration options for controlling test reruns across the entire test suite.

79

80

```python { .api }

81

def pytest_addoption(parser):

82

"""

83

Adds command-line options for test reruns.

84

85

Options added:

86

--reruns: Number of times to re-run failed tests (default: 0)

87

--reruns-delay: Delay in seconds between reruns

88

--only-rerun: Regex patterns for errors to rerun (repeatable)

89

--rerun-except: Regex patterns for errors NOT to rerun (repeatable)

90

--fail-on-flaky: Fail with exit code 7 if flaky test passes on rerun

91

"""

92

```

93

94

### Test Execution Control

95

96

Core functions for controlling test execution and rerun behavior.

97

98

```python { .api }

99

def get_reruns_count(item):

100

"""

101

Get the number of reruns for a test item.

102

Priority: marker > command line > ini file

103

104

Args:

105

item: pytest test item

106

107

Returns:

108

int: Number of reruns for this test

109

"""

110

111

def get_reruns_delay(item):

112

"""

113

Get the delay between reruns for a test item.

114

115

Args:

116

item: pytest test item

117

118

Returns:

119

float: Delay in seconds between reruns

120

"""

121

122

def get_reruns_condition(item):

123

"""

124

Evaluate whether reruns should happen for a test item.

125

126

Args:

127

item: pytest test item

128

129

Returns:

130

bool: Whether reruns are enabled for this test

131

"""

132

133

def evaluate_condition(item, mark, condition: object) -> bool:

134

"""

135

Evaluate condition expressions for flaky marker.

136

137

Args:

138

item: pytest test item

139

mark: pytest marker object

140

condition: str or bool condition to evaluate

141

142

Returns:

143

bool: Result of condition evaluation

144

"""

145

```

146

147

### Pytest Hooks

148

149

Plugin hooks that integrate with pytest's test execution lifecycle.

150

151

```python { .api }

152

def pytest_configure(config):

153

"""

154

Configure the plugin and register flaky marker.

155

156

Args:

157

config: pytest configuration object

158

"""

159

160

def pytest_runtest_protocol(item, nextitem):

161

"""

162

Main test execution protocol with rerun logic.

163

164

Args:

165

item: pytest test item to execute

166

nextitem: next test item in queue

167

168

Returns:

169

bool: True if protocol handled (reruns enabled), None for default behavior

170

"""

171

172

def pytest_runtest_teardown(item, nextitem):

173

"""

174

Handle test teardown with rerun logic.

175

176

Args:

177

item: pytest test item

178

nextitem: next test item in queue

179

"""

180

181

@pytest.hookimpl(hookwrapper=True)

182

def pytest_runtest_makereport(item, call):

183

"""

184

Create test reports with rerun tracking.

185

186

Args:

187

item: pytest test item

188

call: pytest call info

189

190

Returns:

191

TestReport: Enhanced with rerun information

192

"""

193

194

def pytest_report_teststatus(report):

195

"""

196

Report test status including rerun status.

197

198

Args:

199

report: pytest test report

200

201

Returns:

202

tuple: (outcome, letter, verbose_word) for rerun status

203

"""

204

205

def pytest_terminal_summary(terminalreporter):

206

"""

207

Display rerun summary in terminal output.

208

209

Args:

210

terminalreporter: pytest terminal reporter

211

"""

212

213

@pytest.hookimpl(trylast=True)

214

def pytest_sessionfinish(session, exitstatus):

215

"""

216

Handle session finish with flaky test detection.

217

218

Args:

219

session: pytest session

220

exitstatus: current exit status

221

"""

222

```

223

224

### Test State Management

225

226

Functions for managing test state during reruns, including fixture cleanup and setup state management.

227

228

```python { .api }

229

def check_options(config):

230

"""

231

Validate command-line options compatibility.

232

233

Args:

234

config: pytest configuration object

235

236

Raises:

237

pytest.UsageError: If incompatible options are used

238

"""

239

240

def works_with_current_xdist():

241

"""

242

Check compatibility with pytest-xdist version.

243

244

Returns:

245

bool or None: True if compatible, False if incompatible, None if not installed

246

"""

247

248

def is_master(config):

249

"""

250

Determine if running on master node in distributed tests.

251

252

Args:

253

config: pytest configuration object

254

255

Returns:

256

bool: True if master node, False if worker

257

"""

258

259

def show_rerun(terminalreporter, lines):

260

"""

261

Display rerun test information.

262

263

Args:

264

terminalreporter: pytest terminal reporter

265

lines: list to append rerun information to

266

"""

267

```

268

269

### Distributed Testing Support

270

271

Classes and hooks for pytest-xdist integration and crash recovery.

272

273

```python { .api }

274

class XDistHooks:

275

"""Hooks for pytest-xdist integration."""

276

277

def pytest_configure_node(self, node):

278

"""

279

Configure xdist worker nodes.

280

281

Args:

282

node: xdist worker node

283

"""

284

285

def pytest_handlecrashitem(self, crashitem, report, sched):

286

"""

287

Handle crashed tests in distributed execution.

288

289

Args:

290

crashitem: crashed test item identifier

291

report: crash report

292

sched: xdist scheduler

293

"""

294

```

295

296

### Status Database Classes

297

298

Database classes for tracking test failures and reruns across distributed test execution.

299

300

```python { .api }

301

class StatusDB:

302

"""Base in-memory database for tracking test reruns and failures."""

303

304

def add_test_failure(self, crashitem):

305

"""

306

Record a test failure.

307

308

Args:

309

crashitem: test item identifier

310

"""

311

312

def get_test_failures(self, crashitem):

313

"""

314

Get failure count for a test.

315

316

Args:

317

crashitem: test item identifier

318

319

Returns:

320

int: Number of failures recorded

321

"""

322

323

def set_test_reruns(self, crashitem, reruns):

324

"""

325

Set rerun count for a test.

326

327

Args:

328

crashitem: test item identifier

329

reruns: number of reruns allowed

330

"""

331

332

def get_test_reruns(self, crashitem):

333

"""

334

Get rerun count for a test.

335

336

Args:

337

crashitem: test item identifier

338

339

Returns:

340

int: Number of reruns allowed

341

"""

342

343

class ServerStatusDB(StatusDB):

344

"""Server-side socket database for distributed testing."""

345

346

@property

347

def sock_port(self):

348

"""

349

Get the socket port for client connections.

350

351

Returns:

352

int: Port number

353

"""

354

355

def run_server(self):

356

"""Run the database server to handle client connections."""

357

358

class ClientStatusDB(StatusDB):

359

"""Client-side socket database for distributed testing."""

360

361

def __init__(self, sock_port):

362

"""

363

Initialize client database.

364

365

Args:

366

sock_port: server socket port to connect to

367

"""

368

```

369

370

## Marker Reference

371

372

### @pytest.mark.flaky

373

374

Mark individual tests for automatic reruns on failure.

375

376

```python { .api }

377

@pytest.mark.flaky(

378

reruns=1, # int: Number of reruns (default: 1)

379

reruns_delay=0, # float: Delay between reruns in seconds

380

condition=True, # str|bool: Condition for when reruns should happen

381

only_rerun=None, # str|list[str]: Regex patterns for errors to rerun

382

rerun_except=None # str|list[str]: Regex patterns for errors NOT to rerun

383

)

384

def test_function():

385

"""Test that may be flaky and need reruns."""

386

```

387

388

## Configuration

389

390

### Command Line Options

391

392

- `--reruns N`: Re-run failed tests N times (default: 0)

393

- `--reruns-delay SECONDS`: Add delay between reruns (default: 0)

394

- `--only-rerun REGEX`: Only rerun errors matching regex (repeatable)

395

- `--rerun-except REGEX`: Skip reruns for errors matching regex (repeatable)

396

- `--fail-on-flaky`: Fail with exit code 7 if flaky test passes on rerun

397

398

### Configuration File Options

399

400

In `pytest.ini` or `pyproject.toml`:

401

402

```ini

403

[tool.pytest.ini_options]

404

reruns = "3"

405

reruns_delay = "1"

406

```

407

408

### Priority Order

409

410

1. `@pytest.mark.flaky` marker (highest priority)

411

2. Command-line options (`--reruns`, `--reruns-delay`)

412

3. Configuration file options (lowest priority)

413

414

## Error Handling

415

416

### Compatibility Restrictions

417

418

- Not compatible with `--pdb` flag

419

- Not compatible with `--looponfail` flag (pytest-xdist)

420

- Not compatible with `flaky` plugin (choose one or the other)

421

422

### Exception Filtering

423

424

Control which exceptions trigger reruns:

425

426

```python

427

# Only rerun on specific exceptions

428

@pytest.mark.flaky(only_rerun=["AssertionError", "ConnectionError"])

429

def test_network_operation():

430

pass

431

432

# Skip reruns for specific exceptions

433

@pytest.mark.flaky(rerun_except="KeyboardInterrupt")

434

def test_user_interaction():

435

pass

436

```

437

438

### Conditional Reruns

439

440

Use conditions to control when reruns happen:

441

442

```python

443

import sys

444

445

# Only rerun on Windows

446

@pytest.mark.flaky(reruns=3, condition="sys.platform.startswith('win32')")

447

def test_windows_specific():

448

pass

449

450

# Only rerun in CI environment

451

@pytest.mark.flaky(reruns=2, condition="'CI' in os.environ")

452

def test_ci_sensitive():

453

pass

454

```

455

456

## Advanced Usage

457

458

### Crash Recovery

459

460

With pytest-xdist installed, the plugin can recover from hard crashes:

461

462

```bash

463

# Enable crash recovery with parallel execution

464

pytest -n auto --reruns 3

465

```

466

467

### Accessing Execution Count

468

469

In custom pytest hooks, access the execution count:

470

471

```python

472

@pytest.hookimpl(tryfirst=True)

473

def pytest_runtest_makereport(item, call):

474

if hasattr(item, 'execution_count'):

475

print(f"Test {item.nodeid} executed {item.execution_count} times")

476

```

477

478

### Test Item Attributes

479

480

The plugin adds these attributes to test items:

481

482

- `execution_count`: Number of times the test has been executed

483

- `_test_failed_statuses`: Dict tracking failure status for each test phase

484

- `_terminal_errors`: Dict tracking terminal errors that prevent reruns

485

486

### Report Attributes

487

488

The plugin adds these attributes to test reports:

489

490

- `rerun`: Rerun number for this report (0 for first run)

491

- `outcome`: May be "rerun" for intermediate rerun reports

492

493

## Types

494

495

```python { .api }

496

# Test item attributes added by plugin

497

class TestItem:

498

execution_count: int

499

_test_failed_statuses: dict[str, bool]

500

_terminal_errors: dict[str, bool]

501

502

# Report attributes added by plugin

503

class TestReport:

504

rerun: int # 0 for first run, 1+ for reruns

505

outcome: str # may be "rerun" for intermediate reports

506

507

# Configuration constants

508

HAS_PYTEST_HANDLECRASHITEM: bool # True if xdist crash handling available

509

RERUNS_DESC: str # Description for --reruns option

510

RERUNS_DELAY_DESC: str # Description for --reruns-delay option

511

suspended_finalizers: dict # Global storage for suspended test finalizers

512

```