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

response-validation.mddocs/

0

# Response Validation

1

2

Comprehensive validation functions for API responses including JWT validation, regex matching, schema validation, and content assertions using JMESPath expressions.

3

4

## Capabilities

5

6

### JWT Token Validation

7

8

Validates and decodes JWT tokens from API responses using the PyJWT library, returning decoded claims for use in subsequent test stages.

9

10

```python { .api }

11

def validate_jwt(

12

response: requests.Response,

13

jwt_key: str,

14

**kwargs

15

) -> Mapping[str, Box]:

16

"""

17

Validate and decode JWT token from response.

18

19

Parameters:

20

- response: HTTP response object containing JWT

21

- jwt_key: Key name in response JSON containing the JWT token

22

- **kwargs: Additional arguments passed to jwt.decode() (e.g., verify_signature=False)

23

24

Returns:

25

Mapping[str, Box]: Dictionary with 'jwt' key containing boxed JWT claims

26

27

Usage:

28

Can be used both for validation and to extract JWT claims for template variables

29

"""

30

```

31

32

**Usage Examples:**

33

34

```python

35

import requests

36

from tavern.helpers import validate_jwt

37

38

# Basic JWT validation

39

response = requests.get("https://api.example.com/auth")

40

jwt_data = validate_jwt(response, "access_token", verify_signature=False)

41

print(jwt_data["jwt"]["user_id"]) # Access decoded claims

42

43

# In YAML test with validation

44

# response:

45

# status_code: 200

46

# json:

47

# access_token: !anything

48

# validate:

49

# - function: tavern.helpers:validate_jwt

50

# extra_kwargs:

51

# jwt_key: access_token

52

# verify_signature: false

53

# save:

54

# json:

55

# token_claims: !jwt_claims access_token

56

```

57

58

### Regex Pattern Validation

59

60

Validates response content against regular expressions with support for header matching and JMESPath content extraction.

61

62

```python { .api }

63

def validate_regex(

64

response: requests.Response,

65

expression: str,

66

*,

67

header: Optional[str] = None,

68

in_jmespath: Optional[str] = None,

69

) -> dict[str, Box]:

70

"""

71

Validate response content against regex pattern.

72

73

Parameters:

74

- response: HTTP response object

75

- expression: Regular expression pattern to match

76

- header: Optional header name to match against instead of body

77

- in_jmespath: Optional JMESPath to extract content before regex matching

78

79

Returns:

80

dict[str, Box]: Dictionary with 'regex' key containing boxed capture groups

81

82

Raises:

83

BadSchemaError: If both header and in_jmespath are specified

84

RegexAccessError: If regex doesn't match or JMESPath extraction fails

85

"""

86

```

87

88

**Usage Examples:**

89

90

```python

91

from tavern.helpers import validate_regex

92

93

# Match against response body

94

result = validate_regex(response, r"User ID: (\d+)")

95

user_id = result["regex"]["1"] # First capture group

96

97

# Match against specific header

98

result = validate_regex(

99

response,

100

r"Bearer ([a-zA-Z0-9]+)",

101

header="Authorization"

102

)

103

token = result["regex"]["1"]

104

105

# Match against JMESPath extracted content

106

result = validate_regex(

107

response,

108

r"Error: (.+)",

109

in_jmespath="error.message"

110

)

111

error_msg = result["regex"]["1"]

112

113

# In YAML test

114

# response:

115

# status_code: 200

116

# validate:

117

# - function: tavern.helpers:validate_regex

118

# extra_kwargs:

119

# expression: "Order #([0-9]+) created"

120

# save:

121

# regex:

122

# order_id: "1" # First capture group

123

```

124

125

### Content Validation with JMESPath

126

127

Validates response content using JMESPath expressions with various comparison operators for complex assertions.

128

129

```python { .api }

130

def validate_content(

131

response: requests.Response,

132

comparisons: Iterable[dict]

133

) -> None:

134

"""

135

Validate response content using JMESPath expressions and operators.

136

137

Parameters:

138

- response: HTTP response object with JSON content

139

- comparisons: List of comparison dictionaries with keys:

140

- jmespath: JMESPath expression to extract data

141

- operator: Comparison operator (eq, ne, gt, lt, gte, lte, in, contains)

142

- expected: Expected value to compare against

143

144

Raises:

145

JMESError: If validation fails or JMESPath expression is invalid

146

"""

147

```

148

149

**Usage Examples:**

150

151

```python

152

from tavern.helpers import validate_content

153

154

# Single comparison

155

comparisons = [{

156

"jmespath": "users.length(@)",

157

"operator": "gt",

158

"expected": 0

159

}]

160

validate_content(response, comparisons)

161

162

# Multiple comparisons

163

comparisons = [

164

{

165

"jmespath": "status",

166

"operator": "eq",

167

"expected": "success"

168

},

169

{

170

"jmespath": "data.users[0].age",

171

"operator": "gte",

172

"expected": 18

173

},

174

{

175

"jmespath": "data.users[].name",

176

"operator": "contains",

177

"expected": "John"

178

}

179

]

180

validate_content(response, comparisons)

181

```

182

183

### JMESPath Query Matching

184

185

Executes JMESPath queries against parsed response data with optional value validation.

186

187

```python { .api }

188

def check_jmespath_match(

189

parsed_response,

190

query: str,

191

expected: Optional[str] = None

192

):

193

"""

194

Check JMESPath query against response data.

195

196

Parameters:

197

- parsed_response: Parsed response data (dict or list)

198

- query: JMESPath query expression

199

- expected: Optional expected value to match against query result

200

201

Returns:

202

Query result value

203

204

Raises:

205

JMESError: If query path not found or doesn't match expected value

206

"""

207

```

208

209

**Usage Examples:**

210

211

```python

212

from tavern.helpers import check_jmespath_match

213

214

# Check if path exists and return value

215

data = {"users": [{"name": "John", "age": 30}]}

216

result = check_jmespath_match(data, "users[0].name")

217

print(result) # "John"

218

219

# Check path exists with expected value

220

check_jmespath_match(data, "users[0].age", 30) # Passes

221

check_jmespath_match(data, "users.length(@)", 1) # Passes

222

223

# Check complex queries

224

check_jmespath_match(

225

data,

226

"users[?age > `25`].name",

227

["John"]

228

)

229

```

230

231

### Schema Validation

232

233

Validates response JSON against Pykwalify schemas for structural and type validation.

234

235

```python { .api }

236

def validate_pykwalify(

237

response: requests.Response,

238

schema: dict

239

) -> None:

240

"""

241

Validate response JSON against Pykwalify schema.

242

243

Parameters:

244

- response: HTTP response object with JSON content

245

- schema: Pykwalify schema dictionary

246

247

Raises:

248

BadSchemaError: If response is not JSON or doesn't match schema

249

"""

250

```

251

252

**Usage Examples:**

253

254

```python

255

from tavern.helpers import validate_pykwalify

256

257

# Define schema

258

schema = {

259

"type": "map",

260

"mapping": {

261

"status": {"type": "str", "required": True},

262

"data": {

263

"type": "map",

264

"mapping": {

265

"users": {

266

"type": "seq",

267

"sequence": [{

268

"type": "map",

269

"mapping": {

270

"id": {"type": "int"},

271

"name": {"type": "str"},

272

"email": {"type": "str", "pattern": r".+@.+\..+"}

273

}

274

}]

275

}

276

}

277

}

278

}

279

}

280

281

# Validate response

282

validate_pykwalify(response, schema)

283

```

284

285

### Exception Validation

286

287

Validates that API error responses match expected exception formats and status codes.

288

289

```python { .api }

290

def check_exception_raised(

291

response: requests.Response,

292

exception_location: str

293

) -> None:

294

"""

295

Validate response matches expected exception format.

296

297

Parameters:

298

- response: HTTP response object containing error

299

- exception_location: Entry point style location of exception class

300

(e.g., "myapp.exceptions:ValidationError")

301

302

Raises:

303

UnexpectedExceptionError: If response doesn't match expected exception format

304

"""

305

```

306

307

**Usage Examples:**

308

309

```python

310

from tavern.helpers import check_exception_raised

311

312

# Validate error response format

313

try:

314

response = requests.post("https://api.example.com/invalid")

315

check_exception_raised(response, "myapp.exceptions:ValidationError")

316

except UnexpectedExceptionError:

317

print("Error response format doesn't match expected exception")

318

319

# In YAML test

320

# response:

321

# status_code: 400

322

# validate:

323

# - function: tavern.helpers:check_exception_raised

324

# extra_kwargs:

325

# exception_location: "myapp.exceptions:ValidationError"

326

```

327

328

## YAML Integration Examples

329

330

### Using Validation Functions in Tests

331

332

```yaml

333

test_name: Comprehensive validation example

334

335

stages:

336

- name: Test with multiple validations

337

request:

338

url: https://api.example.com/data

339

method: GET

340

response:

341

status_code: 200

342

validate:

343

# JWT validation

344

- function: tavern.helpers:validate_jwt

345

extra_kwargs:

346

jwt_key: access_token

347

verify_signature: false

348

349

# Regex validation

350

- function: tavern.helpers:validate_regex

351

extra_kwargs:

352

expression: "Request ID: ([A-Z0-9-]+)"

353

header: "X-Request-ID"

354

355

# Content validation

356

- function: tavern.helpers:validate_content

357

extra_kwargs:

358

comparisons:

359

- jmespath: "data.items.length(@)"

360

operator: "gt"

361

expected: 0

362

- jmespath: "status"

363

operator: "eq"

364

expected: "success"

365

366

# Schema validation

367

- function: tavern.helpers:validate_pykwalify

368

extra_kwargs:

369

schema:

370

type: map

371

mapping:

372

status: {type: str}

373

data: {type: map}

374

375

save:

376

jwt:

377

user_id: user_id

378

regex:

379

request_id: "1"

380

```

381

382

## Types

383

384

```python { .api }

385

from typing import Optional, Mapping, Iterable

386

import requests

387

from box.box import Box

388

389

BadSchemaError = "tavern._core.exceptions.BadSchemaError"

390

RegexAccessError = "tavern._core.exceptions.RegexAccessError"

391

JMESError = "tavern._core.exceptions.JMESError"

392

UnexpectedExceptionError = "tavern._core.exceptions.UnexpectedExceptionError"

393

```