简体   繁体   中英

How to write a step definition that compares a json response to a scenario outline table

I have json response example:

{
   "colours": ["green","blue", "red"],
   "type" :   ["shoes","socks","t-shirts"],
   "make" :   ["nike", "adidas"],
} 

I have Scenario outline table:

    |colours|type    |make  |
    |red    |shoes   |nike  |
    |blue   |socks   |nike  |
    |green  |t-shirts|adidas|

I want to use the scenario table to assert against the json response. Now I know how to check this one by one, for example

* Assert colour is correct: <colours>
* Assert type is correct: <type>
* Assert make is correct: <make>

And then perform the step definition like the example below for colour:

    @Step("Assert colour is correct: <colours>")
    public void assertColourIsCorrect(String colourValue) {
        String responseBody = BridgeTestState.getLastResponse().getBody().toString();
        itemState itemStateResp = new Gson().fromJson(responseBody, itemState.class);

        assertThat("colours", itemStateResp.getColour(), is(equalTo(colourValue.toLowerCase())));
    }

Note The getColour() comes from a getter and setter I have set.

Now this works but as you can see it's a bit long winded as I have to create three separate steps to assert against each column.

I want to be a little smarter than this but don't know how to implement. What I would like is a step definition where it will look at the json response and compare it to the table based on its field and then from there view the value.

Something along the lines of:

  • Assert correct "fields" and "values" are outputted.

I hope that makes sense, basically a smart one step definition to perform the check between the json response and the table row.

From the comments it seems you want a way to do a row by row where you use the headlines of a datatable as keys for the json. You cannot achieve that by using it by example, because that is specifically meant to be mapped directly into steps the way you describe yourself. As I see there are two ways of dealing with this, depending on your use case.

First, still deal with it as parameters in the steps, ie,

Then the "colours" is <colours>
And the "type" is <type>

and then just have one step implmentation

Then("the {string} is {string}")
public void theKeyIsValue(String key, String value) {
    assertThat(json.get(key)).contains(value);
}

Another, and most likely better would be to deal with it as a normal scenario as already suggested in the comments (I did not understand why you claim that you can't). Which most often is better.

However, most likely the correct solution is - annoyingly enough - to actually rethink your scenario. There are some really great guidelines for best practices etc. on https://cucumber.io/docs/bdd/ they are fairly fast and easy to read, and will help with a lot of the initial problems.

It's hard without a complete example, but from what you write I suspect that your tests might be too technical. It's an extremely hard balance, but try to keep them so vague that they do not specify the "How" but only the "What". Example Given the username "Kate" is a better step than Given I type the username "Kate" , because in the latter you are specifying that there should be something you can type text in. I usually ask people if their tests works with a voice assistant.

Another thing I suspect is that you try to test too many things at once. One thing I notice for instance is that there are no apparent connection between your json and your table. Ie, if they data should match on the index for instance, it might make more sense. However, looking at the sparse data, I think the tests you need are:

Scenario: The colour options
  Given ...

  When the options are given

  Then the following can be chosen
    | Colour |
    | red    |
    | blue   |
    | green  |


Scenario: The clothing options
  Given ..

  When the options are given

  Then the following can be chosen
    | Type     |
    | shoes    |
    | socks    |
    | t-shirts |

That way you can still re-use the steps, you can use the headline for a key in the json, and judging by your data the tests actually relate more closely to the expected things.

Writing acceptance tests is an art the requires practice. I hope some of the suggestions here can be used, however, it is hard to come with more direct suggestions without more context.

Doing what you want to do is counter productive and against the underlying design principles of Cucumber, Scenario Outlines, and probably even data tables in Cucumber.

What the cuke should be doing is explaining WHAT the json response represents and WHY its important. HOW the json response is constructed and the details of exploring its validity and content structure should be pushed down to the step definitions, or better yet helper methods called by the step definitions.

Its really hard to illustrate this with your sample data because its really hard to work out WHAT

{
   "colours": ["green","blue", "red"],
   "type" :   ["shoes","socks","t-shirts"],
   "make" :   ["nike", "adidas"],
} 

represents. Its also pretty hard to understand why you want to make the assertions you want to make.

If you gave a real example and explained what the data represents and WHY its important and perhaps also WHY you need to check it and WHAT you would do if it wasn't correct then we might be able to make more progress.

So I'll try with my own example which won't be very good

Given a set of clothing
When I get a json representation of the clothing
Then the json should be valid clothing

and the steps

Given 'a set of clothing' do
  create_clothing_set
end

When 'I get a json representation of the clothing' do
  @json = make_clothing_request type: :json
end

Then 'the json should be valid clothing' do
  res = validate_clothing json: @json
  expect res ...
end

Now your problem is how to write some code to validate your clothing ie

  def validate_clothing(json: )
    ...
  end

Which is a much simpler problem being executed in a much more powerful environment. This has nothing to do with cucumber, no interactions with features, scenarios etc. its just a simple programming problem.

In general with Cucumber either push technical problems down, so they become programming problems, or pull problems up, so they are outside Cucumber and become scripting problems. This keeps Cucumber on topic. Its job is describe WHAT and WHY and provide a framework to automate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM