API manual testing is a critical aspect of software development, ensuring that APIs function correctly, securely, and efficiently. This process involves verifying that the API meets its specifications and performs as expected under various conditions. Manual testing of APIs can uncover issues that automated tests might miss, such as usability problems and unexpected edge cases.
This article provides a curated selection of questions and answers to help you prepare for interviews focused on API manual testing. By familiarizing yourself with these topics, you will be better equipped to demonstrate your understanding of API testing principles, methodologies, and best practices, thereby enhancing your readiness for technical discussions.
API Manual Testing Interview Questions and Answers
1. Explain the purpose of different HTTP methods (GET, POST, PUT, DELETE) and when you would use each.
HTTP methods are used to perform operations on resources in a RESTful API. The primary methods include GET, POST, PUT, and DELETE, each serving a distinct purpose.
- GET: Retrieves data from a server at the specified resource without altering its state, such as fetching user details.
- POST: Sends data to the server to create a new resource, like submitting form data or uploading a file.
- PUT: Updates an existing resource or creates a new one if it doesn’t exist. It is idempotent, meaning multiple identical requests have the same effect as a single request.
- DELETE: Removes a specified resource from the server, such as deleting a user account.
2. How do headers play a role in API requests and responses? Provide examples of commonly used headers.
Headers in API requests and responses are key-value pairs that provide essential information about the communication between the client and server. They specify content type, handle authentication, manage caching, and more.
Commonly used headers include:
- Content-Type: Specifies the media type of the resource, e.g., application/json for JSON data.
- Authorization: Contains credentials for authenticating the client with the server, e.g., Bearer tokens.
- Accept: Informs the server about the types of data the client can process, e.g., Accept: application/json.
- Cache-Control: Directs caching mechanisms, e.g., Cache-Control: no-cache.
- User-Agent: Provides information about the client software making the request.
Example of setting headers in a Python request:
import requests
url = 'https://api.example.com/data'
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_token_here',
'Accept': 'application/json'
}
response = requests.get(url, headers=headers)
print(response.json())
3. What are some common authentication mechanisms used in APIs, and how do they work?
Common authentication mechanisms in APIs include:
- Basic Authentication: Sends the username and password encoded in Base64 with each request. It is simple but not very secure unless used over HTTPS.
- Token-Based Authentication: Generates a token after login, which is sent with each request, usually in the HTTP headers. Examples include OAuth and JWT.
- OAuth: An open standard for access delegation, allowing third-party services to exchange tokens instead of credentials.
- API Keys: Unique identifiers passed with each request to identify the calling project or application.
- HMAC: Creates a hash of the request data using a secret key, sent along with the request for verification.
4. Differentiate between query parameters and path parameters with examples.
Query parameters and path parameters are used to pass information to an API endpoint.
Query Parameters:
- Appended to the end of the URL to filter or sort resources.
- Specified after a question mark (?) and separated by an ampersand (&).
- Typically used for optional parameters.
Example:
GET /users?age=25&country=USA
Path Parameters:
- Part of the URL path to identify specific resources.
- Embedded directly in the URL and typically used for required parameters.
- Specified within curly braces {} in the URL template.
Example:
GET /users/{userId}
5. Write a test case for an API endpoint that retrieves user details based on user ID.
To write a test case for an API endpoint that retrieves user details based on user ID, consider:
- Endpoint URL and Method: Identify the endpoint URL and HTTP method used.
- Request Parameters: Specify required parameters, such as the user ID.
- Headers: Include necessary headers, like authentication tokens.
- Expected Response: Define expected response, including status codes and response body structure.
- Validation: Outline validation steps to ensure the response is correct.
Example:
import requests
def test_get_user_details(user_id):
url = f"https://api.example.com/users/{user_id}"
headers = {
"Authorization": "Bearer your_token_here",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
# Validate status code
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
# Validate response body
user_details = response.json()
assert "id" in user_details, "User ID not in response"
assert user_details["id"] == user_id, f"Expected user ID {user_id}, got {user_details['id']}"
assert "name" in user_details, "User name not in response"
assert "email" in user_details, "User email not in response"
# Example usage
test_get_user_details(123)
6. How would you handle testing an asynchronous API that returns data after a delay?
To handle testing an asynchronous API that returns data after a delay, use techniques like polling, callbacks, or asynchronous test frameworks. Polling involves repeatedly checking the API response at intervals until the data is available.
Example using polling:
import time
import requests
def test_async_api(url):
max_retries = 5
delay = 2 # seconds
for _ in range(max_retries):
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if data: # Check if data is available
return data
time.sleep(delay)
raise TimeoutError("API did not return data within the expected time frame")
# Example usage
url = "https://example.com/async-api"
try:
result = test_async_api(url)
print("Data received:", result)
except TimeoutError as e:
print(e)
7. What techniques do you use for performance testing of APIs?
Performance testing of APIs involves techniques to ensure the API can handle the expected load and perform well under various conditions:
- Load Testing: Simulates a high number of concurrent users or requests to determine performance under normal and peak load conditions.
- Stress Testing: Pushes the API beyond its normal capacity to see how it behaves under extreme conditions.
- Spike Testing: Involves suddenly increasing the load to observe how it handles sudden spikes in traffic.
- Endurance Testing: Runs the API under a significant load for an extended period to identify potential memory or resource leaks.
- Tools: Tools like JMeter, Postman, and Gatling can be used for performance testing.
- Monitoring Metrics: Key metrics include response time, throughput, error rates, and resource utilization.
8. Describe common security vulnerabilities in APIs and how you would test for them.
Common security vulnerabilities in APIs include:
- SQL Injection: Occurs when an attacker executes arbitrary SQL code on a database by manipulating input fields.
- Cross-Site Scripting (XSS): Allows attackers to inject malicious scripts into web pages viewed by other users.
- Broken Authentication: Happens when authentication mechanisms are improperly implemented, allowing unauthorized access.
- Insecure Direct Object References (IDOR): Occurs when an API exposes internal implementation objects.
- Rate Limiting: Lack of rate limiting can allow brute force or Denial of Service (DoS) attacks.
9. How do you manage API versioning, and why is it important?
API versioning is essential for maintaining backward compatibility and ensuring changes do not disrupt existing clients. It allows developers to introduce new features, fix bugs, and improve performance without breaking existing functionality.
Methods to manage API versioning:
- URI Versioning: Includes the version number in the URL path, e.g.,
/api/v1/resource
.
- Query Parameters: Specifies the version number as a query parameter, e.g.,
/api/resource?version=1
.
- Header Versioning: Includes the version number in the HTTP headers, e.g.,
API-Version: 1
.
- Content Negotiation: Specifies the version in the request’s Accept header, e.g.,
Accept: application/vnd.example.v1+json
.
10. How would you handle rate limits programmatically when making multiple API requests?
To handle rate limits programmatically, implement a mechanism to monitor rate limit headers returned by the API and pause or throttle requests when the limit is reached.
Example:
import time
import requests
def make_request_with_rate_limit(url, headers):
response = requests.get(url, headers=headers)
if response.status_code == 429: # Too Many Requests
retry_after = int(response.headers.get("Retry-After", 1))
time.sleep(retry_after)
return make_request_with_rate_limit(url, headers)
return response
url = "https://api.example.com/data"
headers = {"Authorization": "Bearer YOUR_ACCESS_TOKEN"}
for _ in range(100): # Example loop to make multiple requests
response = make_request_with_rate_limit(url, headers)
print(response.json())
11. How do you ensure data integrity when testing APIs?
Ensuring data integrity when testing APIs involves:
- Validation of Input and Output Data: Ensure the API correctly handles and validates input data, checking for correct data types, required fields, and data formats.
- Consistency Checks: Perform checks to ensure data remains consistent across different parts of the system.
- Use of Automated Testing Tools: Utilize tools like Postman, SoapUI, and JMeter to automate testing.
- Database Verification: Verify that data stored in the database matches expected results after API operations.
- Error Handling and Edge Cases: Test the API’s error handling capabilities by providing invalid or unexpected input.
- Concurrency Testing: Test the API under concurrent access scenarios to ensure data integrity is maintained.
12. How do you test for idempotency in API methods like PUT and DELETE?
Idempotency in API methods means that making multiple identical requests should have the same effect as making a single request. This is important for methods like PUT and DELETE to ensure repeated requests do not cause unintended side effects.
To test for idempotency:
1. Initial Request: Make an initial request and record the response.
2. Subsequent Requests: Make additional identical requests.
3. Compare Responses: Verify that responses from subsequent requests are the same as the initial request.
4. Check Resource State: Ensure the state of the resource remains unchanged after repeated requests.
For example, if testing a PUT method:
- Send a PUT request to update a resource.
- Send the same PUT request again.
- Verify that the response and resource state are the same after both requests.
Similarly, for a DELETE method:
- Send a DELETE request to remove a resource.
- Send the same DELETE request again.
- Verify that the response indicates the resource is already deleted and that it does not exist.
13. How do you validate that API documentation is accurate and up-to-date?
Validating that API documentation is accurate and up-to-date involves:
- Compare Documentation with Actual API Responses: Regularly test endpoints and compare responses with documented examples.
- Automated Tools: Use tools like Swagger, Postman, or Dredd to validate documentation.
- Version Control: Use systems like Git to manage changes in the API and its documentation.
- Stakeholder Involvement: Involve developers, QA engineers, and end-users in the review process.
- Regular Audits: Schedule regular audits of the documentation to ensure it remains accurate.
14. Explain the concept of rate limiting in APIs and why it is important.
Rate limiting controls the amount of traffic to or from a network. In APIs, it restricts the number of calls a user can make within a certain period, typically implemented using a token bucket or leaky bucket algorithm.
Reasons for rate limiting:
- Preventing Abuse: Helps prevent abuse by limiting requests a single user can make.
- Ensuring Fair Usage: Ensures all users have fair access to the API.
- Maintaining Performance: Helps maintain performance and availability by preventing server overload.
- Cost Management: Controls costs by limiting the number of requests a user can make.
15. What is API mocking, and how does it benefit the testing process?
API mocking involves creating a mock server that replicates the responses of a real API. This is useful when the actual API is under development, has limited access, or has usage constraints. By using a mock API, testers can simulate various responses, including error conditions.
Benefits of API mocking include:
- Isolation: Allows testing of the application in isolation from external dependencies.
- Consistency: Provides consistent responses, making it easier to reproduce and debug issues.
- Speed: Reduces testing time by eliminating the need to wait for the actual API to respond.
- Cost-effective: Avoids potential costs associated with using third-party APIs during testing.
- Flexibility: Enables testing of edge cases and error conditions that may be difficult to reproduce with the real API.