【微服务测试】合同测试与功能测试

Chinese, Simplified

合同测试和功能测试之间的差异似乎是一个经常出现在那些开始认真投资于合同测试的团队的辩论。挑战在于它不是黑白相间的情况,而是更多的东西开始在合同测试的深度上爬行。


它可以是常见的一个地方是验证规则和被拒绝的请求。例如,我们可能有一个简单的用户服务,允许消费者注册新用户,通常使用POST请求,其中包含正文中创建的用户的详细信息。
这种交互的简单快乐路径场景可能如下所示:

Given "there is no user called Mary"

When "creating a user with username Mary"

POST /users { "username": "mary", email: "...", ... }

Then

Expected Response is 200 OK


坚持幸福路径存在丢失不同响应代码的风险,并且可能让消费者误解提供者的行为方式。那么,让我们来看一个失败的场景:

Given "there is already a user called Mary"

When "creating a user with username Mary"

POST /users { "username": "mary", email: "...", ... }

Then

Expected Response is 409 Conflict

到目前为止,我们正在使用不同的响应代码覆盖新行为。
现在我们一直在与管理用户服务的团队交谈,他们告诉我们用户名的最大长度为20个字符,他们只允许用户名中的字母和空白用户名显然无效。也许这是我们应该在合同中添加的内容?
这就是我们进入滑坡的地方......现在为我们的合同添加3个场景非常诱人,例如:

When "creating a user with a blank username"

POST /users { "username": "", email: "...", ... }

Then

Expected Response is 400 Bad Request

Expected Response body is { "error": "username cannot be blank" }

 

When "creating a user with a username with 21 characters"

POST /users { "username": "thisisalooongusername", email: "...", ... }

Then

Expected Response is 400 Bad Request

Expected Response body is { "error": "username cannot be more than 20 characters" }

When "creating a user with a username containing numbers"

POST /users { "username": "us3rn4me", email: "...", ... }

Then

Expected Response is 400 Bad Request

Expected Response body is { "error": "username can only contain letters" }

 


我们已经过了合同测试,我们实际上正在测试用户服务是否正确地实现了验证规则:这是功能测试,它应该由用户服务在其自己的代码库中涵盖。


这有什么害处...更多的测试是好的,对吧?这里的问题是这些场景太过分了,并且创建了一个不必要的紧密合同 - 如果用户服务团队确定实际上20个字符对用户名的限制太多并且将其增加到50个字符会怎么样?如果用户名中允许现在的号码怎么办?任何消费者都不应受任何这些变化的影响,遗憾的是,用户服务只会通过放松验证规则来破坏我们的契约。这些不是重大变化,但通过过度指定我们的方案,我们正在阻止用户服务团队实施它们。


让我们回到我们的场景,而只选择一个简单的例子来测试用户服务对错误输入的反应方式:

When "creating a user with an invalid username"

POST /users { "username": "bad_username_that_breaks_some_rule_that_you_are_fairly_confident_will_not_change", ... }

Then

Response is 400 Bad Request

Response body is { "error": "<any string>" }


微妙,但更灵活!现在,用户服务团队可以更改(大多数)他们的验证规则而不破坏我们给他们的契约...我们并不真正关心每个单独的业务规则,我们只关心如果我们发错了,那么我们理解用户服务响应我们的方式。
在为交互编写测试时,请问自己要覆盖的内容。合同应该是关于捕捉:

  • 消费者中的错误
  • 消费者对终点或有效负载的误解
  • 中断提供者对端点或有效负载的更改

简而言之,您的Pact场景不应该深入了解提供商的业务逻辑,而应该坚持验证消费者和提供商是否对请求和响应有共同的理解。在我们的验证示例中,编写有关验证失败的方案,而不是验证失败的原因。

SEO Title
【Microservice testing】Contract Tests vs Functional Tests