API Testing
TestFlowKit provides comprehensive backend testing capabilities for REST APIs and GraphQL endpoints.
REST API Testing
Configuration
Configure your REST API in the apis section of config.yml:
apis:
default_timeout: 10000 # Default timeout for all APIs in milliseconds
definitions:
my_api: # API name - use this to reference the API in tests
type: rest
base_url: "https://api.example.com"
default_headers:
Content-Type: "application/json"
Accept: "application/json"
endpoints:
get_users:
method: GET
path: "/users"
get_user:
method: GET
path: "/users/{id}"
create_user:
method: POST
path: "/users"
update_user:
method: PUT
path: "/users/{id}"
delete_user:
method: DELETE
path: "/users/{id}"
You can define multiple REST APIs in the same configuration:
apis:
definitions:
users_api:
type: rest
base_url: "https://api.example.com"
endpoints:
get_users:
method: GET
path: "/users"
products_api:
type: rest
base_url: "https://products.example.com"
endpoints:
get_products:
method: GET
path: "/products"
Basic Requests
GET Request
Scenario: Fetch user list
Given I prepare a request to "my_api.get_users"
When I send the request
Then the response status code should be 200
And the response should contain "users"
Note: The syntax is "api_name.endpoint_name" where:
api_namematches the key in yourapis.definitionssectionendpoint_namematches the endpoint key within that API
POST Request
Scenario: Create new user
Given I prepare a request to "my_api.create_user"
And I set the request body to:
"""
{
"name": "John Doe",
"email": "john@example.com"
}
"""
When I send the request
Then the response status code should be 201
And the response JSON path "data.name" should be "John Doe"
PUT Request
Scenario: Update user
Given I prepare a request to "my_api.update_user"
And I set the following path parameters:
| id | 123 |
And I set the request body to:
"""
{
"name": "Jane Doe"
}
"""
When I send the request
Then the response status code should be 200
DELETE Request
Scenario: Delete user
Given I prepare a request to "my_api.delete_user"
And I set the following path parameters:
| id | 123 |
When I send the request
Then the response status code should be 204
Path Parameters
# Single parameter
Given I prepare a request to "my_api.get_user"
And I set the following path parameters:
| id | 456 |
When I send the request
# Multiple parameters
Given I prepare a request to "my_api.get_comment"
And I set the following path parameters:
| postId | 123 |
| commentId | 789 |
When I send the request
Query Parameters
Given I prepare a request to "my_api.get_users"
And I set the following query parameters:
| page | 1 |
| limit | 10 |
| status | active |
| sort | name |
When I send the request
Request Headers
# Set individual header
Given I prepare a request to "my_api.protected_endpoint"
And I set the request header "Authorization" to "Bearer {{auth_token}}"
When I send the request
# Set multiple headers
Given I prepare a request to "my_api.api_endpoint"
And I set the following request headers:
| Authorization | Bearer {{token}} |
| X-API-Key | my-api-key |
| Accept-Language | en-US |
When I send the request
Note: Headers set in the step will be merged with default_headers from the API configuration.
Request Body
JSON Body
Given I prepare a request to "my_api.create_product"
And I set the request body to:
"""
{
"name": "Product Name",
"price": 99.99,
"category": "Electronics",
"inStock": true,
"tags": ["new", "featured"]
}
"""
When I send the request
Form Data
Given I prepare a request to "my_api.submit_form"
And I set the form data to:
| name | John Doe |
| email | john@example.com |
| file | @/path/to/file.pdf |
When I send the request
Response Assertions
Status Code
Then the response status code should be 200
Then the response status code should be 201
Then the response status code should be 404
Then the response status code should be 500
Response Body
# Contains text
Then the response should contain "success"
# JSON path assertions
Then the response JSON path "data.id" should be "123"
Then the response JSON path "data.name" should be "John Doe"
Then the response JSON path "data.active" should be "true"
Then the response JSON path "data.items.length" should be "5"
# JSON path existence
Then the response JSON path "data.email" should exist
Then the response JSON path "data.password" should not exist
Response Headers
Then the response header "Content-Type" should be "application/json"
Then the response header "X-Request-Id" should exist
Response Time
Then the response time should be less than 1000 milliseconds
Then the response time should be less than 2 seconds
Extracting Data
Store response data in variables for later use:
# Extract from JSON path
When I send the request
And I store the JSON path "data.id" from the response into "user_id" variable
And I store the JSON path "data.token" from the response into "auth_token" variable
# Use extracted data
Given I prepare a request to "my_api.get_user"
And I set the following path parameters:
| id | {{user_id}} |
And I set the request header "Authorization" to "Bearer {{auth_token}}"
GraphQL Testing
Configuration
Configure your GraphQL API in the apis section of config.yml:
apis:
definitions:
my_graphql_api: # API name - use this to reference the API in tests
type: graphql
endpoint: "https://api.example.com/graphql"
default_headers:
Content-Type: "application/json"
operations:
get_user:
type: query
operation: "graphql/queries/get_user.graphql"
create_post:
type: mutation
operation: "graphql/mutations/create_post.graphql"
You can define both REST and GraphQL APIs together:
apis:
definitions:
rest_api:
type: rest
base_url: "https://api.example.com"
endpoints:
get_users:
method: GET
path: "/users"
graphql_api:
type: graphql
endpoint: "https://api.example.com/graphql"
operations:
get_user: "graphql/queries/get_user.graphql"
Query Files
Create .graphql files for your operations:
# graphql/queries/get_user.graphql
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
id
title
}
}
}
# graphql/mutations/create_post.graphql
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
content
author {
name
}
}
}
Executing Queries
Scenario: Fetch user data
Given I prepare a request to "my_graphql_api.get_user"
And I set the GraphQL variables to:
"""
{
"id": "123"
}
"""
When I send the GraphQL request
Then the response status code should be 200
And the response JSON path "data.user.name" should be "John Doe"
Note: The same unified syntax works for both REST and GraphQL - TestFlowKit automatically detects the API type from your configuration.
Executing Mutations
Scenario: Create a new post
Given I prepare a request to "my_graphql_api.create_post"
And I set the GraphQL variables to:
"""
{
"input": {
"title": "My New Post",
"content": "This is the content"
}
}
"""
When I send the GraphQL request
Then the response status code should be 200
And the response JSON path "data.createPost.id" should exist
And I store the JSON path "data.createPost.id" from the response into "post_id" variable
Authentication Patterns
Bearer Token
Background:
Given I prepare a request to "my_api.login"
And I set the request body to:
"""
{
"email": "user@example.com",
"password": "password123"
}
"""
When I send the request
And I store the JSON path "token" from the response into "auth_token" variable
Scenario: Access protected resource
Given I prepare a request to "my_api.protected_data"
And I set the request header "Authorization" to "Bearer {{auth_token}}"
When I send the request
Then the response status code should be 200
API Key
Scenario: Request with API key
Given I prepare a request to "external_api.some_endpoint"
And I set the request header "X-API-Key" to "{{api_key}}"
When I send the request
Then the response status code should be 200
Setting Default Headers
You can configure default headers (like authorization) in your API definition:
apis:
definitions:
protected_api:
type: rest
base_url: "https://api.example.com"
default_headers:
Authorization: "Bearer {{api_token}}"
X-API-Key: "{{api_key}}"
endpoints:
get_data:
method: GET
path: "/data"
These headers will be automatically included in all requests to this API.
Best Practices
1. Use Descriptive API and Endpoint Names
# Good
apis:
definitions:
user_management_api:
type: rest
base_url: "https://api.example.com"
endpoints:
create_user_account:
method: POST
path: "/users"
# Bad
apis:
definitions:
api1:
type: rest
base_url: "https://api.example.com"
endpoints:
post1:
method: POST
path: "/users"
2. Validate Response Structure
# Verify all important fields
Then the response status code should be 200
And the response JSON path "data.id" should exist
And the response JSON path "data.name" should be "Expected Name"
And the response JSON path "data.email" should exist
3. Chain API Calls Appropriately
Scenario: Full CRUD workflow
# Create
Given I prepare a request to "my_api.create_item"
And I set the request body to:
"""
{"name": "Test Item"}
"""
When I send the request
And I store the JSON path "data.id" from the response into "item_id" variable
Then the response status code should be 201
# Read
Given I prepare a request to "my_api.get_item"
And I set the following path parameters:
| id | {{item_id}} |
When I send the request
Then the response status code should be 200
# Update
Given I prepare a request to "my_api.update_item"
And I set the following path parameters:
| id | {{item_id}} |
And I set the request body to:
"""
{"name": "Updated Item"}
"""
When I send the request
Then the response status code should be 200
# Delete
Given I prepare a request to "my_api.delete_item"
And I set the following path parameters:
| id | {{item_id}} |
When I send the request
Then the response status code should be 204
Next Steps
- Variables — Store and reuse API response data
- Macros — Create reusable API test patterns
- Step Definitions — All API-related steps