为什么 Cucumber 被认为是集成测试工具而不是单元测试工具?

发布于 2024-10-03 01:57:54 字数 212 浏览 1 评论 0原文

这一直困扰着我。为什么人们说在 rspec 中进行单元测试,而在 cucumber 中进行集成测试?我不是在问为什么这些测试是必要的 - 我知道集成和单元测试之间有什么区别。我只是不明白为什么,考虑到 Cucumber 完全可定制的语法,它不用于单元测试?

在我看来,为 cucumber 和 rspec 编写的代码量是相同的,唯一的区别是,对于 cucumber,您将测试逻辑与测试编写分开。

This has always bothered me. Why is it people say to unit test in rspec but integration test in cucumber? I am not asking why these tests are necessary - I know what the difference is between integration and unit testing. I just don't see why, given cucumber's completely customizable syntax, it isn't used for unit testing?

It seems to me like the same amount of code is written for cucumber and rspec, the only difference is that for cucumber you separate the test logic from the test writing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

猫弦 2024-10-10 01:57:55

总体思路是 Cucumber 测试是在比传统单元测试更高的级别编写的。例如,当您对特定模块进行单元测试时,您只专注于测试该模块的功能,与系统的其余部分隔离。系统其他部分的接口通常应该用模拟对象来表示。

另一方面,Cucumber 专注于从 UI 一直到数据持久层的系统测试。

单元测试 = 机械工程师在安装在安全带上的实验室环境中测试他的新发动机。

黄瓜测试 = 测试驾驶员将其放在轨道上旋转。

The general idea is that Cucumber tests are written at a higher level than traditional unit tests. For instance when you unit test a particular module you're focused on testing only that modules functionality in isolation away from the rest of the system. The interface into other parts of the system should generally be represented with mock objects.

Cucumber on the other hand focuses on system testing from the UI all the way through the data persistence layer.

Unit testing = Mechanical Engineer testing his new engine in a lab setting mounted on a harness.

Cucumber testing = Test driver putting it on a track for a spin.

海未深 2024-10-10 01:57:55

单元测试是单独测试特定单元的代码。通常的粒度是类中的一个方法(或几个交互方法)。

集成测试侧重于测试应用程序堆栈的多个层。例如,您可以运行集成测试来检查代码与数据库的交互。大多数集成测试集中于两层或三层对象。

Cucumber 测试尤其倾向于关注完整的应用程序堆栈,因为它们通过在界面和应用程序的所有层(从 UI 到后端服务(数据库、文件系统、网络等)中模拟真实用户来测试应用程序) )已就位并使用。

底线:

单元测试检查特定代码段是否遵守其与世界其他部分的约定...

而黄瓜测试则检查多个代码段的交互代码(有些人可能会说是垂直切片),还有一个额外的好处是测试本身读起来就像简单的英语。

Unit tests are to test a particular unit of code in isolation. The usual granularity being a method (or few interacting methods) in a class.

Integration tests are focused on testing many layers of the application stack. For example, you can run an integration test that checks the interaction of you code with a database. Most integration tests focus of two or three layers of objects.

Cucumber tests in particular tend to focus on the full application stack, as they exercise the application by simulating a real user in the interface and all layers of the application, from the UI to the back end services (databases, file system, networks, etc) are in place and used.

Bottom line:

a unit test checks that a particular piece of code abides to its contract with the rest of the world...

Whereas a cucumber test checks the interaction of several pieces of code (a vertical slice some people may say), with the additional beauty that the test itself reads like plain English.

遥远的绿洲 2024-10-10 01:57:55

根据 Aslak Hellesøy 的说法,Cucumber 不是一个测试工具,而是一个协作工具(针对 BDD)。他最近发布了关于这种明显误解的文章:

https ://cucumber.pro/blog/2014/03/03/the-worlds-most-misunderstood-collaboration-tool.html

也就是说,有很多测试是在低于可接受水平的情况下编写的集成测试层。 ,

Given a user at 123 Evergreen Terrace
When I lookup their name
Then I get Homer Simpson

Given an address
When I lookup a name
Then the home owner name is displayed

cukes.info 显示为命令式示例(而不是声明式),这并没有帮助。

与 Rspec 或 Test::Unit 或 MiniTest 单元测试相比,Cucumber 测试运行速度较慢。它们有很多开销(可能需要几分钟的时间来加载环境,包括所有页面对象类、解析功能文件并实际执行测试)。仅运行 Cucumber 单元测试会比运行集成等效测试更快,但不如运行更轻量级的测试(例如上面提到的三个测试)那么快。

(我正在回答这个老问题,因为这是我在寻找 Cucumber 的替代品进行集成测试时得到的第一个点击之一)

According to Aslak Hellesøy, Cucumber is not a testing tool, rather a collaboration tool (for BDD). He recently posted about this apparent misconception:

https://cucumber.pro/blog/2014/03/03/the-worlds-most-misunderstood-collaboration-tool.html

That said, there are a lot of tests written below the acceptance level that would fall around the integration test layer. Ie,

Given a user at 123 Evergreen Terrace
When I lookup their name
Then I get Homer Simpson

instead of

Given an address
When I lookup a name
Then the home owner name is displayed

It doesn't help that the cukes.info shows as an imperative example (rather than declarative).

Cucumber tests run slow compared to Rspec or Test::Unit or MiniTest unit tests. They have a lot of overhead (it can take minutes to load up the environment, including all the Page Object classes, parse the feature files, and actually execute tests). Running just Cucumber unit tests would be faster than running integration equivalent tests, but not as fast as running something more light weight such as the three above mentioned.

(I am responding to this old question since it was one of the first hits I got when searching for alternatives to Cucumber for integration testing)

可是我不能没有你 2024-10-10 01:57:54

使用cucumber进行单元测试有相当多的开销。您不仅需要编写功能,还需要使用单独的代码将它们映射到实现。

单元测试的目的是要非常快地编写和执行。当然,Cucumber 注重最终用户体验,这主要是由于编写功能时使用的语言。

刷新一下,一个功能将包含以下内容:

作为系统的一些利益相关者
我想要进行一项活动
这样我就可以从中得到一些好处

Given a precondition
When I perform an action
Then something should happen

开头的段落经常被忽略,但它非常重要,因为它为操作设置了上下文并解释了为什么会发生某些事情。由于使用自然语言,这些东西很容易展示给非程序员以获得一些反馈。

现在,使用它们进行单元测试充其量看起来很尴尬。首先,最终用户关注点建议采用更加集成的方法,因为该功能没有提及模拟和 UI/逻辑分离。即,如下所示的功能看起来很奇怪:

Given a that a database mock is configured with the following data
| ID  | Username |
| 0   | igor     |
When call FindAll on User Repository
Then I get the following user back
| ID  | Username |
| 0   | igor     |

此外,随着您的 SUT 变小(即类),操作的上下文不再那么重要。用户存储库不关心上下文,例如它不关心它的使用者是普通用户还是VIP用户。一个简单的组件(按照 SRP,它应该是这样的)是完全基于其输入的确定性的。

因此,单元测试是为了验证您编写的内容是否正确,而黄瓜测试是为了通过将系统的行为置于上下文中来验证您编写的内容是否满足某些更高的目的。

There is quite a lot of overhead in using cucumber for unit testing. Not only you have to write the features but then map them to the implementation using a separate bit of code.

Unit testing is meant to be very fast to write and very fast to execute. Naturally, cucumber focuses on end user experience, mainly due to the language used in writing a feature.

Just to refresh, a feature would contain the following:

As some stakeholder of a system
I would like to perform an activity
So that I can get some benefit out of it

Given a precondition
When I perform an action
Then something should happen

The opening paragraph, that is often ignored, is very important as it sets a context for the operation and explains why something happens. Because of the use of natural language, these things are easy to show to non-programmers in order to get some feedback.

Now, using these for unit tests would seem awkward at best. First of all, the end user focus suggests a more integration approach as the feature says nothing about mocks and UI/logic separation. I.e. a feature like the following just seems weird:

Given a that a database mock is configured with the following data
| ID  | Username |
| 0   | igor     |
When call FindAll on User Repository
Then I get the following user back
| ID  | Username |
| 0   | igor     |

Also, as your SUT gets smaller (i.e. a class), the context of operation is not as important. A User repository does not care about the context e.g. it doesn't care if the consumer of it is a normal user or a VIP user. A simple component (which it should be, following SRP), is completely deterministic based on its inputs.

So, the unit test is there to validate that what you wrote is correct, and the cucmber test is there to validate that what you wrote satisfies some higher purpose by putting a behavior of the system in a context.

给不了的爱 2024-10-10 01:57:54

Cucumber 解决了一组特定的问题 - 吸引那些无法轻松阅读代码并且肯定无法编写代码的业务利益相关者,并在自动化场景中的步骤之间提供重用。这些场景通常还涵盖行为的多个方面,记录整个系统的功能,并且通常涵盖跨多个组件的整个用户旅程。 Cucumber 鼓励的基于步骤的架构非常适合处理这些场景。

它还引入了一系列其他问题。首先,您需要将 Cucumber 场景与一组固定装置联系起来,因此存在另一层抽象,这使得它们的编写速度变慢。其次,英语比代码更难重构——即使是像 Ruby 这样的动态语言(这种差异在 JBehave、SpecFlow、Cuke4Nuke 和 Cuke4Duke 等 C# 和 Java 变体中仍然更加明显)。很难判断步骤是否仍在使用,并且更难以维护场景。管理各个步骤之间的状态也更加困难。

通过单元测试,受众是技术人员。理想情况下,类具有单一职责,几乎没有重复,因此步骤的重用并不重要。当我们想要更改代码元素时,我们倾向于寻找命名约定与文件或类匹配的测试,因此与它们的一对一映射是理想的。

由于 Cucumber 的开销,并且因为我们没有从 Cucumber 提供的好处中获得价值以换取其开销,所以 RSpec 更适合单元级别的行为。 (JUnit、NUnit 等也是如此)

如果您缺少 Cucumber 的“Given、When、Then”,请尝试将它们添加为注释。这对我来说效果很好。

Cucumber solves a particular set of problems - engaging business stakeholders who can't easily read code and certainly can't write it, and providing reuse between the steps in automated scenarios. The scenarios also usually cover more than one aspect of behaviour, documenting the functionality of the entire system and often covering whole user journeys across multiple components. The step-based architecture which Cucumber encourages is ideal for handling these scenarios.

It also introduces a whole set of other problems. First, you need to tie the Cucumber scenarios to a set of fixtures, so there's another layer of abstraction which makes them slower to write. Second, English is harder to refactor than code - even with dynamic languages like Ruby (the difference is still more pronounced in the C# and Java variants like JBehave, SpecFlow, Cuke4Nuke and Cuke4Duke). It's harder to tell if steps are still being used, and harder to maintain the scenarios. It's also harder to manage state between the various steps.

With unit tests, the audience is technical. Classes ideally have single responsibilities with little to no duplication, so the reuse of steps isn't important. When we want to change an element of code we tend to look for tests whose naming conventions match the files or classes, so a one-to-one mapping with these is ideal.

Because of Cucumber's overheads, and because we don't get value from the benefits Cucumber provides in return for its overheads, RSpec is a better fit for behaviour at a unit level. (This is also true of JUnit, NUnit, etc.)

If you're missing the "Given, When, Then" of Cucumber, try adding them as comments. This works well for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文