如何迭代动态对象数组并将每个对象用作测试中的参数?

huangapple go评论56阅读模式
英文:

How to iterate over a dynamic array of objects and use each object as a parameter in test?

问题

我一个月前开始学习空手道。我有一个名为getAllCars.feature的简单GET测试,显示当前可用的汽车列表:

[   
  {     
    "brandName": "BMW",     
    "id": 1,     
    "winterTires": false,     
    "modelName": "X5"   
  },   
  {     
    "brandName": "Opel",     
    "id": 34,     
    "winterTires": true,     
    "modelName": "Insignia"   
  },   
  {     
    "brandName": "Mercedes-Benz",     
    "id": 36,     
    "winterTires": true,     
    "modelName": "GLE Coupe"   
  },   
  {     
    "brandName": "Huydai",      
    "id": 251,     
    "winterTires": false,     
    "modelName": "i30"   
  } 
]

我必须将每个id用作下一个功能文件的参数,问题是,汽车列表是动态的,id不重复,我将不得不在几个其他功能文件中使用这些id列表。我成功创建了一个名为getCarIds.feature的辅助功能,它创建了一个对象数组 "carId": "#number":

Feature: 获取汽车ID

  Scenario: 获取汽车ID
    * call read('classpath:x/automation/cars/getAllCars.feature')
    * def carIds = $response[*].id
    * def carFeeder = karate.mapWithKey(carIds, 'carId')

接下来的getCarParameters.feature必须遍历来自getCarIds.feature的数组,并将每个id作为参数传递以获得每辆汽车的性能参数的响应,我不知道如何单独使用每个id作为参数(考虑到id列表在更改):

Feature: 获取每辆汽车的参数

  Scenario: 获取每辆汽车的参数
    * call read('classpath:x/automation/cars/getCarIds.feature')
    Given url carUrl + '/carparameters'
    And param carId =
    When method GET
    Then status 200

当将getCarIds.feature中的值传递给getCarParameters.feature时,我成功做到了如此描述的方式,通过向getCarIds.feature添加以下行:

* call read('classpath:x/automation/cars/getCarParameters.feature') carFeeder

但是还有其他测试需要汽车id。我需要getCarIds.feature是可重复使用的,所以我必须从创建id数组的功能文件中检索数据,而不是将其传递给GET功能,显然并不那么容易。也许我的方法完全错误。

英文:

I started my adventure with Karate a month ago. I have a simple GET test called getAllCars.feature showing a list of cars currently available:

[   
  {     
    "brandName": "BMW",     
    "id": 1,     
    "winterTires": false,     
    "modelName": "X5"   
  },   
  {     
    "brandName": "Opel",     
    "id": 34,     
    "winterTires": true,     
    "modelName": "Insignia"   
  },   
  {     
    "brandName": "Mercedes-Benz",     
    "id": 36,     
    "winterTires": true,     
    "modelName": "GLE Coupe"   
  },   
  {     
    "brandName": "Huydai",      
    "id": 251,     
    "winterTires": false,     
    "modelName": "i30"   
  } 
]

I have to use each id as a parameter for the next feature file, the problem is, the list of cars is dynamic, ids don't repeat and I will have to use this list of ids for several other feature files. I managed to create a helper getCarIds.feature, which creates an array of objects "carId": "#number":

Feature: Get car IDs

  Scenario: Get car IDs
    * call read('classpath:x/automation/cars/getAllCars.feature')
    * def carIds = $response[*].id
    * def carFeeder = karate.mapWithKey(carIds, 'carId')

The following getCarParameters.feature has to iterate over the array from getCarIds.feature and pass each id as a parameter to get a response with performance parameters of each car and I don't know how to use each id separately as a parameter (keeping in mind that the list of ids is changing):

Feature: Get parameters of each car

  Scenario: Get parameters for each car
    * call read('classpath:x/automation/cars/getCarIds.feature')
    Given url carUrl + '/carparameters'
    And param carId =
    When method GET
    Then status 200

I managed to do it when passing the values from getCarIds.feature to getCarParameters.feature like described here by adding following line to getCarIds.feature:

* call read('classpath:x/automation/cars/getCarParameters.feature') carFeeder

but several other tests require car ids. I need getCarIds.feature to be reusable, so I would have to retrieve data from feature file, which creates the array with ids, instead of passing it to the GET feature and apparently it isn't so easy. Maybe my approach is completely wrong.

答案1

得分: 0

我认为这是一个适用于karate.callSingle()的有效案例:https://github.com/karatelabs/karate#karatecallsingle

所以,你实际上可以将这个部分放入任何功能中,它保证只在整个测试套件中执行一次。如果数据确实是你的测试套件中大多数部分都在使用的内容,你甚至可以在karate-config.js中进行初始化。

所以这应该有效。首先是可重用的功能common.feature。不要使用硬编码的响应,你知道如何发出实际的HTTP请求。

@ignore
Feature:

Scenario:
* def response =
"""
[   
  {     
    "brandName": "BMW",     
    "id": 1,     
    "winterTires": false,     
    "modelName": "X5"   
  },   
  {     
    "brandName": "Opel",     
    "id": 34,     
    "winterTires": true,     
    "modelName": "Insignia"   
  }
]
"""
* print '获取汽车ID'
* def carIds = response.map(x => ({ id: x.id }))

请注意上面使用的JS map()函数,我开始推荐它而不是JsonPath。

这是一个使用上述功能的示例。这里使用了新的@setup注解,它使“循环”变得容易:https://github.com/karatelabs/karate#setup

你可以快速尝试这个示例,观察它使用来自循环的参数id进行2次请求。

Feature:

@setup
Scenario:
* def data = karate.callSingle('call-single-common.feature').carIds

Scenario Outline:
* url 'https://httpbin.org/get'
* param id = id
* method get

Examples:
| karate.setup().data | 

还有其他循环的方法,请参考:https://github.com/karatelabs/karate#data-driven-features

英文:

I think this is a valid case for karate.callSingle(): https://github.com/karatelabs/karate#karatecallsingle

So you can actually stick this in any feature and it is guaranteed to execute only once across your test suite. If the data is indeed something used by a majority of your test suite, you could even do this initialization in karate-config.js.

So this should work. First the reusable feature common.feature. Instead of the hard-coded response, you know how to make an actual HTTP request.

@ignore
Feature:

Scenario:
* def response =
"""
[   
  {     
    "brandName": "BMW",     
    "id": 1,     
    "winterTires": false,     
    "modelName": "X5"   
  },   
  {     
    "brandName": "Opel",     
    "id": 34,     
    "winterTires": true,     
    "modelName": "Insignia"   
  }
]
"""
* print 'getting car ids'
* def carIds = response.map(x => ({ id: x.id }))

Note the use of the JS map() function above, which I have started to recommend instead of JsonPath.

And here is a feature that uses the above. This uses the new @setup annotation that makes it easy to "loop": https://github.com/karatelabs/karate#setup

You can try this example quickly, and watch it make 2 requests using a param id from the loop.

Feature:

@setup
Scenario:
* def data = karate.callSingle('call-single-common.feature').carIds

Scenario Outline:
* url 'https://httpbin.org/get'
* param id = id
* method get

Examples:
| karate.setup().data | 

There are other ways to loop, refer: https://github.com/karatelabs/karate#data-driven-features

huangapple
  • 本文由 发表于 2023年2月9日 03:20:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75390745.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定