or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-execution.mdexceptions.mdindex.mdplugin-system.mdpytest-integration.mdresponse-validation.md

pytest-integration.mddocs/

0

# Pytest Integration

1

2

Deep integration with pytest providing custom hooks, CLI options, automatic test file discovery, and seamless integration with pytest plugins and reporting systems.

3

4

## Capabilities

5

6

### Pytest Plugin Hooks

7

8

Core pytest plugin hooks that integrate Tavern into the pytest framework, enabling automatic test discovery and execution.

9

10

```python { .api }

11

def pytest_addhooks(pluginmanager):

12

"""

13

Register custom Tavern hooks with pytest.

14

15

Parameters:

16

- pluginmanager: Pytest plugin manager instance

17

"""

18

19

def pytest_addoption(parser):

20

"""

21

Add Tavern-specific command line options to pytest.

22

23

Parameters:

24

- parser: Pytest argument parser

25

"""

26

27

def pytest_collect_file(parent, path):

28

"""

29

Collect Tavern YAML test files during pytest discovery.

30

31

Parameters:

32

- parent: Parent pytest node

33

- path: File path being considered for collection

34

35

Returns:

36

TavernFile instance if file matches Tavern pattern, None otherwise

37

"""

38

```

39

40

### Parser Option Management

41

42

Programmatic interface for adding Tavern CLI options to pytest parsers.

43

44

```python { .api }

45

def add_parser_options(parser_addoption, with_defaults=True):

46

"""

47

Add Tavern CLI options to a parser programmatically.

48

49

Parameters:

50

- parser_addoption: Parser add_option function

51

- with_defaults: Whether to include default values

52

"""

53

```

54

55

### Custom Hook Execution

56

57

Interface for calling custom Tavern hooks during test execution.

58

59

```python { .api }

60

def call_hook(test_block_config, hookname, **kwargs):

61

"""

62

Call a custom Tavern hook during test execution.

63

64

Parameters:

65

- test_block_config: Test configuration object

66

- hookname: Name of hook to call

67

- **kwargs: Arguments to pass to hook

68

"""

69

```

70

71

## Custom Hooks

72

73

### Beta Hook Specifications

74

75

Custom hooks for extending Tavern test execution with user-defined functionality.

76

77

```python { .api }

78

def pytest_tavern_beta_before_every_test_run(

79

test_dict: dict,

80

variables: dict

81

) -> None:

82

"""

83

Hook called before each test execution.

84

85

Parameters:

86

- test_dict: Test definition dictionary

87

- variables: Current test variables

88

"""

89

90

def pytest_tavern_beta_after_every_test_run(

91

test_dict: dict,

92

variables: dict

93

) -> None:

94

"""

95

Hook called after each test execution.

96

97

Parameters:

98

- test_dict: Test definition dictionary

99

- variables: Updated test variables

100

"""

101

102

def pytest_tavern_beta_after_every_response(

103

expected: Any,

104

response: Any

105

) -> None:

106

"""

107

Hook called after each response is received.

108

109

Parameters:

110

- expected: Expected response specification

111

- response: Actual response object

112

"""

113

114

def pytest_tavern_beta_before_every_request(

115

request_args: MutableMapping

116

) -> None:

117

"""

118

Hook called before each request is sent.

119

120

Parameters:

121

- request_args: Mutable request arguments dictionary

122

"""

123

```

124

125

## CLI Options

126

127

### Tavern-Specific Options

128

129

Command line options added to pytest for controlling Tavern behavior.

130

131

**Core Configuration:**

132

- `--tavern-global-cfg`: Path to global configuration file

133

- `--tavern-strict`: Response matching strictness level

134

- `--tavern-file-path-regex`: Regex pattern for test files (default: `r".+\.tavern\.ya?ml$"`)

135

136

**Backend Selection:**

137

- `--tavern-http-backend`: HTTP backend plugin name (default: "requests")

138

- `--tavern-mqtt-backend`: MQTT backend plugin name (default: "paho-mqtt")

139

- `--tavern-grpc-backend`: gRPC backend plugin name (default: "grpc")

140

141

**Debugging Options:**

142

- `--tavern-use-default-traceback`: Use Python-style tracebacks

143

- `--tavern-setup-init-logging`: Setup simple logger for initialization

144

145

**HTTP-Specific:**

146

- `--tavern-always-follow-redirects`: Always follow HTTP redirects

147

148

## Usage Examples

149

150

### Basic Pytest Integration

151

152

```bash

153

# Run Tavern tests with pytest

154

pytest tests/ -v

155

156

# Run specific Tavern test file

157

pytest test_api.tavern.yaml -v

158

159

# Run with Tavern-specific options

160

pytest tests/ --tavern-global-cfg config.yaml --tavern-strict

161

```

162

163

### Custom Hook Implementation

164

165

```python

166

# conftest.py

167

def pytest_tavern_beta_before_every_test_run(test_dict, variables):

168

"""Add custom setup before each test."""

169

print(f"Running test: {test_dict.get('test_name', 'Unknown')}")

170

171

# Add dynamic variables

172

variables['timestamp'] = str(int(time.time()))

173

variables['test_id'] = str(uuid.uuid4())

174

175

def pytest_tavern_beta_after_every_response(expected, response):

176

"""Log response details."""

177

if hasattr(response, 'status_code'):

178

print(f"Response status: {response.status_code}")

179

180

def pytest_tavern_beta_before_every_request(request_args):

181

"""Modify requests before sending."""

182

# Add common headers

183

if 'headers' not in request_args:

184

request_args['headers'] = {}

185

request_args['headers']['X-Test-Run'] = 'true'

186

```

187

188

### Programmatic Parser Configuration

189

190

```python

191

import argparse

192

from tavern._core.pytest import add_parser_options

193

194

# Create custom parser with Tavern options

195

parser = argparse.ArgumentParser()

196

add_parser_options(parser.add_argument, with_defaults=True)

197

198

# Parse arguments

199

args = parser.parse_args([

200

'--tavern-global-cfg', 'config.yaml',

201

'--tavern-strict',

202

'--tavern-http-backend', 'custom_requests'

203

])

204

```

205

206

### File Discovery and Collection

207

208

```python

209

# Custom pytest plugin using Tavern collection

210

class CustomTavernPlugin:

211

def pytest_collect_file(self, parent, path):

212

"""Collect custom Tavern files."""

213

if path.ext == ".yaml" and "api_test" in path.basename:

214

# Use Tavern's collection logic

215

from tavern._core.pytest import pytest_collect_file

216

return pytest_collect_file(parent, path)

217

```

218

219

### Configuration Integration

220

221

```yaml

222

# pytest.ini

223

[tool:pytest]

224

addopts =

225

--tavern-global-cfg=tests/global_config.yaml

226

--tavern-strict

227

--tavern-http-backend=requests

228

-v

229

230

testpaths = tests/

231

python_files = *.tavern.yaml

232

```

233

234

### Advanced Hook Usage

235

236

```python

237

# Plugin with comprehensive hook usage

238

class TavernTestPlugin:

239

def __init__(self):

240

self.test_results = []

241

self.start_time = None

242

243

def pytest_tavern_beta_before_every_test_run(self, test_dict, variables):

244

self.start_time = time.time()

245

246

# Set up test-specific configuration

247

test_name = test_dict.get('test_name', 'unknown')

248

variables['test_start_time'] = self.start_time

249

variables['test_environment'] = os.getenv('TEST_ENV', 'local')

250

251

print(f"Starting test: {test_name}")

252

253

def pytest_tavern_beta_after_every_test_run(self, test_dict, variables):

254

duration = time.time() - self.start_time

255

test_name = test_dict.get('test_name', 'unknown')

256

257

self.test_results.append({

258

'name': test_name,

259

'duration': duration,

260

'variables_used': list(variables.keys())

261

})

262

263

print(f"Completed test: {test_name} in {duration:.2f}s")

264

265

def pytest_tavern_beta_before_every_request(self, request_args):

266

# Add request tracing

267

if 'headers' not in request_args:

268

request_args['headers'] = {}

269

request_args['headers']['X-Trace-ID'] = str(uuid.uuid4())

270

271

# Log outgoing requests

272

method = request_args.get('method', 'GET')

273

url = request_args.get('url', 'unknown')

274

print(f"Sending {method} request to {url}")

275

276

def pytest_tavern_beta_after_every_response(self, expected, response):

277

# Validate response timing

278

if hasattr(response, 'elapsed'):

279

if response.elapsed.total_seconds() > 5.0:

280

print(f"WARNING: Slow response ({response.elapsed.total_seconds():.2f}s)")

281

282

# Log response status

283

if hasattr(response, 'status_code'):

284

print(f"Received response: {response.status_code}")

285

```

286

287

## Integration with Pytest Ecosystem

288

289

### Pytest Plugin Compatibility

290

291

```python

292

# Works with pytest-xdist for parallel execution

293

pytest tests/ -n auto --tavern-global-cfg config.yaml

294

295

# Works with pytest-cov for coverage

296

pytest tests/ --cov=myapp --tavern-strict

297

298

# Works with pytest-html for HTML reports

299

pytest tests/ --html=report.html --self-contained-html

300

```

301

302

### Custom Test Item Classes

303

304

```python { .api }

305

# Internal classes used by pytest integration

306

class TavernFile:

307

"""Represents a Tavern YAML test file in pytest collection."""

308

309

class TavernItem:

310

"""Represents an individual Tavern test case in pytest."""

311

```

312

313

## Types

314

315

```python { .api }

316

from typing import Any, MutableMapping

317

from _pytest.config import Config

318

from _pytest.nodes import File, Item

319

320

TestConfig = "tavern._core.pytest.config.TestConfig"

321

```