如何重构Karate测试以消除对Service B的重复调用?
问题描述
我有一个Karate测试用例,里面包含4次重复的Service B请求调用,以及1次Service A的请求调用。希望把这4次重复的Service B调用重构为更简洁的实现方式,原测试代码如下:
@BcomRetry Feature: Message Routing u Background: * configure ssl = true * configure httpVersion = 'http2' * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093'] * def serviceaBaseUrl = 'http://localhost:28081' * configure retry = { count: 100 } Scenario: Test7 * def serviceb1BaseUrl = karate.get('servicebBaseUrls[0]') * def serviceb2BaseUrl = karate.get('servicebBaseUrls[1]') * def serviceb3BaseUrl = karate.get('servicebBaseUrls[2]') * def serviceb4BaseUrl = karate.get('servicebBaseUrls[3]') * def serviceaBaseUrl = karate.get('serviceaBaseUrl') * def requestBody = read('sba-local-policy/request.json') * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json') * url serviceb1BaseUrl Given path '/service-b/v1/id' When method get Then status 200 And print response * url serviceb2BaseUrl Given path '/service-b/v1/id' When method get Then status 200 And print response * url serviceb3BaseUrl Given path '/service-b/v1/id' When method get Then status 200 And print response * url serviceb4BaseUrl Given path '/service-b/v1/id' When method get Then status 200 And print response * url serviceaBaseUrl Given path '/service-a/v1/testLoadbalancer' And header Accept = 'application/json; charset=utf-8' And header Content-Type = 'application/json; charset=utf-8' And request requestBody When method post Then status 200 Then match response == expectedResponse1
重构方案
方案1:用循环遍历URL列表(最简单直接)
直接利用已有的servicebBaseUrls数组,通过karate.forEach循环处理每个Service B的请求,省去单独定义每个URL变量的步骤,代码更简洁:
@BcomRetry Feature: Message Routing u Background: * configure ssl = true * configure httpVersion = 'http2' * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093'] * def serviceaBaseUrl = 'http://localhost:28081' * configure retry = { count: 100 } Scenario: Test7 * def requestBody = read('sba-local-policy/request.json') * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json') # 循环遍历所有Service B的URL,统一执行请求 * karate.forEach(servicebBaseUrls, function(url) { url url Given path '/service-b/v1/id' When method get Then status 200 And print response }) * url serviceaBaseUrl Given path '/service-a/v1/testLoadbalancer' And header Accept = 'application/json; charset=utf-8' And header Content-Type = 'application/json; charset=utf-8' And request requestBody When method post Then status 200 And match response == expectedResponse1
方案2:提取Service B请求为可重用Feature(适合复杂场景)
如果后续Service B的请求逻辑可能变化,或者需要在其他测试用例中复用,可以把Service B的请求单独抽成一个独立的Feature文件:
新建service-b-check.feature文件
Feature: 检查Service B接口 Scenario: 调用Service B的/id接口 * url __arg Given path '/service-b/v1/id' When method get Then status 200 And print response
主测试用例中循环调用这个Feature
@BcomRetry Feature: Message Routing u Background: * configure ssl = true * configure httpVersion = 'http2' * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093'] * def serviceaBaseUrl = 'http://localhost:28081' * configure retry = { count: 100 } Scenario: Test7 * def requestBody = read('sba-local-policy/request.json') * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json') # 循环调用重用的Feature,传入每个URL * karate.forEach(servicebBaseUrls, function(url) { call read('service-b-check.feature') url }) * url serviceaBaseUrl Given path '/service-a/v1/testLoadbalancer' And header Accept = 'application/json; charset=utf-8' And header Content-Type = 'application/json; charset=utf-8' And request requestBody When method post Then status 200 And match response == expectedResponse1
额外优化点
- 原代码中单独定义
serviceb1BaseUrl到serviceb4BaseUrl完全没必要,直接用数组索引或者循环处理即可,上面的方案已经去掉了这些冗余代码。 - 原代码中
def serviceaBaseUrl = karate.get('serviceaBaseUrl')属于重复定义,可以直接使用Background里的serviceaBaseUrl变量。
内容的提问来源于stack exchange,提问作者Starbucks Admin
相关产品推荐
相关产品推荐

