or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-processing.mdconfiguration.mderror-processing.mdindex.mdmain-interface.mdplugin-development.mdpytest-integration.mdvcs-hooks.md

pytest-integration.mddocs/

0

# Pytest Integration

1

2

Seamless integration with pytest for automated code quality checking during testing. Pylama provides a pytest plugin that automatically discovers and checks Python files as part of your test suite.

3

4

## Capabilities

5

6

### Plugin Configuration

7

8

Add pylama checking option to pytest command line interface.

9

10

```python { .api }

11

def pytest_addoption(parser):

12

"""

13

Add --pylama option to pytest command line.

14

15

Args:

16

parser: pytest argument parser

17

18

Adds:

19

--pylama: Enable pylama code quality checks on .py files

20

21

When enabled, pytest will collect all .py files and run pylama

22

checks on them as part of the test suite.

23

"""

24

```

25

26

### File Collection

27

28

Collect Python files for pylama checking during pytest discovery phase.

29

30

```python { .api }

31

def pytest_collect_file(path, parent):

32

"""

33

Collect Python files for pylama checking.

34

35

Args:

36

path: File path being considered for collection

37

parent: Parent pytest collector

38

39

Returns:

40

Optional[PylamaFile]: PylamaFile collector if --pylama enabled and path is .py file

41

42

Only collects files when:

43

- --pylama option is enabled

44

- File has .py extension

45

- File is not excluded by pytest collection rules

46

"""

47

```

48

49

### Session Management

50

51

Manage caching across pytest sessions for performance optimization.

52

53

```python { .api }

54

def pytest_sessionstart(session):

55

"""

56

Initialize pylama session with file modification time caching.

57

58

Args:

59

session: pytest session object

60

61

Sets up caching to skip unchanged files that previously passed

62

pylama checks, improving performance on large codebases.

63

"""

64

65

def pytest_sessionfinish(session):

66

"""

67

Save modification time cache at end of pytest session.

68

69

Args:

70

session: pytest session object

71

72

Persists file modification times to cache for next test run,

73

enabling incremental checking.

74

"""

75

76

def pytest_load_initial_conftests(early_config, *_):

77

"""

78

Register pylama markers before pytest configuration loading.

79

80

Args:

81

early_config: Early pytest configuration

82

83

Registers 'pycodestyle' marker to prevent warnings when using

84

--strict command line argument.

85

"""

86

```

87

88

### Test Implementation

89

90

Core test classes that perform pylama checking within pytest framework.

91

92

```python { .api }

93

class PylamaError(Exception):

94

"""

95

Exception raised when pylama checks fail.

96

97

Contains formatted error messages from pylama checking that

98

will be displayed in pytest output when tests fail.

99

"""

100

101

class PylamaFile(pytest.File):

102

"""

103

Pytest file collector for pylama checks.

104

105

Represents a Python file that will be checked by pylama.

106

Creates a single PylamaItem for the entire file.

107

"""

108

109

def collect(self):

110

"""

111

Create test items for this file.

112

113

Returns:

114

List[PylamaItem]: Single item representing pylama check for this file

115

"""

116

117

class PylamaItem(pytest.Item):

118

"""

119

Pytest test item for individual file pylama checks.

120

121

Represents the actual test that runs pylama on a single file

122

and reports any code quality issues as test failures.

123

"""

124

125

def __init__(self, *args, **kwargs):

126

"""

127

Initialize pylama test item.

128

129

Automatically adds 'pycodestyle' marker and sets up caching

130

infrastructure for performance optimization.

131

"""

132

133

def setup(self):

134

"""

135

Set up test item with caching logic.

136

137

Returns:

138

bool: True if setup successful, False if should skip

139

140

Checks file modification time against cache and skips test

141

if file hasn't changed since last successful check.

142

"""

143

144

def runtest(self):

145

"""

146

Execute pylama check on the file.

147

148

Raises:

149

PylamaError: If any code quality issues are found

150

151

Runs pylama analysis and raises PylamaError with formatted

152

error messages if any issues are discovered.

153

"""

154

155

def repr_failure(self, excinfo, style=None):

156

"""

157

Format test failure output.

158

159

Args:

160

excinfo: Exception information from test failure

161

style: Output style (unused)

162

163

Returns:

164

str: Formatted error messages for pytest output

165

"""

166

```

167

168

### File Checking

169

170

Standalone function for checking individual files within pytest context.

171

172

```python { .api }

173

def check_file(path):

174

"""

175

Check a single file using pylama with default configuration.

176

177

Args:

178

path: File path to check

179

180

Returns:

181

List[Error]: Errors found in the file

182

183

Loads default pylama configuration and checks the specified file,

184

returning any code quality issues found.

185

"""

186

```

187

188

## Usage Examples

189

190

### Basic Pytest Integration

191

192

```python

193

# Run tests with pylama checking

194

import subprocess

195

196

# Enable pylama for all .py files

197

result = subprocess.run(['pytest', '--pylama'])

198

199

# Combine with specific test selection

200

result = subprocess.run(['pytest', '--pylama', 'tests/', '-v'])

201

202

# Use with pytest configuration

203

result = subprocess.run(['pytest', '--pylama', '--tb=short'])

204

```

205

206

### Configuration in pytest.ini

207

208

```ini

209

[tool:pytest]

210

addopts = --pylama

211

testpaths = src tests

212

python_files = *.py

213

markers =

214

pycodestyle: Code style checks

215

```

216

217

### Configuration in pyproject.toml

218

219

```toml

220

[tool.pytest.ini_options]

221

addopts = "--pylama"

222

testpaths = ["src", "tests"]

223

markers = [

224

"pycodestyle: Code style checks"

225

]

226

```

227

228

### Programmatic Usage

229

230

```python

231

import pytest

232

from pylama.pytest import check_file

233

234

# Run pytest with pylama programmatically

235

exit_code = pytest.main(['--pylama', 'src/'])

236

237

# Check individual file

238

errors = check_file('mymodule.py')

239

if errors:

240

for error in errors:

241

print(f"{error.filename}:{error.lnum} - {error.message}")

242

```

243

244

### Custom Test Integration

245

246

```python

247

import pytest

248

from pylama.pytest import check_file

249

250

def test_code_quality():

251

"""Custom test function that uses pylama checking."""

252

253

# Check specific files

254

files_to_check = ['src/main.py', 'src/utils.py']

255

256

all_errors = []

257

for filepath in files_to_check:

258

errors = check_file(filepath)

259

all_errors.extend(errors)

260

261

# Assert no code quality issues

262

if all_errors:

263

error_messages = [

264

f"{err.filename}:{err.lnum} - {err.text}"

265

for err in all_errors

266

]

267

pytest.fail(f"Code quality issues found:\n" + "\n".join(error_messages))

268

```

269

270

### Conditional Pylama Testing

271

272

```python

273

import pytest

274

import sys

275

276

# Skip pylama tests in certain conditions

277

@pytest.mark.skipif(sys.version_info < (3, 8), reason="Requires Python 3.8+")

278

def test_pylama_advanced_features():

279

"""Test that only runs on newer Python versions."""

280

result = pytest.main(['--pylama', 'src/advanced_features.py'])

281

assert result == 0

282

```

283

284

### Integration with Coverage

285

286

```python

287

# pytest command combining pylama with coverage

288

import subprocess

289

290

result = subprocess.run([

291

'pytest',

292

'--pylama', # Code quality checks

293

'--cov=src', # Coverage reporting

294

'--cov-report=html', # HTML coverage report

295

'--cov-fail-under=80' # Minimum coverage threshold

296

])

297

```

298

299

### Custom Marker Usage

300

301

```python

302

import pytest

303

304

@pytest.mark.pycodestyle

305

def test_specific_style_check():

306

"""Test specifically marked for style checking."""

307

# This test will be collected when running with --pylama

308

pass

309

310

# Run only style-marked tests

311

# pytest -m pycodestyle --pylama

312

```

313

314

### Performance Optimization

315

316

```python

317

# pytest-xdist for parallel execution with pylama

318

import subprocess

319

320

# Run pylama checks in parallel

321

result = subprocess.run([

322

'pytest',

323

'--pylama',

324

'-n', 'auto', # Use all available CPU cores

325

'--dist=loadfile' # Distribute by file

326

])

327

```

328

329

### CI/CD Integration

330

331

```yaml

332

# GitHub Actions example

333

name: Code Quality

334

on: [push, pull_request]

335

336

jobs:

337

pylama:

338

runs-on: ubuntu-latest

339

steps:

340

- uses: actions/checkout@v2

341

- name: Set up Python

342

uses: actions/setup-python@v2

343

with:

344

python-version: 3.9

345

- name: Install dependencies

346

run: |

347

pip install pylama pytest

348

- name: Run code quality checks

349

run: pytest --pylama src/

350

```

351

352

### Custom Configuration with Pytest

353

354

```python

355

# conftest.py

356

import pytest

357

from pylama.config import parse_options

358

359

@pytest.fixture(scope="session")

360

def pylama_options():

361

"""Custom pylama configuration for tests."""

362

return parse_options([

363

'--linters=pycodestyle,pyflakes',

364

'--ignore=E501,W503',

365

'--max-line-length=100'

366

])

367

368

def test_with_custom_config(pylama_options):

369

"""Test using custom pylama configuration."""

370

from pylama.main import check_paths

371

372

errors = check_paths(['src/'], pylama_options)

373

assert len(errors) == 0, f"Code quality issues: {errors}"

374

```

375

376

## Caching System

377

378

The pytest integration includes an intelligent caching system:

379

380

```python { .api }

381

HISTKEY: str = "pylama/mtimes"

382

"""Cache key for storing file modification times."""

383

```

384

385

**Cache Behavior:**

386

- Files that pass pylama checks have their modification times cached

387

- On subsequent runs, unchanged files are skipped automatically

388

- Cache is persistent across pytest sessions

389

- Cache is invalidated when files are modified

390

- Improves performance significantly on large codebases

391

392

**Cache Location:**

393

- Uses pytest's built-in cache system (`.pytest_cache/`)

394

- Survives across different test runs and environments

395

- Can be cleared with `pytest --cache-clear`