如何在Cucumber中读取CSV文件获取测试数据?
Great question! Let’s break down the core issue first, then walk through the correct ways to use CSV test data with Cucumber and Serenity.
The Root Problem
You’re running into a conflict between two different testing models:
@RunWith(SerenityParameterizedRunner.class)is designed for JUnit parameterized tests, which require@Testannotated methods to execute.- Cucumber uses a scenario/step-based model, where tests are defined in
.featurefiles withGiven/When/Thensteps—no@Testannotations needed. These two runners can’t be used together, which is why you’re getting that error about missing@Test.
Solution 1: Load CSV Directly in Cucumber Steps (Batch Validation)
This is the simplest approach if you want to iterate through all CSV rows in a single Cucumber scenario.
Prepare your CSV file
Place it insrc/test/resources(e.g.,src/test/resources/testdata/status-levels.csv) with a header row:status,expectedLevel Active,1 Inactive,2 Pending,3 Suspended,4Load CSV in your step definition class
Use Serenity’sTestDataFactoryto read the CSV, then loop through the rows in your step:import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import net.thucydides.core.util.TestDataFactory; import java.util.List; import java.util.Map; public class StatusValidationSteps { // Load CSV data once when the class is initialized private final List<Map<String, String>> statusData = TestDataFactory.fromCSV("testdata/status-levels.csv").build(); @Given("^I navigate to the status management page$") public void goToStatusPage() { // Add your page navigation logic here } @Then("^all statuses should have their correct levels$") public void verifyAllStatusLevels() { for (Map<String, String> row : statusData) { String status = row.get("status"); String expectedLevel = row.get("expectedLevel"); // Call your validation logic for each status-level pair verifyStatusMatchesLevel(status, expectedLevel); } } private void verifyStatusMatchesLevel(String status, String expectedLevel) { // Add your actual verification code (e.g., check UI elements, API responses) System.out.printf("Verifying status '%s' has level '%s'%n", status, expectedLevel); } }Update your Feature file
You only need a single scenario to trigger the batch validation:Feature: Validate Status Level Mapping Scenario: Verify all status-level combinations from CSV Given I navigate to the status management page Then all statuses should have their correct levels
Solution 2: CSV Rows as Separate Cucumber Scenarios (Individual Test Cases)
If you want each CSV row to appear as a separate test case in your Serenity report, you can combine Cucumber’s Scenario Outline with a custom data loader.
Keep your CSV file the same as Solution 1.
Create a helper class to load CSV data
import net.thucydides.core.util.TestDataFactory; import java.util.List; import java.util.Map; public class StatusDataProvider { public static List<Map<String, String>> getStatusLevels() { return TestDataFactory.fromCSV("testdata/status-levels.csv").build(); } }Adjust your step definitions to accept parameters from the scenario outline:
import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; public class StatusValidationSteps { private String targetStatus; private String expectedLevel; @Given("^I am checking the status \"([^\"]*)\"$") public void setTargetStatus(String status) { this.targetStatus = status; } @Given("^its expected level is \"([^\"]*)\"$") public void setExpectedLevel(String level) { this.expectedLevel = level; } @Then("^the system displays the correct level$") public void verifyStatusLevel() { // Add your validation logic here System.out.printf("Verifying status '%s' has level '%s'%n", targetStatus, expectedLevel); } }Use a Scenario Outline in your Feature file
For small datasets, you can manually map CSV rows to theExamplestable. For larger datasets, you can use Serenity/Cucumber extensions to load CSV dynamically. Here’s the manual approach:Feature: Validate Status Level Mapping Scenario Outline: Verify individual status-level pairs Given I am checking the status "<status>" And its expected level is "<expectedLevel>" Then the system displays the correct level Examples: | status | expectedLevel | | Active | 1 | | Inactive | 2 | | Pending | 3 | | Suspended | 4 |
Key Takeaway
You don’t need SerenityParameterizedRunner or @Test annotations for Cucumber tests. Instead, leverage Serenity’s TestDataFactory to load CSV data directly in your steps, or pair it with Cucumber’s Scenario Outline for individual test cases. This aligns with Cucumber’s scenario-based model while still letting you use external CSV data.
内容的提问来源于stack exchange,提问作者Keerthisagar PM

