ruby REST API 测试黄瓜步骤最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16741490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
REST API test cucumber steps best practice
提问by ccy
Trying to write up cucumber feature steps for REST API test.
尝试为 REST API 测试编写黄瓜功能步骤。
I am not sure which approach is better:
我不确定哪种方法更好:
Given I log in with username and password
When I add one "tv" into my cart
And I check my cart
Then I should see the item "tv" is in my cart
or
或者
Given the client authenticate with username and password
When the client send POST to "/cart/add" with body "{item: body}"
Then the response code should be "200"
And the response body should expect "{success: true}"
When the client send GET to "/cart"
Then the response code should be "200"
And the response body should expect "{"items": ["tv"]}"
Is there any convention to follow when people trying to write cucumber steps for REST API?
当人们尝试为 REST API 编写黄瓜步骤时,是否有任何约定可遵循?
回答by bitlather
I just stumbled on this helpful article: http://gregbee.ch/blog/effective-api-testing-with-cucumber
我偶然发现了这篇有用的文章:http: //gregbee.ch/blog/effective-api-testing-with-cucumber
To summarize...
总结...
Scenario: List fruit
Given the system knows about the following fruit:
| name | color |
| banana | yellow |
| strawberry | red |
When the client requests a list of fruit
Then the response is a list containing 2 fruits
And one fruit has the following attributes:
| attribute | type | value |
| name | String | banana |
| color | String | yellow |
And one fruit has the following attributes:
| attribute | type | value |
| name | String | strawberry |
| color | String | red |
Validating a result against JSON is tricky business because if the result is an array, the elements may not be the same order as how you are validating in the test.
根据 JSON 验证结果是一件棘手的事情,因为如果结果是一个数组,元素的顺序可能与您在测试中验证的顺序不同。
回答by Whitney Imura
Here's a (close enough) example to what the Pragmatic Programmer's "the Cucumber Book" says about testing REST APIs via Cuke,and it seems to more closely relate to your second example:
这是一个(足够接近的)示例,用于说明 Pragmatic Programmer 的“Cucumber Book”中关于通过 Cuke 测试 REST API 的内容,它似乎与您的第二个示例更密切相关:
Feature: Addresses
In order to complete the information on the place
I need an address
Scenario: Addresses
Given the system knows about the following addresses:
[INSERT TABLE HERE or GRAB FROM DATABASE]
When client requests GET /addresses
Then the response should be JSON:
"""
[
{"venue": "foo", "address": "bar"},
{ more stuff }
]
"""
STEP DEFINITION:
Given(/^the system knows about the following addresses:$/) do |addresses|
# table is a Cucumber::Ast::Table
File.open('addresses.json', 'w') do |io|
io.write(addresses.hashes.to_json)
end
end
When(/^client requests GET (.*)$/) do |path|
@last_response = HTTParty.get('local host url goes here' + path)
end
Then /^the response should be JSON:$/ do |json|
JSON.parse(@last_response.body).should == JSON.parse(json)
end
ENV File:
require File.join(File.dirname(__FILE__), '..', '..', 'address_app')
require 'rack/test'
require 'json'
require 'sinatra'
require 'cucumber'
require 'httparty'
require 'childprocess'
require 'timeout'
server = ChildProcess.build("rackup", "--port", "9000")
server.start
Timeout.timeout(3) do
loop do
begin
HTTParty.get('local host here')
break
rescue Errno::ECONNREFUSED => try_again
sleep 0.1
end
end
end
at_exit do
server.stop
end
回答by Emil
I've been using cucumber to test and more importantly to document the API that I created using rails-apiin my current project. I looked around for some tools to use and I ended up using a combination of cucumber-api-stepsand json_spec. It worked well for me.
我一直在使用黄瓜来测试,更重要的是记录我rails-api在当前项目中使用的 API 。我环顾四周寻找一些可以使用的工具,最终我使用了Cucumber -api-steps和json_spec 的组合。它对我来说效果很好。
There is no convention on how to write the cucumber steps. The way you write your steps depends on how you want to use your cucumber suite. I used the cucumber output as the reference for our Angular JS client devs to implement the API client. So my cucumber steps contained the actual JSON requests and responses along with the status code for each scenario. This made it really easy to communicate with a client side team whenever something changed ( especially when the client side team was not physically present at my workplace ).
关于如何编写黄瓜步骤没有约定。您编写步骤的方式取决于您想如何使用黄瓜套件。我使用黄瓜输出作为我们的 Angular JS 客户端开发人员的参考来实现 API 客户端。所以我的黄瓜步骤包含实际的 JSON 请求和响应以及每个场景的状态代码。这使得在发生变化时与客户端团队沟通变得非常容易(尤其是当客户端团队不在我的工作场所时)。
Everytime I would create or update an API, the CI server would run cucumber as part of the build and move the HTML formatted output to a "build_artifacts" location that can be opened in the browser. The client side devs would always get the most recent reference that way.
每次我创建或更新 API 时,CI 服务器都会将黄瓜作为构建的一部分运行,并将 HTML 格式的输出移动到可以在浏览器中打开的“build_artifacts”位置。客户端开发人员总是会以这种方式获得最新的参考。
I've written all of this down in a blog post about creating a tested, documented and versioned JSON API, hope it helps you in some way.
我已经在一篇关于创建经过测试、记录和版本化的 JSON API的博客文章中写下了所有这些内容,希望它能以某种方式帮助您。
回答by Neil Slater
One of Cucumber's original intents, which contributes to its design, is to bridge the gap between technical implementation, and people who know the business needs, so that the test descriptions could be written and/or understood by non-developers. As such, it's not a great fit to detailed technical specs, or blow-by-blow unit testing.
有助于其设计的 Cucumber 的初衷之一是弥合技术实施与了解业务需求的人员之间的差距,以便非开发人员可以编写和/或理解测试描述。因此,它不太适合详细的技术规范或详细的单元测试。
So that would point me to your first test description, if that's also the reason you are using Cucumber.
如果这也是您使用 Cucumber 的原因,那么这将指向您的第一个测试描述。
There is no major problem with implementing tests like the second version, Cucumber can support it. There probably are not a large number of statement types you would need to parse either. But you could end up fighting the test framework a little, or going against your rationale for using Cucumber in the first place.
像第二个版本那样实现测试没有什么大问题,Cucumber 可以支持。您可能也不需要解析大量语句类型。但是您最终可能会与测试框架发生一些冲突,或者与您首先使用 Cucumber 的基本原理背道而驰。
As for a convention, I am not aware of enough REST API tests in practice to comment, and none that I have seen tested have used Cucumber as the framework.
至于约定,我不知道在实践中是否有足够的 REST API 测试来评论,而且我所看到的测试中没有一个使用 Cucumber 作为框架。
Update: Browsing around SO on the subject, I did find a link to this: https://github.com/jayzes/cucumber-api-stepswhich is more similar to your second format.
更新:浏览关于这个主题的 SO,我确实找到了一个链接:https: //github.com/jayzes/cucumber-api-steps,它更类似于你的第二种格式。
回答by Katie
There are a few libraries now for server side REST testing with cucumber in Ruby. Here's a couple:
现在有一些库用于在Ruby 中使用 Cucumber 进行服务器端 REST 测试。这是一对夫妇:
- Cucumber-API-Steps. (Recommended)
- Cucumber-API. A small tutorial for that is here.
The library I've been using for server side REST testing with cucumber is Cucumber-API-Steps.
我一直在使用Cucumber-API-Steps进行服务器端 REST 测试的库是Cucumber-API-Steps。
Cucumber-API-Steps
Cucumber-API-步骤
Here's how I'd write your test using 'cucumber-api-steps'(Recommended):
以下是我使用“cucumber-api-steps”(推荐)编写测试的方法:
@success
Scenario: Successfully add to cart
Given I am logged in
When I send a POST request to “/cart/add” with the following:
| item | body |
Then the response status should be “200”
And the JSON response should have "success" with the text "true"
When I send a GET request to “/cart”
Then the response status should be “200”
And the JSON response should be "{'items': ['tv']}"
And here's what my tests look like using 'cucumber-api-steps':
这是我使用'cucumber-api-steps' 进行的测试:
@success
Scenario: Successfully log in
Given I am logged out
When I send a POST request to “/login” with:
| username | [email protected] |
| password | mypassword |
Then the response status should be “200”
And the JSON response should have "firstName" with the text "Katie"
Cucumber-API
黄瓜API
Here's how I'd write your test using 'cucumber-api':
以下是我如何使用'cucumber-api'编写您的测试:
@success
Scenario: Successfully add to cart
Given I am logged in
When I send a POST request to “/cart/add”
And I set JSON request body to '{item: body}'
Then the response status should be “200”
And the response should have key “success” with value “true”
When I send a GET request to “/cart”
Then the response status should be “200”
And the response should follow "{'items': ['tv']}"
And here's what my tests look like using 'cucumber-api':
这是我使用'cucumber-api' 进行的测试:
@success
Scenario: Successfully log in
Given I am logged out
When I send a POST request to “/login” with:
| username | [email protected] |
| password | mypassword |
Then the response status should be “200”
And the response should have key “firstName”
- Note about Cucumber-API: There is no way currently to do
should have key “firstName” with value “Katie”. The "with value" part has not been done yet. - Also "Follow" expects a JSON file
- 关于 Cucumber-API 的注意事项:目前没有办法做到
should have key “firstName” with value “Katie”. “带值”部分还没有完成。 - “Follow”还需要一个 JSON 文件
Another resource is here, but it is old (2011).
另一个资源在这里,但它是旧的(2011)。
回答by ADP
I would recommend your first scenario.
我会推荐你的第一个场景。
From my own experiences I personally feel that the biggest value you get from using BDD as a software delivery method, is when you place the emphasis on business value.
根据我自己的经验,我个人认为使用 BDD 作为软件交付方法获得的最大价值是当您将重点放在业务价值上时。
In other words the scenarios should be examples of what behaviour the business wants, rather than technical implementation. This ensures that the development is driven by the goals of the business and the deliverables match their expectations.
换句话说,场景应该是业务想要什么行为的例子,而不是技术实现。这确保了开发是由业务目标驱动的,并且可交付成果符合他们的期望。
This is known as outside-in development.
这被称为由外向内开发。
Additional tests of the system behaviour can and shouldbe used to cover the technical requirements but I think there's less value in spending effort writing these up in natural language, which is often time consuming and laborious across a large number of scenarios.
系统行为的额外测试可以而且应该用于覆盖技术要求,但我认为花费精力用自然语言编写这些测试的价值较小,这在大量场景中通常既耗时又费力。
I recommend the following approach:
我推荐以下方法:
1) Work with the BAs and POs to develop examples of the behaviour they want using non-implementation specific language (like your first example).
1) 与 BA 和 PO 合作,使用非实现特定语言(如您的第一个示例)开发他们想要的行为示例。
2) Engineers use these to drive the development from a test first approach, automating them as integration tests - with the majority below the browser (against your REST API for example) and the most core scenarios also through the browser(if you are developing one).
2) 工程师使用这些从测试优先的方法来驱动开发,将它们作为集成测试自动化——大多数在浏览器下面(例如针对你的 REST API)和最核心的场景也通过浏览器(如果你正在开发一个)。
3) Engineers TDD the feature code with unit tests until both the unit tests and BDD examples pass.
3) 工程师使用单元测试对特征代码进行 TDD,直到单元测试和 BDD 示例都通过。
回答by Steve Chew
I think the first one is better. I would put the technical in the ruby classes and modules. E.g like module cart.add(items)in the when step and in the then step put expect(cart.item).to include('items' => a_string_matching(item))
我觉得第一个更好。我会将技术放在 ruby 类和模块中。例如像模块cart.add(items)在when 步骤和then 步骤中放置expect(cart.item).to include('items' => a_string_matching(item))
By this, the ruby classes and modules can be reuse in another features steps. E.g like maybe you have another scenario which would add multiple items into the cart then validate the total amount.
这样,ruby 类和模块可以在另一个功能步骤中重用。例如,也许您有另一种情况,可以将多个项目添加到购物车中,然后验证总金额。
However, the second 1 I think can make it like technical features. E.g like common/global header or body request is expected across all the api.
但是,我认为第二个 1 可以使它像技术功能一样。例如,所有 api 都需要通用/全局标头或正文请求。
回答by Bernd
See here: https://github.com/ctco/cukes-rest. It provides a Cucumber DSL to test RESTful APIs.
请参阅此处:https: //github.com/ctco/cukes-rest。它提供了一个 Cucumber DSL 来测试 RESTful API。

