何时给定(GWT)和行为安排断言(AAA)之间的区别?


13

在TDD中,有Arrange Act Assert(AAA)语法:

[Test]
public void Test_ReturnItemForRefund_ReturnsStockOfBlackSweatersAsTwo_WhenOneInStockAndOneIsReturned()
{
    //Arrange
    ShopStock shopStock = new ShopStock();
    Item blackSweater = new Item("ID: 25");
    shopStock.AddStock(blackSweater);
    int expectedResult = 2;
    Item blackSweaterToReturn = new Item("ID: 25");

    //Act
    shopStock.ReturnItemForRefund(blackSweaterToReturn);
    int actualResult = shopStock.GetStock("ID: 25");

    //Assert
    Assert.AreEqual(expectedResult, actualResult);
}

在BDD中,编写测试使用类似的结构,但语法为“当下(GWT)”:

    [Given(@"a customer previously bought a black sweater from me")]
    public void GivenACustomerPreviouslyBoughtABlackSweaterFromMe()
    { /* Code goes here */   }

    [Given(@"I currently have three black sweaters left in stock")]
    public void GivenICurrentlyHaveThreeBlackSweatersLeftInStock()
    { /* Code goes here */   }

    [When(@"he returns the sweater for a refund")]
    public void WhenHeReturnsTheSweaterForARefund()
    { /* Code goes here */   }

    [Then(@"I should have four black sweaters in stock")]
    public void ThenIShouldHaveFourBlackSweatersInStock()
    { /* Code goes here */   }

尽管它们通常被认为是相同的,但仍存在差异。一些关键的是:

  1. GWT可以直接映射到BDD框架中功能文件的规范

  2. 通过鼓励使用通俗易懂的英语,并对每个部分的功能进行简短描述,GWT对于非开发人员来说更容易理解。

  3. 在各种BDD框架(例如SpecFlow和Cucumber)中给定“何时”和“之后”是关键字

我的问题是AAA和GWT之间是否还有其他区别(名称除外)?除了上面指定的理由之外,还有什么理由比另一个更可取吗?


3
除了“读起来更像自然语言”以外,我没有其他区别。给定一个安排,当一个动作发生时,就断言有关新状态的事情。
Sjoerd Job Postmus

我认为您已经找到了两个相关的要点,并且不太可能获得其他差异的答案。出于其价值,我完全使用AAA进行单元测试,因为该格式完全与方法无关,但鼓励进行小型独立测试。
阿蒙

Answers:


9

我认为您在问题中很好地列出了差异,但是我将对我对这两种方法的看法发表一些看法。

在测试自己的代码时,AAA对我非常有用。如果我正在为自己开发项目或库,那么AAA是我的选择。它使我可以设置执行测试所需的任何内容,然后进行测试。它可以快速设置,并且可以快速验证我的代码是否按预期工作。

GWT在需要将程序员所完成的工作映射到业务价值的业务环境中很有用。商业价值是由功能映射的,希望功能不会引入错误。有许多将功能映射到编程任务的策略,但是其中之一就是通过需求。根据我的经验,需求范围从用户级别的需求一直到用户执行的小任务。这很有用,因为对于管理人员而言,很容易理解程序员所做的工作如何影响他们的客户/用户,以及为什么程序员为他们的业务增加价值

  • 用户级要求:假设仓库中至少有N件商品,那么当用户购买N件商品时,仓库会将N件商品运送给用户
  • 系统级要求1:给定库存系统中有N个物料,当向库存系统输入N个物料的请求时,库存系统会减少该物料类型的库存数量
  • 系统级要求2:给定付款系统中有N个物品的库存,当将对N个物品的请求输入到付款系统时,付款系统向用户收取N个物品的费用
  • ...
  • 程序员级别的要求1:假设库存中有5件毛衣,那么从库存中删除3件毛衣时,库存中剩下2个座位
  • ...

这种需求结构允许进行树状设计,其中所有程序员级别的需求都将树映射到用户级别的需求。这样,当程序员级别的要求失败时,您便知道受影响的用户级别的要求。

相反,AAA测试可能看起来像这样。对我而言,这是面向程序员的,对企业没有用。这并不是说无法通过AAA测试策略来构建类似的需求树结构,但是AAA语言中的任何内容都不会使它更容易做到。

public void Test_CaseWhereThereAreEnoughSweatersLeft() {
    // Arrange
    // setup Sweater Inventory mock (DB mocks, etc)
    // count = 5
    // when The number of sweaters remaining is request, return count
    // when Inventory is requested to remove N items, then count = count - N

    // Act
    // call the Unit Under Test to remove 3 items from inventory

    // Assert
    // the number of sweaters in the inventory is 2
    // the removal should return indicating a successful removal of items from the inventory
}

public void Test_CaseWhereThereAreNotEnoughSweatersLeft() {
    // Arrange
    // setup Sweater Inventory mock (DB mocks, etc)
    // count = 2
    // when The number of sweaters remaining is request, return count
    // when Inventory is requested to remove N items, then count = count - N

    // Act
    // call the Unit Under Test to remove 3 items from inventory

    // Assert
    // the number of sweaters remaining is still 2
    // the removal should return an error indicating not enough items in the inventory
}

当人们质疑计算机(以及程序员)是否正在为他们的业务增值时,我总是觉得很有趣。难道真的只是一个自私的大竹竿?我认为业务经理应该或者对编程学到足够的知识,以了解它是如何实现其目标的,或者仅仅是相信它可以完成而不必担心。我可能不太了解一种化学物质如何影响心房细胞延迟整流电流的产生,但是我绝对可以感觉到不再患有心律不齐是多么好。

在计算机科学之外,抽象是重要的。人们将拥有不同领域的专业知识,并且能够与他人交流这些专业知识对于企业至关重要。GWT是一种抽象,有助于使程序员和(项目|项目)经理进行交流。第二,作为程序员,很容易想到程序员有潜力为企业创造几乎没有价值。最后,值得注意的是,GWT不仅是让程序员和管理人员进行交流的方式,还是企业可能想尝试的众多工具之一。
弗兰克·布莱斯

另外,我希望我的医生在将其投入使用之前了解我的心律不齐纠正机制为何起作用,而不仅仅是这样做。GWT测试应该有助于回答“为什么”。GWT帮助程序员与产品经理之间的交流类似于化学家与医生之间的交流。产品经理与用户交流他们所获得的功能,而医生向患者传达他们通过心律不齐矫正所获得的价值。
Frank Bryce '18

4

我猜这取决于您使用的框架。通常,据我了解,AAA由NUnit框架支持,因此在这方面是自然的选择。至于TDD和BDD之间的理论差异,它们似乎很小。请参阅链接,比我更有资格的人给您解释。


2

完全没有区别。
测试的三种状态:
给定=安排,
当=行动,
然后=声明。

您在问题中提供的差异是TDD和BDD之间的差异,而不是GWT和AAA之间的差异。

在TDD中,您可以通过三种不同的方法进行一项测试

public class TestsOfFormatMethod
{        
    public void Arrange() { // set dependencies }
    public string Act() { // return formattted result }
    public string AssertThatFormatIsEmpty()
    {
        Arrange();
        var actual = Act();
        Assert.IsEmpty(actual);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.