服務(wù)端的測(cè)試,大多數(shù)內(nèi)容都圍繞著接口展開。對(duì)于接口測(cè)試,無非也是功能、自動(dòng)化、性能測(cè)試為主,偶然想到一個(gè)問題,如果能寫一個(gè)用例,在功能、自動(dòng)化、性能三者的測(cè)試場(chǎng)景中重復(fù)使用,肯定能省去非常多的時(shí)間。
總體思路跟之前的接口和性能框架一樣,通過總的測(cè)試項(xiàng)目中把接口功能封裝好,留出來測(cè)試參數(shù)。功能測(cè)試就寫方法調(diào)用然后人肉檢查,自動(dòng)化的話把接口響應(yīng)拿出來,然后驗(yàn)證各種數(shù)據(jù),性能直接使用性能框架直接調(diào)用該方法即可。
花了點(diǎn)時(shí)間,做了一個(gè)Demo,分享給大家。
這是一個(gè)簡(jiǎn)易的接口請(qǐng)求方法,其中main方法里面是功能測(cè)試執(zhí)行代碼,用例是文檔形式,這里就不寫了:
public class Headgear extends NajmBase {
public Headgear(NajmBase najmBase) {
this.loginKey = najmBase.loginKey;
this.args = najmBase.args;
this.user_id = najmBase.user_id;
}
private static NajmBase base = NajmBase.getBase(0);
public static Headgear drive = new Headgear(base);
/**
* 當(dāng)前正在使用的頭套
*/
public int usingHeadgearId;
// public JSONObject headgearInfo = new JSONObject();
public Map<Integer, Long> headgearInfo = new HashMap<>();
public static void main(String[] args) {
// NajmBase.getUserBalance(base.user_id);
// int type = 1, id = 36, packageId = 60, num = 1, price = 1;
// NajmBase base1 = new NajmBase(V580User.getUserName(0));
// Headgear headgear = new Headgear();
// headgear.switchHeadgear(34);
// output(headgear.getHeadgearInfo());
// output(headgear.getUsingHeadgearId());
// output(base1.loginResponse);
// drive.getAllHeadgear();
// new MallBase(base).buy(type, id, packageId, num, price);
// drive.getUserHeadgearInfo();
// NajmBase.getUserBalance(base.user_id);
// drive.getUserHeadgearInfo();
// drive.getOnsaleHeadgear();
int times = 0;
while (true) {
times++;
int type = 1, id = getRandomInt(2) == 1 ? 34 : 36, packageId = id == 34 ? 56 : 60, num = 1, price = 1;
long deadtime1 = drive.getHeadgearInfo().get(id);
Verify verify = new Verify(new MallBase(base).buy(type, id, packageId, num, price));
drive.getUserHeadgearInfo();
long deadtime2 = drive.getHeadgearInfo().get(id);
if (deadtime2 - deadtime1 != DAY) break;
}
output("一共進(jìn)行了:" + times);
// output(drive.getHeadgearInfo());
// output(drive.usingHeadgear);
// output(drive.loginKey);
// output(drive.args);
// output(base.loginResponse.getJSONObject(DATAINFO).getJSONObject("headGear").getInt("id"));
testOver();
}
/**
* 獲取所有頭套信息,包括下架的
*
* @return
*/
public JSONObject getAllHeadgear() {
String url = HOST + HeadgearApiPath.GET_ALL_HEADGEAR;
HttpGet httpGet = getHttpGet(url);
JSONObject response = getHttpResponseEntityByJson(httpGet);
output(response);
return response;
}
/**
* 用戶切換頭套接口
*
* @param hid
* @return
*/
public JSONObject switchHeadgear(int hid) {
String url = HOST + HeadgearApiPath.SWITCH_HEADGEAR + hid + changeJsonToArguments(args);
HttpPost httpPost = getHttpPost(url);
JSONObject response = getHttpResponseEntityByJson(httpPost);
// output(response);
return response;
}
/**
* 獲取用戶頭套信息
*
* @return
*/
public JSONObject getUserHeadgearInfo() {
sleep(1);
String url = HOST + HeadgearApiPath.GET_USER_HEADGEAR;
JSONObject response = getHttpResponseEntityByJson(getHttpGet(url, args));
output(response);
if (isRightResponse(response)) {
headgearInfo.clear();
JSONArray jsonArray = response.getJSONArray(DATAINFO);
jsonArray.forEach(json -> {
JSONObject jsonObject = JSONObject.fromObject(json.toString()) ;
String name = jsonObject.getString("name") ;
long deadTime = jsonObject.getLong("deadlineTime") ;
int headgearId = jsonObject.getInt("goodId") ;
int use = jsonObject.getInt("isUse") ;
if (use == 1) usingHeadgearId = headgearId;
headgearInfo.put(headgearId, deadTime);
output(name, headgearId, getTimeByTimestamp(deadTime));
} );
}
return response;
}
/**
* 獲取在售的頭套的列表
*
* @return
*/
public JSONObject getOnsaleHeadgear() {
String url = HOST + HeadgearApiPath.GET_ONSALE_HEADGEAR;
JSONObject response = getHttpResponseEntityByJson(getHttpGet(url, args));
output(response);
return response;
}
public int getUsingHeadgearId() {
getUserHeadgearInfo();
return usingHeadgearId;
}
public Map<Integer, Long> getHeadgearInfo() {
getUserHeadgearInfo();
return headgearInfo;
}
}
下面是基于該功能的自動(dòng)化測(cè)試用例,main方法里面是調(diào)試用例的過程,執(zhí)行用例的方法在之前的文章寫過,利用反射去記錄用例信息和執(zhí)行測(cè)試用例,并保存測(cè)試結(jié)果,輸出測(cè)試報(bào)告,異常預(yù)警等等:
/**
* 用戶0-10
*/
public class HeadgearCase extends SourceCode {
static HeadgearCase headgearCase = new HeadgearCase();
static NajmBase base = new NajmBase(V580User.getUserName(0));
static Headgear drive = new Headgear(base);
public static void main(String[] args) {
// headgearCase.testDemo001();
// headgearCase.testDemo002();
// headgearCase.testDemo003();
// headgearCase.testDemo004();
headgearCase.testDemo005();
// headgearCase.testDemo006();
ApiLibrary.testOver();
}
/**
* 獲取所有頭套信息用例
*/
public void testDemo001() {
String label = "獲取所有頭套信息用例" + TAB + Thread.currentThread().getStackTrace()[1];
Verify verify = new Verify(drive.getAllHeadgear());
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為0", verify.isRight());
result.put("包含數(shù)組", verify.isArray("heads"));
result.put("包含已下架的頭套", verify.isContains("自動(dòng)化專用3"));
result.put("包含正在出售的頭套", verify.isContains("自動(dòng)化專用1"));
MySqlTest.saveTestResult(label, result);
}
/**
* 獲取在售的頭套用例
*/
public void testDemo002() {
String label = "獲取在售的頭套用例" + TAB + Thread.currentThread().getStackTrace()[1];
Verify verify = new Verify(drive.getOnsaleHeadgear());
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為0", verify.isRight());
result.put("包含數(shù)組", verify.isArray("dataInfo"));
result.put("不包含已下架的頭套", !verify.isContains("自動(dòng)化專用3"));
result.put("包含正在出售的頭套", verify.isContains("自動(dòng)化專用1"));
result.put("包含描述信息", verify.isContains("測(cè)試10天"));
MySqlTest.saveTestResult(label, result);
}
/**
* 獲取用戶頭套信息用例
*/
public void testDemo003() {
String label = "獲取用戶頭套信息用例" + TAB + Thread.currentThread().getStackTrace()[1];
Verify verify = new Verify(drive.getUserHeadgearInfo());
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為0", verify.isRight());
result.put("用戶頭套正常", verify.isContains("自動(dòng)化專用1"));
result.put("用戶佩戴正常", verify.isContains("\"isUse\":1"));
result.put("頭套套餐正常", verify.isContains("測(cè)試1天"));
MySqlTest.saveTestResult(label, result);
}
/**
* 余額不足購(gòu)買用例
*/
public void testDemo004() {
String label = "余額不足購(gòu)買用例" + TAB + Thread.currentThread().getStackTrace()[1];
NajmBase base = new NajmBase(V580User.getUserName(1));
int type = 1, id = 36, packageId = 60, num = 1, price = 1;
Verify verify = new Verify(new MallBase(base).buy(type, id, packageId, num, price));
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為35", 35 == verify.getCode());
MySqlTest.saveTestResult(label, result);
}
/**
* 正常購(gòu)買用例
*/
public void testDemo005() {
String label = "正常購(gòu)買用例" + TAB + Thread.currentThread().getStackTrace()[1];
int type = 1, id = getRandomInt(2) == 1 ? 34 : 36, packageId = id == 34 ? 56 : 60, num = 1, price = 1;
int balance = NajmBase.getUserBalance(drive.user_id);
long deadtime1 = drive.getHeadgearInfo().get(id);
Verify verify = new Verify(new MallBase(base).buy(type, id, packageId, num, price));
drive.getUserHeadgearInfo();
long deadtime2 = drive.getHeadgearInfo().get(id);
int balance1 = NajmBase.getUserBalance(drive.user_id);
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為0", verify.isRight());
result.put("截止日期正確", (deadtime2 + EMPTY).equals(verify.getValue("deadlineTime")));
result.put("頭套日期增加正常", deadtime2 - deadtime1 == DAY);
result.put("用戶余額減少正常", balance - balance1 == 1);
MySqlTest.saveTestResult(label, result);
}
/**
* 用戶切換頭套用例
*/
public void testDemo006() {
String label = "用戶切換頭套用例" + TAB + Thread.currentThread().getStackTrace()[1];
drive.getAllHeadgear();
int id1 = drive.getUsingHeadgearId() == 34 ? 36 : 34;
Verify verify = new Verify(drive.switchHeadgear(id1));
int id2 = drive.getUsingHeadgearId();
JSONObject result = new JSONObject();
result.put("狀態(tài)碼為0", verify.isRight());
result.put("頭套切換成功", id1 == id2);
MySqlTest.saveTestResult(label, result);
}
}
下面是一個(gè)針對(duì)其中某個(gè)功能的性能測(cè)試用例(測(cè)試用例分兩種,一類是HTTP單次請(qǐng)求的,我才用了獲取請(qǐng)求的HttpRequestBase對(duì)象然后去重新發(fā)送并發(fā)請(qǐng)求,一類是多接口或者非HTTP請(qǐng)求,如dubbo,mysql,redis,消息隊(duì)列等等,直接調(diào)用的方法進(jìn)行壓測(cè)):
簡(jiǎn)單HTTP請(qǐng)求:
class CancelReason extends OkayBase{
public static void main(String[] args) {
def argsUtil = new ArgsUtil(args)
def thread = argsUtil.getIntOrdefault(0, 2)
def times = argsUtil.getIntOrdefault(1, 5)
def base = getBase()
Headgear drive = new Headgear(base);
drive.getAllHeadgear()
def request = FanLibrary.getLastRequest()
def timesthread = new RequestThreadTimes(request, times)
new Concurrent(timesthread, thread,"獲取所有頭套,內(nèi)容流轉(zhuǎn)二期壓測(cè)接口").start()
allOver()
}
}
非簡(jiǎn)單HTTP請(qǐng)求的請(qǐng)參考之前寫過的性能測(cè)試框架Demo:性能測(cè)試框架第二版。這類方法寫起來比較簡(jiǎn)單,使用范圍很高,但是需要根據(jù)不同的業(yè)務(wù)需求解決多線程數(shù)據(jù)和對(duì)象的安全問題。
整個(gè)項(xiàng)目放在git上,功能測(cè)試在本地,自動(dòng)化項(xiàng)目和性能項(xiàng)目在服務(wù)器,采用Groovy腳本運(yùn)行,也可以在本地調(diào)試。自動(dòng)化項(xiàng)目采取定時(shí)或者間隔固定時(shí)間自動(dòng)運(yùn)行,性能項(xiàng)目收到輸入命令groovy filename.groovy來運(yùn)行。
- 鄭重聲明:文章首發(fā)于公眾號(hào)“FunTester”,禁止第三方(騰訊云除外)轉(zhuǎn)載、發(fā)表。
技術(shù)類文章精選
- java一行代碼打印心形
- Linux性能監(jiān)控軟件netdata中文漢化版
- 性能測(cè)試框架第二版
- 如何在Linux命令行界面愉快進(jìn)行性能測(cè)試
- 圖解HTTP腦圖
- 將swagger文檔自動(dòng)變成測(cè)試代碼
- 五行代碼構(gòu)建靜態(tài)博客
- 基于java的直線型接口測(cè)試框架初探
- Selenium 4.0 Alpha更新日志
- Selenium 4.0 Alpha更新實(shí)踐