前言
最近公司開始有后端的項(xiàng)目倒戏,必不可免的需要針對這些后端API進(jìn)行測試。隨著測試技術(shù)的突飛猛進(jìn)恐似,越來越多的人喜歡造輪子杜跷。面對如此多的框架該如何選型呢。
框架選型
在眾多的框架里面矫夷,耳熟能詳?shù)母鹈疲琾ostman,RF, JMeter双藕,rest-assured淑趾,HTTPrunner....
對于框架的選型,個人的觀點(diǎn)忧陪,怎么簡單怎么來吧扣泊。
- 框架是否能較好的支持
- 框架維護(hù)成本
- 團(tuán)隊(duì)成員學(xué)習(xí)成本
我的方案 Junit + Rest-Assured, 原因如下:
*后端項(xiàng)目采用Gradle,Rest-Assured可以快速度集成嘶摊,在后續(xù)的CI中較友好延蟹,統(tǒng)一的倉庫,編譯執(zhí)行命令叶堆。
*團(tuán)隊(duì)采用Juint做UT/IT阱飘,學(xué)習(xí)成本較低。
*現(xiàn)有的mock server client虱颗,可以使用Gradle集成
*Rest-Assured對restful的支持友好沥匈,提供良好的斷言,given-when-then與現(xiàn)有的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
}
整體的框架結(jié)果如下:
上手寫case
1.使用mock讓內(nèi)部的第三方api返回期望的結(jié)果高帖,通過before,after在測試前mock辨萍,結(jié)束后清理掉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文件中爪飘。更多方法查看官網(wǎng)
https://rest-assured.io/
public class UserInfoTest {
private static final Long TIME_OUT = 5000L;
@Test
public 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\""));
}
}
更多問題歡迎探討~