or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-types.mddebug.mdfields.mdfiltering.mdforms.mdindex.mdrest-framework.mdtesting.mdviews.md

testing.mddocs/

0

# Testing Utilities

1

2

Test case classes and utility functions for GraphQL testing in Django applications with assertion helpers, query execution, and comprehensive testing patterns. Provides tools for unit testing GraphQL schemas, resolvers, and mutations.

3

4

## Capabilities

5

6

### GraphQLTestCase

7

8

Test case base class for GraphQL testing with built-in GraphQL execution and assertion helpers.

9

10

```python { .api }

11

class GraphQLTestCase(django.test.TestCase):

12

"""

13

Test case base class for GraphQL testing.

14

15

Provides utility methods for executing GraphQL queries and mutations

16

in Django test environment with assertion helpers and error handling.

17

"""

18

19

GRAPHQL_SCHEMA = None # GraphQL schema for testing

20

GRAPHQL_URL = '/graphql/' # GraphQL endpoint URL

21

22

def query(self, query, op_name=None, input_data=None, variables=None, headers=None):

23

"""

24

Execute GraphQL query in test environment.

25

26

Parameters:

27

- query: GraphQL query string

28

- op_name: Operation name for named queries

29

- input_data: Input data for mutations (deprecated, use variables)

30

- variables: Query variables

31

- headers: HTTP headers

32

33

Returns:

34

dict: GraphQL response data

35

"""

36

37

def assertResponseNoErrors(self, resp, msg=None):

38

"""

39

Assert GraphQL response has no errors.

40

41

Parameters:

42

- resp: GraphQL response

43

- msg: Custom assertion message

44

45

Raises:

46

AssertionError: If response contains errors

47

"""

48

49

def assertResponseHasErrors(self, resp, msg=None):

50

"""

51

Assert GraphQL response has errors.

52

53

Parameters:

54

- resp: GraphQL response

55

- msg: Custom assertion message

56

57

Raises:

58

AssertionError: If response contains no errors

59

"""

60

61

def setUp(self):

62

"""Set up test case with schema configuration."""

63

64

def _client_query(self, query, op_name=None, input_data=None, variables=None, headers=None):

65

"""

66

Internal method for client query execution.

67

68

Parameters:

69

- query: GraphQL query string

70

- op_name: Operation name

71

- input_data: Input data

72

- variables: Query variables

73

- headers: HTTP headers

74

75

Returns:

76

django.http.HttpResponse: HTTP response

77

"""

78

```

79

80

### Utility Functions

81

82

Helper functions for GraphQL query execution and testing patterns outside of test case classes.

83

84

```python { .api }

85

def graphql_query(query, variables=None, headers=None, client=None, graphql_url='/graphql/'):

86

"""

87

Utility function for making GraphQL requests in tests.

88

89

Parameters:

90

- query: GraphQL query string

91

- variables: Query variables dict

92

- headers: HTTP headers dict

93

- client: Django test client instance

94

- graphql_url: GraphQL endpoint URL

95

96

Returns:

97

django.http.HttpResponse: HTTP response with GraphQL result

98

"""

99

100

def format_graphql_query(query, variables=None, operation_name=None):

101

"""

102

Format GraphQL query with variables and operation name.

103

104

Parameters:

105

- query: GraphQL query string

106

- variables: Query variables

107

- operation_name: GraphQL operation name

108

109

Returns:

110

dict: Formatted query data for HTTP request

111

"""

112

113

def extract_graphql_errors(response):

114

"""

115

Extract GraphQL errors from response.

116

117

Parameters:

118

- response: HTTP response with GraphQL data

119

120

Returns:

121

list: List of GraphQL error objects

122

"""

123

```

124

125

## Usage Examples

126

127

### Basic Query Testing

128

129

```python

130

from graphene_django.utils.testing import GraphQLTestCase

131

from myapp.schema import schema

132

133

class UserQueryTest(GraphQLTestCase):

134

GRAPHQL_SCHEMA = schema

135

136

def setUp(self):

137

self.user = User.objects.create(

138

username='testuser',

139

email='test@example.com'

140

)

141

142

def test_users_query(self):

143

query = '''

144

query {

145

users {

146

id

147

username

148

email

149

}

150

}

151

'''

152

153

response = self.query(query)

154

self.assertResponseNoErrors(response)

155

156

users = response['data']['users']

157

self.assertEqual(len(users), 1)

158

self.assertEqual(users[0]['username'], 'testuser')

159

160

def test_user_by_id_query(self):

161

query = '''

162

query GetUser($id: ID!) {

163

user(id: $id) {

164

username

165

email

166

}

167

}

168

'''

169

170

variables = {'id': str(self.user.id)}

171

response = self.query(query, variables=variables)

172

self.assertResponseNoErrors(response)

173

174

user_data = response['data']['user']

175

self.assertEqual(user_data['username'], 'testuser')

176

self.assertEqual(user_data['email'], 'test@example.com')

177

```

178

179

### Mutation Testing

180

181

```python

182

class UserMutationTest(GraphQLTestCase):

183

GRAPHQL_SCHEMA = schema

184

185

def test_create_user_mutation(self):

186

mutation = '''

187

mutation CreateUser($input: CreateUserInput!) {

188

createUser(input: $input) {

189

user {

190

id

191

username

192

email

193

}

194

errors {

195

field

196

messages

197

}

198

}

199

}

200

'''

201

202

variables = {

203

'input': {

204

'username': 'newuser',

205

'email': 'new@example.com',

206

'password': 'securepassword123'

207

}

208

}

209

210

response = self.query(mutation, variables=variables)

211

self.assertResponseNoErrors(response)

212

213

result = response['data']['createUser']

214

self.assertEqual(len(result['errors']), 0)

215

self.assertEqual(result['user']['username'], 'newuser')

216

217

# Verify user was created in database

218

user = User.objects.get(username='newuser')

219

self.assertEqual(user.email, 'new@example.com')

220

221

def test_create_user_validation_error(self):

222

# Create existing user

223

User.objects.create(username='existing', email='existing@example.com')

224

225

mutation = '''

226

mutation CreateUser($input: CreateUserInput!) {

227

createUser(input: $input) {

228

user {

229

id

230

}

231

errors {

232

field

233

messages

234

}

235

}

236

}

237

'''

238

239

variables = {

240

'input': {

241

'username': 'existing', # This should cause validation error

242

'email': 'new@example.com'

243

}

244

}

245

246

response = self.query(mutation, variables=variables)

247

self.assertResponseNoErrors(response) # No GraphQL errors

248

249

result = response['data']['createUser']

250

self.assertIsNone(result['user'])

251

self.assertGreater(len(result['errors']), 0)

252

self.assertEqual(result['errors'][0]['field'], 'username')

253

```

254

255

### Authentication Testing

256

257

```python

258

from django.contrib.auth import get_user_model

259

from django.test import override_settings

260

261

User = get_user_model()

262

263

class AuthenticatedGraphQLTest(GraphQLTestCase):

264

GRAPHQL_SCHEMA = schema

265

266

def setUp(self):

267

self.user = User.objects.create_user(

268

username='testuser',

269

email='test@example.com',

270

password='testpass123'

271

)

272

273

def test_authenticated_query(self):

274

# Login user

275

self.client.force_login(self.user)

276

277

query = '''

278

query {

279

me {

280

id

281

username

282

email

283

}

284

}

285

'''

286

287

response = self.query(query)

288

self.assertResponseNoErrors(response)

289

290

me_data = response['data']['me']

291

self.assertEqual(me_data['username'], 'testuser')

292

293

def test_unauthenticated_query_error(self):

294

query = '''

295

query {

296

me {

297

id

298

username

299

}

300

}

301

'''

302

303

response = self.query(query)

304

self.assertResponseHasErrors(response)

305

306

errors = response['errors']

307

self.assertIn('authentication', errors[0]['message'].lower())

308

309

def test_permission_required_mutation(self):

310

# Create staff user

311

staff_user = User.objects.create_user(

312

username='staff',

313

email='staff@example.com',

314

password='staffpass',

315

is_staff=True

316

)

317

318

mutation = '''

319

mutation DeleteUser($id: ID!) {

320

deleteUser(id: $id) {

321

success

322

errors {

323

field

324

messages

325

}

326

}

327

}

328

'''

329

330

# Test without permission

331

self.client.force_login(self.user)

332

response = self.query(mutation, variables={'id': str(self.user.id)})

333

self.assertResponseHasErrors(response)

334

335

# Test with permission

336

self.client.force_login(staff_user)

337

response = self.query(mutation, variables={'id': str(self.user.id)})

338

self.assertResponseNoErrors(response)

339

```

340

341

### Connection/Pagination Testing

342

343

```python

344

class PaginationTest(GraphQLTestCase):

345

GRAPHQL_SCHEMA = schema

346

347

def setUp(self):

348

# Create multiple users for pagination testing

349

for i in range(10):

350

User.objects.create(

351

username=f'user{i}',

352

email=f'user{i}@example.com'

353

)

354

355

def test_connection_pagination(self):

356

query = '''

357

query GetUsers($first: Int, $after: String) {

358

users(first: $first, after: $after) {

359

edges {

360

node {

361

id

362

username

363

}

364

cursor

365

}

366

pageInfo {

367

hasNextPage

368

hasPreviousPage

369

startCursor

370

endCursor

371

}

372

}

373

}

374

'''

375

376

# First page

377

response = self.query(query, variables={'first': 3})

378

self.assertResponseNoErrors(response)

379

380

connection = response['data']['users']

381

self.assertEqual(len(connection['edges']), 3)

382

self.assertTrue(connection['pageInfo']['hasNextPage'])

383

self.assertFalse(connection['pageInfo']['hasPreviousPage'])

384

385

# Second page

386

end_cursor = connection['pageInfo']['endCursor']

387

response = self.query(query, variables={'first': 3, 'after': end_cursor})

388

self.assertResponseNoErrors(response)

389

390

connection = response['data']['users']

391

self.assertEqual(len(connection['edges']), 3)

392

self.assertTrue(connection['pageInfo']['hasPreviousPage'])

393

```

394

395

### Filtering Testing

396

397

```python

398

class FilteringTest(GraphQLTestCase):

399

GRAPHQL_SCHEMA = schema

400

401

def setUp(self):

402

self.active_user = User.objects.create(

403

username='active',

404

email='active@example.com',

405

is_active=True

406

)

407

self.inactive_user = User.objects.create(

408

username='inactive',

409

email='inactive@example.com',

410

is_active=False

411

)

412

413

def test_filter_by_active_status(self):

414

query = '''

415

query GetUsers($isActive: Boolean) {

416

users(isActive: $isActive) {

417

edges {

418

node {

419

username

420

isActive

421

}

422

}

423

}

424

}

425

'''

426

427

# Test active users

428

response = self.query(query, variables={'isActive': True})

429

self.assertResponseNoErrors(response)

430

431

users = response['data']['users']['edges']

432

self.assertEqual(len(users), 1)

433

self.assertEqual(users[0]['node']['username'], 'active')

434

435

# Test inactive users

436

response = self.query(query, variables={'isActive': False})

437

self.assertResponseNoErrors(response)

438

439

users = response['data']['users']['edges']

440

self.assertEqual(len(users), 1)

441

self.assertEqual(users[0]['node']['username'], 'inactive')

442

```

443

444

### Error Handling Testing

445

446

```python

447

class ErrorHandlingTest(GraphQLTestCase):

448

GRAPHQL_SCHEMA = schema

449

450

def test_invalid_query_syntax(self):

451

invalid_query = '''

452

query {

453

users {

454

id

455

nonexistentField

456

}

457

}

458

'''

459

460

response = self.query(invalid_query)

461

self.assertResponseHasErrors(response)

462

463

errors = response.get('errors', [])

464

self.assertGreater(len(errors), 0)

465

466

def test_resolver_exception(self):

467

query = '''

468

query {

469

userThatThrowsError {

470

id

471

}

472

}

473

'''

474

475

response = self.query(query)

476

self.assertResponseHasErrors(response)

477

478

errors = response.get('errors', [])

479

self.assertIn('error', errors[0]['message'].lower())

480

481

def test_custom_error_formatting(self):

482

# Override error formatting for sensitive information

483

with override_settings(DEBUG=False):

484

query = '''

485

query {

486

sensitiveOperation {

487

data

488

}

489

}

490

'''

491

492

response = self.query(query)

493

self.assertResponseHasErrors(response)

494

495

# In production, errors should be generic

496

errors = response.get('errors', [])

497

self.assertNotIn('database', errors[0]['message'].lower())

498

```

499

500

### Custom Headers and Context Testing

501

502

```python

503

class CustomContextTest(GraphQLTestCase):

504

GRAPHQL_SCHEMA = schema

505

506

def test_custom_headers(self):

507

query = '''

508

query {

509

requestInfo {

510

headers

511

userAgent

512

}

513

}

514

'''

515

516

headers = {

517

'HTTP_USER_AGENT': 'Test Client 1.0',

518

'HTTP_X_CUSTOM_HEADER': 'custom-value'

519

}

520

521

response = self.query(query, headers=headers)

522

self.assertResponseNoErrors(response)

523

524

request_info = response['data']['requestInfo']

525

self.assertEqual(request_info['userAgent'], 'Test Client 1.0')

526

527

def test_graphql_context(self):

528

self.client.force_login(self.user)

529

530

query = '''

531

query {

532

contextInfo {

533

userId

534

isAuthenticated

535

}

536

}

537

'''

538

539

response = self.query(query)

540

self.assertResponseNoErrors(response)

541

542

context_info = response['data']['contextInfo']

543

self.assertTrue(context_info['isAuthenticated'])

544

self.assertEqual(int(context_info['userId']), self.user.id)

545

```