前言最近公司开始有后端的项目,必不可免的需要针对这些后端 API 进行测试。随着测试技术的突飞猛进,越来越多的人喜欢造轮子。面对如此多的框架该如何选型呢。
框架选型在众多的框架里面,耳熟能详的,postman,RF, JMeter,rest-assured,HTTPrunner....对于框架的选型,个人的观点,怎么简单怎么来吧。
1.框架是否能较好的支持
2.框架维护成本
3.团队成员学习成本
我的方案 Junit + Rest-Assured, 原因如下:
*后端项目采用 Gradle,Rest-Assured 可以快速度集成,在后续的 CI 中较友好,统一的仓库,编译执行命令。
*团队采用 Juint 做 UT/IT,学习成本较低。
*现有的 mock server client,可以使用 Gradle 集成
*Rest-Assured 对 restful 的支持友好,提供良好的断言,given-when-then 与现有的 AC 方式相似,可接受度高
开始框架集成 build.gradle 添加依赖, 在这里需要注意的是版本间的兼容
dependencies { testImplementation('junit:junit:4.13') //rest-assured testCompile group: 'io.rest-assured', name: 'rest-assured', version: '4.1.2' testCompile group: 'io.rest-assured', name: 'rest-assured-all', version: '4.1.2' testCompile group: 'io.rest-assured', name: 'spring-mock-mvc', version: '4.1.2' testImplementation 'io.rest-assured:json-path:4.1.2' testImplementation 'io.rest-assured:json-schema-validator:4.1.2' testImplementation 'io.rest-assured:xml-path:4.1.2' //Log4J: testImplementation group: 'log4j', name: 'log4j', version: '1.2.17' //Gson: compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5' //Inject compile group: 'com.google.inject', name: 'guice', version: '4.2.3' //mockingbird-client compile group: 'mockingbird', name: 'mockingbird-client', version: '3.1-SNAPSHOT' compile group: 'commons-io', name: 'commons-io', version: '2.6' api group: 'com.ringcentral', name: 'ringcentral', version: '0.6.4'}
复制代码
使用 Guice 作为依赖注入在 junit 中使用 GuiceJUnit4Runner.java
package com.ringcentral.ltibackend;
import com.google.inject.Guice;import com.google.inject.Module;import com.google.inject.internal.ProviderMethodsModule;import org.junit.runners.BlockJUnit4ClassRunner;import org.junit.runners.model.InitializationError;
public class GuiceJUnit4Runner extends BlockJUnit4ClassRunner {
public GuiceJUnit4Runner(Class<?> klass) throws InitializationError { super(klass); }
@Override public Object createTest() throws Exception { Object object = super.createTest(); Module module = ProviderMethodsModule.forObject(object); Guice.createInjector(module).injectMembers(object); return object; }
}
复制代码
在测试中声明*Test.java
@RunWith(GuiceJUnit4Runner.class)public class VideoConfigTest { //todo}
复制代码
整体的框架结果如下:
上手写 case
1.使用 mock 让内部的第三方 api 返回期望的结果,通过 before,after 在测试前 mock,结束后清理掉 mock 的 api。
package com.*.*.core.api;import com.google.inject.Inject;import com.*.*.GuiceJUnit4Runner;import com.*.*.util.config.ApiConfig;import com.*.*.util.config.EnvConfig;import com.*.*.util.mock.services.MockRCServer;import io.restassured.RestAssured;import org.apache.http.HttpStatus;import org.junit.After;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import static org.hamcrest.Matchers.containsString;import static org.hamcrest.Matchers.lessThan;
@RunWith(GuiceJUnit4Runner.class)public class VideoConfigTest {
private static final Long TIME_OUT = 5000L;
@Inject private MockRCServer mockRCServer;
@Before public void setUp() { mockRCServer.mockSucessRCToken(); mockRCServer.mockVideoConfigurationReturnRCVideo(); }
@After public void teardown() { mockRCServer.getMockServer().deleteMockFor(); }
@Test public void videoConfigTestShouldBeCorrect() { RestAssured.useRelaxedHTTPSValidation(); RestAssured.given().header("x-api-key", ApiConfig.API_HEADER). when(). get(EnvConfig.LTI_SERVER_URL + ApiConfig.API_VIDEO_CONFIG). then(). assertThat(). statusCode(HttpStatus.SC_OK). and().assertThat().body(containsString("RCVideo")). and().time(lessThan(TIME_OUT)); }
}
复制代码
2.更好的断言 jsonschema,可以通过https://extendsclass.com/json-schema-validator.html生成 json 文件。将 json 文件放置在 resource 文件中。更多方法查看官网https://rest-assured.io/
public class UserInfoTest {private static final Long TIME_OUT = 5000L;
@Testpublic void userInfoTestShouldBeCorrect() { RestAssured.useRelaxedHTTPSValidation(); RestAssured.given().header("x-api-key", ApiConfig.API_HEADER). when(). get(EnvConfig.LTI_SERVER_URL + ApiConfig.API_USER_INFO). then(). assertThat(). statusCode(HttpStatus.SC_OK). and().time(lessThan(TIME_OUT)). and().assertThat().body(matchesJsonSchemaInClasspath("userInfo.json")). and().assertThat().body(containsString("\"brand\":\"rc\",\"extensionId\":\"2172406004\",\"meetingProvider\":\"RCVideo\""));}}
复制代码
更多问题欢迎探讨~
评论