日常开发过程中,项目的接口通常由服务提供方约定和提供,微服务模式下接口被多个消费者调用更是常态,那么提供方接口的变更如何快速、高效、无遗漏的通知给消费者呢?另外,当一个service同时被多个使用者调用,如何保证对service的修改可以让其它所有使用者造成的影响都能被感知到?这些问题契约测试可以给你答案。另外,微服务模式下,接口测试是非常重要的测试手段,它在实际的项目中帮助验证微服务之间的协同和交互,大幅降低测试成本和提高测试效率方面提供了很大帮助,可以说接口测试是业务功能测试前置的助推器。因此,这里对这两种测试手段进行介绍。
在实际的工作中,结合随行付的实际情况我们对自动化测试金字塔原理进行了定制,加入契约自动化测试内容,形成如下新版自动化测试金字塔结构。
由图可知,一个项目的测试过程,从项目推进的维度,首先进行单元测试,其次接口自动化测试、契约测试,最后UI自动化测试和手工测试。
接口测试属于集成测试范畴,他是单元测试的扩展和延续。它主要的关注点是内部接口功能实现是否完整,比如说内部逻辑是不是正常,异常处理是不是正确。它是单元测试和契约测试的过渡阶段,它是项目单个代码逻辑最终串联形成有价值业务逻辑的桥梁。因此,其作用举足轻重。随行付开展接口测试,采用的思路是规范和方法先行,其次是工具选择、人员培训,然后是实施和过程优化,最后常态化持续提效和质量保证的过程。
接口测试的质量保证和测试过程的流程化需要通过规范和方法进行指导和约束。我们定制了如下要求(部分内容):
测试流程规范涉及从需求提出、脚本编写、执行到测试报告的各个过程。
脚本命名规范和编写规范如下(部分内容):
为了保证接口的质量,需要进行全面的接口测试,因此在涉及接口测试用例时需要依赖方法,因此我们总结了接口测试用例的设计要求,如下图所示。
接口测试过程提效、测试过程自动化需要依赖自动化测试工具,武器不好很难打胜仗。经过调研,市面上很多接口自动化测试工具均无法满足所有的测试要求,因此我们自研了接口自动化测试平台。自动化测试平台具有如下能力:
通过接口测试持续运行1年多的持续运营,随行付核心业务接口基本实现接口测试用例全覆盖,且均纳入到定期回归过程,持续为接口的质量保驾护航。
契约测试分两种类型,一种是消费者驱动,一种是提供者驱动。其中最常用的,是消费者驱动的契约测试(Consumer-Driven Contract Test,简称 CDC)。核心思想是从消费者业务实现的角度出发,由消费者端定义需要的数据格式以及交互细节,生成一份契约文件。然后生产者根据契约文件来实现自己的逻辑,并在持续集成环境中持续验证该实现结果是否正确。对于基于Restful API的微服务来说,它的契约就是指 API 的请求和响应的规则。 如下图所示:
那么契约测试能给微服务带来什么价值呢?文章开头已经提到了契约测试的一部分价值,即接口变更快速通知,servise修改的快速感知。除此之外,它还带来下列价值:
随行付采用在Spring Cloud Contract开展契约测试。其核心流程包括2步:
下面用一个简单的例子说明设计契约测试的方法。这个例子中,一个微服务提供了一个包含三个字段(“IP”、“name”和“password”)的资源,供三个消费者微服务使用。这三个微服务分别使用这个资源中的不同部分。消费者 A 使用其中的 IP 和 name 这两个字段。因此,测试脚本中将只验证来自提供者的资源中是否正确包含这两个字段,而不需要验证 password 字段。消费者 B 使用 IP 和 password 字段,而不需要验证 name 字段。消费者 C 则需要确认资源中包含了所有这三个字段。现在,如果提供者需要将 name 分为姓(first name)和名(last name),那么就需要去掉原有的 name 字段,加入新的 first name 字段和 last name 字段。这时执行契约测试,就会发现消费者 A 和 C 的测试用例就会失败。测试用例 B 则不受影响。这意味着消费者 A 和 C 服务的代码需要修改,以兼容更新之后的提供者。修改之后,还需要对契约内容进行更新。
下面以一个例子介绍如何使用Spring Cloud Contract开展契约测试的。
package contracts org.springframework.cloud.contract.spec.Contract.make { request { method 'PUT' url '/fraudcheck' body([ "client.id": $(regex('[0-9]{10}')), loanAmount: 99999 ]) headers { contentType('application/json') } } response { status OK() body([ fraudCheckStatus: "FRAUD", "rejection.reason": "Amount too high" ]) headers { contentType('application/json') } } }
./gradlew generateContractTests
下面是自动生成的测试脚本
@Test public void validate_shouldMarkClientAsFraud() throws Exception { //given: MockMvcRequestSpecification request = given() .header("Content-Type", "application/vnd.fraud.v1+json") .body("{/"client.id/":/"1234567890/",/"loanAmount/":99999}"); //when: ResponseOptions response = given().spec(request) .put("/fraudcheck"); //then: assertThat(response.statusCode()).isEqualTo(200); assertThat(response.header("Content-Type")).matches("application/vnd.fraud.v1.json.*"); //and: DocumentContext parsedJson = JsonPath.parse(response.getBody().asString()); assertThatJson(parsedJson).field("['fraudCheckStatus']").matches("[A-Z]{5}"); assertThatJson(parsedJson).field("['rejection.reason']").isEqualTo("Amount too high"); }
这个一个标准的JUnit测试,用RestAssured来启动Spring的webApplicationContext。
@Before public void setup() { RestAssuredMockMvc.webAppContextSetup(webApplicationContext); }
./gradlew verifierStubsJar
Spring Cloud Contract Stub Runner在集成测试中通过运行WireMock实例或者消息路由模拟真实的服务。 因此在运行之前,需要将依赖加入到gralde中,当然可以把他加到私服仓库中。
spring-cloud-starter-contract-stub-runner
对于调用方,Spring Cloud Contract提供了Stub Runner来简化Stub的使用。现在可以使用@AutoConfigureStubRunner注解.为了Spring Cloud Contract Stub Runner运行stubs注解中增加了group-id和artifact-id,举例如下:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment=WebEnvironment.NONE) @AutoConfigureStubRunner(ids = {"cn.vbill.service:test-client-stubs:1.5.0-SNAPSHOT:stubs:6565"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL) public class LoanApplicationServiceTests { ...... }
注解AutoConfigureStubRunner,里面设置了下载Stub Jar包的私库地址以及包的完整 ID,最后的6565就是指定Stub运行的本地端口。测试的时候访问Stub端口,就会根据契约返回内容。
由于随行付微服务是基于spring cloud技术栈,因此采用spring cloud contract进行微服务下的契约测试使得测试过程更流畅,更顺利,同时Spring Cloud Contract和SpringBoot以及 Junit的集成更简单方便。相信随着spring cloud contract版本的优化,契约测试可以做的更好。
本篇分别从微服务模式下如何开展接口自动化测试,契约测试的价值以及如何开展契约测试角度进行了介绍,微服务模式下,服务间的调用关系复杂,接口测试和契约测试是保证服务提高质量的重要手段,因此要充分利用。
本分类文章,与「随行付研究院」微信号文章同步,第一时间接收公众号推送,请关注「随行付研究院」公众号。