如何在Karate中使用Scenario Outline读取两个.csv文件并实现请求与响应文件的匹配校验?
Karate was built specifically for data-driven testing scenarios like this—using CSV files to generate request payloads and validate API responses against expected CSV data is not only possible but one of its core strengths. Let’s break down the process with concrete, actionable examples.
Step 1: Set Up Your CSV Files
First, let’s define sample CSV structures to work with. Let’s say you have:
request-data.csv (for generating payloads):
user_id,full_name,email 1,Alice Smith,alice@test.com 2,Bob Johnson,bob@test.com
expected-responses.csv (for validation):
user_id,status_code,response_message 1,200,"User registered successfully" 2,200,"User registered successfully"
Step 2: Write the Karate Feature File
Here’s a complete feature that reads both CSVs, sends requests for each row, and validates responses against the expected data. We’ll cover two common approaches:
Approach 1: Using Scenario Outline (Clean, Readable)
This uses Karate’s scenario outline to loop through CSV rows automatically:
Feature: Validate API with CSV Input/Output Background: * url 'https://your-api-base-url.com/register' # Load both CSV files into Karate variables * def requestRows = read('request-data.csv') * def expectedRows = read('expected-responses.csv') Scenario Outline: Test each user registration request Given request { user_id: <user_id>, full_name: '<full_name>', email: '<email>' } When method POST Then status <expected_status> And match response.message == '<expected_message>' # Optional: Validate the returned user ID matches the request And match response.user_id == <user_id> Examples: | user_id | full_name | email | expected_status | expected_message | | karate.forEach(requestRows, expectedRows, (req, exp) => ({ user_id: req.user_id, full_name: req.full_name, email: req.email, expected_status: exp.status_code, expected_message: exp.response_message })) |
Approach 2: Using a Direct Loop (Flexible for Complex Logic)
If you need more control (like handling dynamic data or custom mappings), use a karate.forEach loop:
Scenario: Iterate through CSV data and validate responses * url 'https://your-api-base-url.com/register' * def requestRows = read('request-data.csv') * def expectedRows = read('expected-responses.csv') # Create a lookup map for expected responses (useful if rows aren't in order) * def expectedLookup = karate.map(expectedRows, (exp) => ({ key: exp.user_id, value: exp })) * karate.forEach(requestRows, (req) => { Given request req When method POST Then status expectedLookup[req.user_id].status_code And match response.message == expectedLookup[req.user_id].response_message # Add custom validation here (e.g., check timestamp format) And match response.timestamp =~ '#regex \\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}' })
Key Tips for Smooth Implementation
- Nested Payloads: If your API expects nested JSON, use dot notation in your CSV headers (e.g.,
user.full_name,contact.email)—Karate will auto-convert this into nested objects. - Dynamic Values: For response fields that change (like timestamps or generated IDs), use Karate’s fuzzy matching:
And match response.generated_id != null And match response.created_at =~ '#regex \\d{4}-\\d{2}-\\d{2}' - Large Datasets: Karate handles large CSV files efficiently, but if you need to filter rows, use
karate.filterbefore looping:* def filteredRequests = karate.filter(requestRows, (req) => req.user_id > 1)
内容的提问来源于stack exchange,提问作者SujitLearner

