Steerpike
Steerpike

Reputation: 1843

Cucumber in-line data table conversion and iteration

A fairly elementary question as I get used to Cucumber after a long hiatus and also get up to speed with Java 8 and lambdas. I wonder if someone can point out a better/optimal way of doing this simple Step Definition:

Given a Cucumber Scenario:

Scenario:Student submits grades 
    Given a student has completed a paper
    When they have submitted the following grades 
      | math     | good |
      | physics  | poor |
    Then the grades website shows the correct grading

And data that needs to be sent to an api in the following format:

iteration 1:
math:good
iteration 2:
physics:poor

...before asserting in the Then that both reports display as expected.

And the troublesome step definition:

 @When("they have submitted the following grades")
    public void theyHaveSubmittedTheFollowingGrades(Map<String, String> reportData) {

        String reportData;

        reportData.forEach((subject, grade) ->

        report = String.join(subject, ":", grade));

        sendReportGrades(report);

        ); //Unexpected token error here in IntelliJ
    }

so sendReportGrades(report) method calls the service that will apply the grade only if in subject:grade format and it needs to send both reports (or however many are in the table).

Upvotes: 0

Views: 1202

Answers (2)

st6ph
st6ph

Reputation: 86

I would use a POJO and dependency injection to make it more readable. Using Pico container or Spring for dependency injection as described here : https://cucumber.io/docs/cucumber/state/

In the Feature file (using a header in the data table of the When step) :
When they have submitted the following grades
  | subject | grade |
  | math    | good  |
  | physics | poor  |

POJO

public class ReportData {

  private String subject;
 
  private String grade;

  public ReportData(String subject, String grade) {
    this.subject = subject;
    this.grade = grade;
  }

  @Override
  public String toString() {
    return String.format("%s:%s", subject, grade);
  }
}

Step definition

@When("they have submitted the following grades")
public void theyHaveSubmittedTheFollowingGrades(List<ReportData> reportData) {
    reportData.stream()
        .map(ReportData::toString)
        .forEach(r -> sendReportGrades(r));
}

private void sendReportGrades(String report) {
    // Calling system under test
    ...
    System.out.println("report sent -> " + report);
}

Before Cucumber 3.x, dependency injection from the data table into the POJO was using xstream so it was really plug-and-play, but since 3.x, you have to declare your mapping from the Data Table into the ReportData POJO class like this in your step definition class :

@DataTableType
public ReportData convert(Map<String, String> entry){
  return new ReportData(
     entry.get("subject"),
     entry.get("grade")
  );
}

It gives you :

report sent -> math:good
report sent -> physics:poor

Upvotes: 1

lojza
lojza

Reputation: 1891

What about

public void theyHaveSubmittedTheFollowingGrades(Map<String, String> reportData) {
    reportData.forEach((subject, grade) -> sendReportGrades(String.join(subject, ":", grade)));
}

Upvotes: 1

Related Questions