您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 > TestNG
如何利用TestNG監(jiān)聽(tīng)器優(yōu)化測(cè)試報(bào)告?
作者:runtime_ 發(fā)布時(shí)間:[ 2016/10/18 15:47:52 ] 推薦標(biāo)簽:單元測(cè)試工具 TestNG

  今年四月底我花了時(shí)間簡(jiǎn)單搭建了php接口測(cè)試工程,maven + testng + jenkins,從0開(kāi)始到現(xiàn)在510個(gè)用例(持續(xù)增長(zhǎng)中),逐漸開(kāi)始提高了測(cè)試回歸效率并發(fā)現(xiàn)一些線上問(wèn)題,這期間遇到過(guò)不少問(wèn)題,這次先分享下如何利用testng監(jiān)聽(tīng)器優(yōu)化測(cè)試報(bào)告。
  一、給工程添加失敗重試機(jī)制
  接口用例量上來(lái)以后,我們遇到的第一個(gè)問(wèn)題是http方式調(diào)用php接口會(huì)有部分接口偶爾不穩(wěn)定或者超時(shí)的情況,但第二次運(yùn)行又正常,每次接口失敗都需要花費(fèi)時(shí)間排查,但實(shí)際沒(méi)有問(wèn)題,為了排除不穩(wěn)定帶來(lái)的干擾,給大家節(jié)約排查維護(hù)時(shí)間,首先需要解決的是給工程添加失敗自動(dòng)重試機(jī)制。
  目前我的做法是實(shí)現(xiàn)了testng自帶的IRetryAnalyzer接口,定義了一個(gè)MAX _ RETRY_COUNT,即大重試次數(shù),實(shí)現(xiàn)的retry方法非常簡(jiǎn)單,如下:
public boolean retry(ITestResult result) {
if (retryCount < MAX_RETRY_COUNT) {
retryCount++;
return true;
}
return false;
}
  如果團(tuán)隊(duì)有人想要使用失敗重試的功能也很簡(jiǎn)單,只需要在Annotation里面加上retryAnalyzer屬性即可,如下:
@Test(retryAnalyzer = TestRetry.class)
public void summaryTest(){
String url = urlList.get(0);
JSONObject map = ResponseJsonBase.manageJson(url, "");
String total = map.getString("total");
assert "7.59".equals(total) : url;
}
  這種方式帶來(lái)的好處是有比較大的自由度,可以自由選擇某個(gè)用例是否需要失敗重試的功能,因?yàn)椴糠纸涌谥卦嚨诙问遣辉试S的,比如分銷(xiāo)的關(guān)注接口(有頻率限制等)。 但是僅僅到這里還是會(huì)有問(wèn)題,首先會(huì)發(fā)現(xiàn)我們的接口測(cè)試報(bào)告有問(wèn)題,其次會(huì)發(fā)現(xiàn)失敗重試后通過(guò)的情況下,依然會(huì)有郵件提醒,我們還是需要花費(fèi)很多時(shí)間看接口問(wèn)題。在這里,我為了復(fù)現(xiàn)當(dāng)時(shí)遇到的問(wèn)題,隨便造了一個(gè)有問(wèn)題的接口測(cè)試報(bào)告:

  二、通過(guò)定義一個(gè)監(jiān)聽(tīng)器優(yōu)化測(cè)試報(bào)告
  根據(jù)遇到的問(wèn)題,首先我們需要優(yōu)化一下測(cè)試報(bào)告,從而避免給大家?guī)?lái)太多干擾。 我的做法是定義了一個(gè)testng的監(jiān)聽(tīng)器來(lái)處理失敗重試的用例。具體實(shí)現(xiàn)是通過(guò)繼承TestListenerAdapter類(lèi),覆蓋onTestFailure、 onStart、 onFinish方法,貼一下主要的代碼段:
@Override
public void onTestFailure(ITestResult tr) {
if (tr.getMethod().getRetryAnalyzer() == null) {
log(tr.getMethod() + "--Test method failed ");
}
if (tr.getMethod().getRetryAnalyzer() != null) {
TestRetry testRetry = (TestRetry)       tr.getMethod().getRetryAnalyzer();
if (testRetry.getRetryCount() < testRetry.getMaxRetryCount()) {
tr.setStatus(ITestResult.SKIP);
Reporter.setCurrentTestResult(null);
isRemoveSkipNeeded = true;
skippedCases.addResult(tr, tr.getMethod());
}
else {
failedCases.addResult(tr, tr.getMethod());
isRetryNeeded = true;
}
}
}
  其實(shí)上面代碼里面是統(tǒng)一對(duì)失敗的用例做處理,每次失敗都會(huì)去判斷是否已經(jīng)達(dá)到大失敗次數(shù),如果沒(méi)有,會(huì)將該用例狀態(tài)設(shè)置為skip,到這里為止,看我們的測(cè)試報(bào)告,大概長(zhǎng)這樣:

  可以看到,依然有很明顯的問(wèn)題,我們還需要做的事情是:失敗的用例列表去重,以及在Skipped的testcase里面剔除真正Failed的Test Case。 其實(shí)測(cè)試報(bào)告的主要數(shù)據(jù)獲取是下面幾個(gè):
  getFailedConfigurations()
  getSkippedConfigurations()
  getFailedTests()
  getSkippedTests()
  做對(duì)應(yīng)優(yōu)化很簡(jiǎn)單了,貼下我這邊f(xié)ailed Cases去重的代碼段,可以舉一反三寫(xiě)其他幾個(gè):
private void removeFailedTestsInTestNG(ITestContext test) {
IResultMap returnValue = test.getFailedTests();
for (ITestResult resultToCheck : failedCases.getAllResults()) {
int c = 0;
for (ITestResult result : returnValue.getAllResults()) {
if (result.getMethod().equals(resultToCheck.getMethod())) {
c++;
if (c > 1) {
returnValue.removeResult(result.getMethod());
test.getFailedConfigurations().removeResult(
result.getMethod());
}
}
}
}
}
  然后是在每個(gè)testSuit運(yùn)行結(jié)束的時(shí)候,統(tǒng)一處理:
@Override
public void onFinish(final ITestContext testContext) {
if(isRetryNeeded){
removeIncorrectlySkippedTests(testContext,failedCases);
removeFailedTestsInTestNG(testContext);
}
else{
if(isRemoveSkipNeeded)
removeSkippedTestsInTestNG(testContext);
else{
skippedCases= testContext.getSkippedTests();
failedCases= testContext.getFailedTests();
}
}
}

上一頁(yè)12下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd