自動(dòng)化跑用例,必須要有結(jié)果展示捎废,才能知道腳本跑測(cè)的情況笑窜,而我使用的是Appium+TestNG+java來(lái)寫(xiě)腳本,而截圖尤為重要登疗,腳本pass倒沒(méi)事排截,若是fail,那怎么辦辐益?所以断傲,我們需要一個(gè)腳本跑fail了就自動(dòng)截圖的功能。那么問(wèn)題來(lái)了智政,這個(gè)組合认罩,默認(rèn)情況下,并沒(méi)有截圖功能续捂,那么我們就需要自己寫(xiě)一個(gè)截圖的功能垦垂。
經(jīng)過(guò)查找資料,了解到牙瓢,TestNG作為測(cè)試框架劫拗,有多個(gè)監(jiān)聽(tīng)器接口和類(lèi),這里我們需要用到的是ITestListener接口矾克,只需要注冊(cè)就可以監(jiān)聽(tīng)腳本页慷,
如何實(shí)現(xiàn)監(jiān)聽(tīng)器類(lèi)?
其方法有如下
onFinish(ITestContext arg0)
onStart(ITestContext arg0)
onTestFailedButWithinSuccessPercentage(ITestResult arg0)
onTestFailure(ITestResult result)
onTestSkipped(ITestResult arg0)
onTestStart(ITestResult arg0)
onTestSuccess(ITestResult arg0)
詞即義聂渊,方法什么意思看詞語(yǔ)就知道差购,此處,我們需要的是用例失敗即自動(dòng)截圖功能汉嗽,那我們把截圖功能放到onTestFailure(ITestResult result)方法下欲逃,那么我們需要先建一個(gè)類(lèi),我們就叫它ScreenshotListener吧饼暑,然后把這個(gè)類(lèi)實(shí)現(xiàn)ITestListener接口稳析,即
public class ScreenshotListener implements ITestListener
onTestFailure方法代碼如下
public void onTestFailure(ITestResult result)
{
// 跑fail則截圖
// 獲取屏幕截圖
File srcFile = (driver).getScreenshotAs(OutputType.FILE);
// System.out.println(srcFile.getAbsolutePath().toString());
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_hhmmss");
File location = new File("screenshots");
String dest = result.getMethod().getRealClass().getSimpleName() + "." + result.getMethod().getMethodName();
File targetFile =
new File(location.getAbsolutePath() + File.separator + dest + "_" + dateFormat.format(new Date()) + ".png");
System.out.println("截圖位置:");
System.out.println("----------------- file is " + targetFile.getPath());
try
{
FileUtils.copyFile(srcFile, targetFile);
}
catch (IOException e)
{
e.printStackTrace();
}
}
怎么用監(jiān)聽(tīng)器?
此處弓叛,我只實(shí)現(xiàn)了用例失敗自動(dòng)監(jiān)聽(tīng)截圖監(jiān)聽(tīng)器類(lèi)彰居,那么怎么用呢?我用的方法是在腳本類(lèi)前面加入一個(gè)注解撰筷,代碼如下
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidKeyCode;
@Listeners({ScreenshotListener.class}) //此處需要寫(xiě)入監(jiān)聽(tīng)器注解
public class Display
{
private AndroidDriver driver;
AppiumUtil appiumUtil = new AppiumUtil();
/**
* 1.屏幕上方跳出亮度條調(diào)節(jié)框
* 2.亮度條調(diào)節(jié)框消失
*/
@Test
public void brightnessLevel_003()
{
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
WebElement webElement = driver.findElementByAndroidUIAutomator(appiumUtil.scrollTo("Display", AppiumUtil.NAME));
webElement.click();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
webElement = driver.findElementByName("Brightness level");
webElement.click();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
driver.pressKeyCode(AndroidKeyCode.BACK);
}
/**
* step
1.點(diǎn)擊進(jìn)入設(shè)置 --> 顯示 --> 壁紙陈惰,觀察界面
result
1.界面顯示動(dòng)態(tài)壁紙、壁紙毕籽、谷歌相冊(cè)
*/
@Test
public void enterWallpaper_012()
{
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
WebElement webElement = driver.findElementByName("Wallpaper");
webElement.click();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
}
@BeforeTest
public void beforeTest()
throws Exception
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", "Android Devices");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", "7.0");
capabilities.setCapability("udid", "HKL3XDH8");
capabilities.setCapability("automationName", "Uiautomator2");
capabilities.setCapability("appPackage", "com.android.settings");
capabilities.setCapability("appActivity", ".Settings");
capabilities.setCapability("NoReset", true);
driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
ScreenshotListener.driver = driver; //此處需要把driver傳入給監(jiān)聽(tīng)器抬闯,否則監(jiān)聽(tīng)器使用driver的時(shí)候井辆,會(huì)拋空指針
System.out.println("啟動(dòng)應(yīng)用!");
}
@AfterTest
public void afterTest()
{
driver.quit();
System.out.println("退出driver溶握!");
}
}
然后試跑一下杯缺,我刻意把用例跑失敗,得出如下睡榆,圖片好像上傳不了萍肆,稍后傳上
總結(jié),自動(dòng)化跑腳本失敗時(shí)胀屿,可以通過(guò)添加監(jiān)聽(tīng)器類(lèi)塘揣,實(shí)現(xiàn)自動(dòng)截圖功能,監(jiān)聽(tīng)器類(lèi)的實(shí)現(xiàn)方法和如何使用監(jiān)聽(tīng)器類(lèi)以上有提到宿崭。
疑問(wèn):注冊(cè)監(jiān)聽(tīng)器的另外一種方式勿负,也可以在testng.xml文件添加監(jiān)聽(tīng)器,我的如下
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<listeners>
<listener class-name="com.hq.prodreamer.DisplayTest.ScreenshotListener" />
</listeners>
<test name="Display">
<classes>
<class name="com.hq.prodreamer.DisplayTest.Display"/>
</classes>
<listeners>
//這是你需要加的東西
<listener class-name="org.uncommons.reportng.HTMLReporter" />
<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
</listeners>
</test> <!-- Test -->
</suite> <!-- Suite -->
不知為何劳曹,我在testng.xml注冊(cè)監(jiān)聽(tīng)器,也沒(méi)有監(jiān)聽(tīng)成功琅摩?而需要在腳本類(lèi)前面添加監(jiān)聽(tīng)器注釋?zhuān)坑卸拇笊窨梢灾笇?dǎo)一下铁孵。
接上。
終于知道為何在testng.xml注冊(cè)監(jiān)聽(tīng)器沒(méi)有監(jiān)聽(tīng)成功了房资,上面的com.hq.prodreamer.DisplayTest.ScreenshotListener監(jiān)聽(tīng)器沒(méi)有寫(xiě)進(jìn)<test>...</test>里面蜕劝,故沒(méi)有監(jiān)聽(tīng)到Display類(lèi)的情況,所以我們要把監(jiān)聽(tīng)器同樣像reportng一樣寫(xiě)進(jìn)去轰异,代碼如下
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="Display">
<classes>
<class name="com.hq.prodreamer.DisplayTest.Display"/>
</classes>
<listeners>
//這是你需要加的東西
<listener class-name="org.uncommons.reportng.HTMLReporter" />
<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
<listener class-name="com.hq.prodreamer.DisplayTest.ScreenshotListener" />
</listeners>
</test> <!-- Test -->
</suite> <!-- Suite -->