在执行用例过程中,当失败的时候,需要自动截图,方便定位问题。
所以就要实现以下功能:
1、截图功能
/*
* 截图
*/
public void takeScreenShot() {
long date = System.currentTimeMillis();
String path = String.valueOf(date);
String curPath = System.getProperty("user.dir");
path = path + ".png";
String screenPath = curPath + "/" + path;
try {
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screen, new File(screenPath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2、监听器中加入失败监测,重写失败方法
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
LoginTest.getInstance().takeScreenShot();
}
最后执行整个代码如下:
package com.erp.selenium;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners({ TestngListenerScreenShot.class })
public class LoginTest {
public static WebDriver driver = new ChromeDriver(); //创建浏览器对象了
private LoginTest() {
}
private static LoginTest loginTest;
/*
*单例模式,保证在一个浏览器对象中执行*/
public static LoginTest getInstance() {
if (loginTest == null) {
loginTest = new LoginTest();
}
return loginTest;
}
/*
* 截图
*/
public void takeScreenShot() {
long date = System.currentTimeMillis();
String path = String.valueOf(date);
String curPath = System.getProperty("user.dir");
path = path + ".png";
String screenPath = curPath + "/" + path;
try {
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screen, new File(screenPath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void test1() {
LoginTest.getInstance().driver.get("http://www.baidu.com"); //此时已经存在浏览器对象,直接用存在的
driver.findElement(By.xpath("//f")).click();
System.out.println("test");
}
// public static void main(String[] args) {
// LoginTest lg = new LoginTest();
// lg.takeScreenShot();
// }
}
package com.erp.selenium;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
public class TestngListenerScreenShot extends TestListenerAdapter {
public LoginTest lt;
@Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
}
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
LoginTest.getInstance().takeScreenShot(); //失败截图,通过单例模式来执行,保证只有一个浏览器对象
}
@Override
public void onTestSkipped(ITestResult tr) {
super.onTestSkipped(tr);
}
@Override
public void onStart(ITestContext testContext) {
super.onStart(testContext);
}
@Override
public void onFinish(ITestContext testContext) {
super.onFinish(testContext);
}
}
问题:这么搞是有点复杂,需要重新优化下,把driver单独抽出来创建为class,让用例类和监听类都集成同一个driver。这样结构更加清晰。
更新后的代码结构如下:
封装好浏览器,保证用例之行时候,都调用一个浏览器对象。截图功能也放到里面。
package com.erp.selenium;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class BaseDriver {
public WebDriver driver;
public BaseDriver() {
driver= new ChromeDriver();
}
/*
* 截图
*/
public void takeScreenShot() {
long date = System.currentTimeMillis();
String path = String.valueOf(date);
String curPath = System.getProperty("user.dir");
path = path + ".png";
String screenPath = curPath + "/" + path;
try {
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screen, new File(screenPath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.erp.selenium;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import com.erp.page.BasePage;
import product.DriverBase;
public class TestngListenerScreenShot extends TestListenerAdapter {
public DriverBase driver;
@Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
}
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
this.takeScreenShot(tr);
}
private void takeScreenShot(ITestResult tr) {
BaseDriver b=(BaseDriver) tr.getInstance(); //这里的强转换,是因为logintest中的注解@listeners获取了logintest类对象,而logintest继承了basedriver,所以能实现强转换。
b.takeScreenShot(); //这里执行的是basedriver类中的方法takeScreenShot
}
@Override
public void onTestSkipped(ITestResult tr) {
super.onTestSkipped(tr);
}
@Override
public void onStart(ITestContext testContext) {
super.onStart(testContext);
}
@Override
public void onFinish(ITestContext testContext) {
super.onFinish(testContext);
}
}
执行case
package com.erp.selenium;
import org.openqa.selenium.By;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners({ TestngListenerScreenShot.class }) //监听器 用例执行过程中,满足class中的方法后,监听器中的方法就会被执行。比如这里,失败的时候,就会去执行截图了。
public class LoginTest extends BaseDriver{
@Test
public void test1() {
driver.get("http://jd.com");
driver.findElement(By.xpath("//f")).click();
System.out.println("test");
}
}