应该测试哪个抽象层

时间:2017-11-02 23:19:16

标签: unit-testing testing tdd bdd

假设我们有一些功能可以写。它应该使用一些公司数据验证csv文件 - 每行一个公司。我想为这个功能编写测试。今天我与同事进行了一些对话,我们无法确定哪种方法更好,或者我们都错了:

  1. 在某些服务级别编写测试,这是验证的切入点。它有一种方法:

    ProcessingResult process(CsvFile csvFile)
    

    IBAN号的测试如下:

    // given
    valid csv row with invalid value in IBAN column
    // when
    service called
    // then
    result is validation failure with INVALID_IBAN error reason
    
  2. 为特定验证器编写测试。这种方法假设很少有验证器负责某些列ex。 CompanyNameValidatorAccountNumberValidator等等。

  3. 第一种方法很好,因为它让我们在不接触测试的情况下重构整个验证过程。我尝试了它并且在每一步之后完全改变了实现运行测试,我非常自信我没有破坏任何东西。这种方法也有缺点。假设我对公司名称和IBAN进行了测试。考虑在IBAN之前实施检查公司名称。假设此名称检查已损坏。现在对IBAN的测试也被打破了(公司名称打破了它)。是不是没有?

    第二种方法不会有上述问题,因为公司名称由不同的验证者验证,而不是IBAN。然而,这使得更大的重构变得不可能。如果我们想要改变实现并从多个验证器方法中退出,我们将不得不修改测试以及我们测试它们而不是整个功能。

    哪种方法更好,或者有另一种方法来测试我不知道的这种代码?

2 个答案:

答案 0 :(得分:2)

正如您所注意到的,第一种方法将带来更多价值,因为您可以自由地使用实现。

  

我们说我对公司名称和IBAN进行了测试。考虑   在IBAN之前实施检查公司名称。让我们说出这个名字   检查坏了。现在,IBAN的测试也被打破了(公司名称   打破它)。是不是没有?

分别为每个验证测试用例编写测试。那么你将获得干净的测试报告"如果没有读取/打开失败的测试消息,测试名称将告诉您确切的问题。

但是,因为您阅读文件,建议抽象文件读取,然后您的测试变得更快,并且不会影响维护验证逻辑。

答案 1 :(得分:2)

我喜欢教我的团队的主题:

尽量避免将测试与实现细节耦合,因为单元测试(尤其是在TDD环境中)是关于重构,而不是测试。

测试特定的验证器将导致脆弱的测试,因为重构的能力将会严重改变。

的确,如果明天您或您的队友有更好的方法来设计涉及不同验证性质的代码,该怎么办?

如果明天你让第三方图书馆进行验证工作怎么办? 如果明天你想要合并/合并一些验证器怎么办?

我的观点是:始终在API级别进行单元测试就像您提到的第一种方法
这样,您就可以在不破坏任何测试的情况下重构代码。

您的测试不应该了解您用于完成工作的策略 它应该只关注入口点:API(通常是Java / C#等中的public方法)。

人们抱怨单位测试浪费时间;症状是独一无二的:
按照他们的方式,测试与实现细节相结合;所以在重构步骤中太容易破坏。

不要单独为每个验证编写测试文件,除非在出现故障时聆听测试变得难以理解。
只要你能够做到这一点,你就会陷入困境,因为你不会因为你赢了而不允许重构。你现有的测试中断了(一种悲伤的人类行为)。

  

我们说我对公司名称和IBAN进行了测试。考虑   在IBAN之前实施检查公司名称。让我们说出这个名字   检查坏了。现在,IBAN的测试也被打破了(公司名称   打破了它。)

这一点显然不依赖于测试策略。
您的算法应根据相关的用户故事进行调整:
验证"快速失败"那些(在这种情况下,检查公司名称的失败是否会中断整个过程)?
只需编写另一个测试,其中上下文是成功的公司名称检查和失败的IBAN验证;但继续定位API。

如果您想了解更多信息,建议您观看that video;我在这个问题上看过的最好的。