【问题标题】:Can I use BDD by testing low abstraction level code?我可以通过测试低抽象级别的代码来使用 BDD 吗?
【发布时间】:2022-03-17 20:19:04
【问题描述】:

我检查了several (real world) BDD examples,但我发现的只是使用 selenium 的 e2e 测试。我想知道,是否可以使用 BDD 编写单元测试?如果是这样,这样的单元测试在小黄瓜中应该怎么看?我很难想象在功能和场景描述中要写什么,以及如何使用它们来生成文档,例如java collection framework

编辑

我在这里找到了一个例子:http://jonkruger.com/blog/2010/12/13/using-cucumber-for-unit-tests-why-not/comment-page-1/

特点:

Feature: Checkout

  Scenario Outline: Checking out individual items
    Given that I have not checked anything out
    When I check out item 
    Then the total price should be the  of that item

  Examples:
    | item | unit price |
    | "A"  | 50         |
    | "B"  | 30         |
    | "C"  | 20         |
    | "D"  | 15         |

  Scenario Outline: Checking out multiple items
    Given that I have not checked anything out
    When I check out 
    Then the total price should be the  of those items

  Examples:
    | multiple items | expected total price | notes                |
    | "AAA"          | 130                  | 3 for 130            |
    | "BB"           | 45                   | 2 for 45             |
    | "CCC"          | 60                   |                      |
    | "DDD"          | 45                   |                      |
    | "BBB"          | 75                   | (2 for 45) + 30      |
    | "BABBAA"       | 205                  | order doesn't matter |
    | ""             | 0                    |                      |

  Scenario Outline: Rounding money
    When rounding "" to the nearest penny
    Then it should round it using midpoint rounding to ""

    Examples:
      | amount | rounded amount |
      | 1      | 1              |
      | 1.225  | 1.23           |
      | 1.2251 | 1.23           |
      | 1.2249 | 1.22           |
      | 1.22   | 1.22           |

步骤定义(红宝石):

require 'spec_helper'

describe "Given that I have not checked anything out" do
  before :each do
    @check_out = CheckOut.new
  end

  [["A", 50], ["B", 30], ["C", 20], ["D", 15]].each do |item, unit_price|
  describe "When I check out an invididual item" do
    it "The total price should be the unit price of that item" do
      @check_out.scan(item)
      @check_out.total.should == unit_price
    end
  end
end

  [["AAA", 130], # 3 for 130
    ["BB", 45],  # 2 for 45
    ["CCC", 60],
    ["DDD", 45],
    ["BBB", 75], # (2 for 45) + 30
    ["BABBAA", 205], # order doesn't matter
    ["", 0]].each do |items, expected_total_price|
    describe "When I check out multiple items" do
      it "The total price should be the expected total price of those items" do
        individual_items = items.split(//)
        individual_items.each { |item| @check_out.scan(item) }
        @check_out.total.should == expected_total_price
      end
    end
  end
end

class RoundingTester
  include Rounding
end

[[1, 1],
  [1.225, 1.23],
  [1.2251, 1.23],
  [1.2249, 1.22],
  [1.22, 1.22]].each do |amount, rounded_amount|
  describe "When rounding an amount of money to the nearest penny" do
    it "Should round the amount using midpoint rounding" do
      RoundingTester.new.round_money(amount).should == rounded_amount
    end
  end
end

我不知道基于此生成文档的方法。这不是没有希望的,例如将Feature: Checkout 映射到Checkout 类很容易。也许可以在方法级别上做类似的事情。编写特定于此任务的帮助器的另一种可能的解决方案。

【问题讨论】:

  • 哪种语言?爪哇?
  • @maboiteaspam 我认为语言在这里并不重要,我只想知道如何将 gherkin 上描述的特性映射到 API 在任何 oo 语言上的类/接口和方法。我猜功能和场景描述应该包含这些信息,但我认为接口、类和方法名称是实现细节,所以小黄瓜代码不应该包含它们,它们应该只在步骤定义中。也许我错了,这就是我对现实世界的例子感兴趣的原因。
  • 事实上我想建议你检查一下 mocha 框架,因为它提供了界面和输出文档很容易。忘记链接对不起,它在这里mochajs.org
  • @maboiteaspam 不明白跟题目有什么关系,是个javascript单元测试框架,我知道,我更喜欢jasmine。但是它们并不完全支持 BDD,它们只有 BDD 之类的断言,仅此而已。 Cucumber 有功能和步骤文件,而这些测试框架只有一个包含混合内容的规范文件。顺便提一句。我不是在寻找测试框架,而是通过测试低抽象级别的代码来寻找 gherking 的示例用法。
  • 我不明白你为什么不能。我不希望在我的单元测试中增加黄瓜的开销。

标签: cucumber bdd gherkin


【解决方案1】:

这里的一个关键思想是理解描述行为和测试之间的区别。在这种情况下,描述行为是:

  • 更抽象
  • 易于被更广泛的受众阅读
  • 更专注于您正在做什么以及为什么要这样做
  • 较少关注“如何”做某事
  • 不那么详尽,我们使用示例,我们不会涵盖所有内容

测试往往是:

  • 精确
  • 详细
  • 详尽的
  • 技术

当您使用 BDD 工具时,例如Cucumber 来编写单元测试,你往往会以测试结束

  1. 冗长
  2. 充满了只有少数人才能欣赏的技术细节
  3. 运行成本很高
  4. 难以维护

因此,我们为不同类型的“测试”提供了不同的工具和不同的技术。通过使用正确的工具完成正确的工作,您可以获得最大的收益。

虽然使用一种工具进行所有测试的想法似乎非常吸引人。最后,它与使用一种工具修理汽车一样明智 - 尝试用锤子为轮胎打气!

【讨论】:

  • 我认为这里的关键字是抽象的。例如。通过密码更改:"Given I am logged in as customer When I change the password Then I can login with the new password But not with the old password",这是非常抽象的,但是您可以通过测试移动页面、桌面页面、rest api、业务逻辑甚至数据访问来使用它,只需通过不同的步骤使用它即可。所以我认为如果你的 BDD 测试充满了技术细节,那么你做错了什么。 (这只是我个人的看法。)
【解决方案2】:

BDD 将系统描述为一个黑盒子。如果您在其中有任何与实现相关的词,它不再是 BDD。 Inf3rno 发布了一个具有正确抽象的示例。

我总是问自己,如果用户界面消失了,我还能保留相同的功能文件吗?如果要通过语音命令执行用例,这些步骤是否仍然有意义?

另一种思考方式是,步骤陈述应该是关于系统的事实,而不是关于如何手动测试它的说明。

good step definition
Given An account "FOO" with username <username> and password <password>


bad step definition (only applies to ui)
Given I am at the login page
And I enter <username> as the username
And I enter <password> as the password

Full example
Given An account "FOO" with username <username> and password <password>
When Creating an account with username <username> and password BAR
Then An error "Username already in use" is returned

请注意,我可以针对用户界面和 api 实现最后一个示例,但我也可以通过语音命令实现它;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2013-04-18
    • 1970-01-01
    相关资源
    最近更新 更多