我应该测试合同中的所有枚举值吗?

Should I test all enum values in a contract?

我对是否应该考虑某种类型的测试功能或合同有疑问。

假设我有一个像 /getToolType 这样的 API,它接受一个 {object" "myObject"} 作为输入,并且 returns 的类型为 {type: " [a-z]+"}

客户端和服务器同意类型 returned 将匹配一组字符串,比方说 [hammer|knife|screwdriver],因此消费者决定在枚举中解析它们,使用returned 类型未知时的回退值。

消费者是否应该为每种类型(锤子、刀子、螺丝刀)包含一个测试用例,以确保生产者仍然遵守协议,它总是 return,例如,小写字符串 "hammer" 当使用锤子对象调用 /getToolType 时? 或者你会认为这样的测试用例是功能性的吗?为什么?

好问题。简短回答:没有正确或错误的方法,只有你想怎么做。

更长的答案:

Pact(和合同测试)的重点是测试特定场景并确保它们匹配。您可以简单地在合同中创建一个正则表达式,允许这些枚举使用任何字符串类型,或者可能为 null,但前提是您的消费者根本不关心该值。例如,如果工具类型有品牌,我不会关心品牌,只关心它作为字符串返回,因为我只是在消费者(前端)上逐字显示品牌。

但是,如果由我来决定,根据我对你的场景的理解,考虑到它所击中的端点,工具类型似乎实际上非常重要,因此我可能会对每个枚举进行特定的测试和合同确保我的消费者的那些特定场景有效(我用某物调用 X,我希望 Y 具有工具类型 Z)。

这两种解决方案都有效,归结为:您认为特定工具类型对消费者重要吗?如果是,则创建特定于它的合同,如果不是,则只需创建一个通用合同。

希望对您有所帮助。

IMO 简短的回答是 'no'。

合同测试对结构更感兴趣,如果我们开始边界测试 API,我们将进入功能测试 [1] 领域,最好在提供商代码库中完成。您可以使用匹配器来确保这三个值中只有一个被 returned,这应该确保 Provider 构建不能 return 其他值。

我会附和@J_A_X的评论——没有正确或错误的答案,只是要小心测试input/output数据的所有排列.

[1] https://docs.pact.io/best_practices/contract_tests_not_functional_tests.html

正确状态是消费者消费锤子、刀子、螺丝刀,简称c=(锤子、刀子、螺丝刀),而生产者生产锤子、刀子、螺丝刀,p=(锤子、刀子、螺丝刀)。 有四种回归场景:

  1. c=(锤子,刀子,螺丝刀,剑),p=(锤子,刀子,螺丝刀)
  2. c=(锤子、刀、螺丝刀)、p=(锤子、刀、螺丝刀、剑)
  3. c=(锤子,刀子,螺丝刀),p=(锤子,刀子)
  4. c=(锤子,刀),p=(锤子,刀,螺丝刀)

1和3以一种非常温和的方式违约。 在第一种情况下,客户声明了生产者(尚未)支持的新类型。 在第三种情况下,生产者停止支持一种类型。 场景的严重性当然可能是谨慎的,因为我认为软回归的东西可能在业务关键流程中的某个服务中。 但是,如果它很关键,那么就有很大的动机用专门的测试用例来覆盖它。 第二和第四种情况更严重,在这两种情况下,消费者都可能会出错,例如可能无法反序列化数据。

每种类型都有一个测试用例应该可以检测场景 3 和场景 4。 在第一种情况下,它可能会触发开发人员创建一个额外的测试用例,该用例将在生产者站点上失败。 但是,测试用例对第二种情况无能为力。 所以尽管成本相对较高,但这种策略并没有为我们提供完整的测试覆盖率。

拥有一个包含所有有效类型(即锤子|刀|螺丝刀)的正则表达式测试用例应该是消费者开发人员在第一个阶段重新设计测试用例的强大触发因素和第四种情况。 一旦将正则表达式调整为新的消费者功能,它就可以以概率 p=1/3 检测场景 4(即,如果生产者选择螺丝刀作为样本值,则测试将失败)。 即使没有正则表达式调整,它也会检测到 p=1/3 的第三种情况。 此策略对第一种和第二种情况无能为力。

但是,在正则表达式之上,我们可以做更多的事情。 即,我们可以用随机数据设计生产者测试用例。 假设有问题的类型定义如下:

enum Tool {hammer,knife,screwdriver}

我们可以渲染测试数据:

responseBody = Arranger.some(Tool.class);

这段代码使用了 test-arranger,但也有其他库可以做同样的事情。 它选择一个有效的枚举值。 每次都可以是不同的。 它改变了什么? 现在我们可以检测第二种情况,并在调整正则表达式后检测第 4 种情况。 所以它涵盖了最严重的场景。 还有一个缺点需要考虑。 生产者测试是不确定的,取决于提取的值,它可以成功或失败,这被认为是反模式。 尽管测试的代码是正确的,但有时某些测试有时会失败,人们开始忽略测试的结果。 请注意 producer test case with random data 并非如此,事实上恰恰相反。 尽管经过测试的代码不正确,但它有时会成功。 它仍然远非完美,但这是一个有趣的权衡,因为它是第一个成功解决非常严重的第二种情况的策略。

我的建议是使用 生产者测试用例和随机数据 支持客户端的正则表达式。 尽管如此,没有完美的解决方案,您应该始终考虑对您的服务来说什么是重要的。 具体来说,如果消费者可以安全地忽略未知值,则推荐的方法可能并不完美。