哈哈哈,很久没写博客了,懒了。
因为一些原因最近需要把监听事件重新整理一下,开始没细想,直接copy网上的,其实结果发现报错很多,或者是达不到效果,然后把之前的代码翻出来,仔细看了一下。下面给一些需要的小伙伴整理一下思路:
1、首先我们用到的是testng里面的监听,所以这个毋庸置疑
2、我们需要重新他的监听事件
3、用例中肯定需要加入监听事件
这三点是网上公认的,但是怎么做确没有说明白。
首先看一下我的目录结构:
图片中我有4个类,
1、driverBase是一个基类,里面是driver的初始化,截图的方法也在里面。
2、selectDriver是根据浏览器不同返回不同的driver
3、testngListenerScreen是testng的监听类,他继承了TestListenerAdapter类,把里面的方法进行了重写。主要他会去监听你测试类是否报错,如果报错他就会去调用我们driverbase下面的截图方法。
4、testlogin 不用说,我们的测试类,他需要继承我们的driverBase基类,去拿里面的driver。
这个说完了先看代码,首先从我们基类开始:
package com.mushishi.selenium.base; import java.io.File; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; /** * @author mushishi * */ public class driverBase { public WebDriver driver; /** * 获取driver * */ public WebDriver getDriver() { return driver; } /** * 自动截图 * */ public void takeScreenShot() { SimpleDateFormat sf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); String dateStr = sf.format(date);
//上面几行代码的意思都是获取时间,并且格式化,用来作为图片的名称
//下面这个是获取当前运行的类名称和时间的组合一起命名图片 String path = this.getClass().getSimpleName() + "_" + dateStr + ".png";
//因为我们截图是需要用到driver的,所以这里需要获取driver,这个driver是获取的当前对象的driver takeScreenShot((TakesScreenshot) this.getDriver(), path); } /** * 传入参数截图 * */ public void takeScreenShot(TakesScreenshot drivername, String path) { String currentPath = System.getProperty("user.dir"); // get current work File scrFile = drivername.getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(scrFile, new File(currentPath + "\\" + path)); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("截图成功"); } } }
上面的代码,可能有那么一两个地方看不懂,都没关系,我写备注了。主要是以类名字和时间组合起来命名,并且把当前运行的对象的driver获取到,用来截图操作。
下面看selectDriver的类:
package com.mushishi.selenium.base; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; public class SelectDriver { public WebDriver driverName(String browser){ if(browser.equalsIgnoreCase("fireFox")){
//设置环境变量,并且返回driver System.setProperty("webdriver.firefox.marionette","D:\\java\\geckodriver\\geckodriver-v0.14.0-win64\\geckodriver.exe"); return new FirefoxDriver(); }else{ System.setProperty("webdriver.chrome.driver", "D:\\java\\chromedriver_win32\\chromedriver.exe"); return new ChromeDriver(); } } }
上面的没什么可看的,就是根据传入的对象生成一个driver,这个我用的3.0的selenium,所以需要这么设置。这个根据自己情况。
下面看监听类的: 1 package com.mushishi.selenium.base;
import org.testng.ITestContext; import org.testng.ITestResult; import org.testng.TestListenerAdapter; public class TestNGListenerScreen extends TestListenerAdapter{ @Override public void onTestSuccess(ITestResult tr) { super.onTestSuccess(tr); }
//主要是用到这个方法了,当你报错时他会监听到,然后就会执行截图操作,这里的 ITestresult tr是testng里的,获取到的是当前运行对象,你这样理解,他就是
//我当前运行的类这个对象 @Override public void onTestFailure(ITestResult tr) { super.onTestFailure(tr); System.out.println(tr); takeScreenShot(tr); }
//所以这里我执行截图的时候就获取到了我运行过程中实力对象的driver了,懂了吧。所以当我再回去调用我基类的对象时,那么driver就是同一个了 private void takeScreenShot(ITestResult tr) { driverBase b = (driverBase) tr.getInstance(); // driver = b.driver; b.takeScreenShot(); } @Override public void onTestSkipped(ITestResult tr) { super.onTestSkipped(tr); } @Override public void onTestStart(ITestResult result) { super.onTestStart(result); } @Override public void onStart(ITestContext testContext) { super.onStart(testContext); } @Override public void onFinish(ITestContext testContext) { super.onFinish(testContext); } }
最后一个类,测试类:
package com.mushishi.selenium.testCase; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import com.mushishi.selenium.ProUtil; import com.mushishi.selenium.base.SelectDriver; import com.mushishi.selenium.base.TestNGListenerScreen; import com.mushishi.selenium.base.driverBase; @Listeners({ TestNGListenerScreen.class }) public class testLogin extends driverBase { SelectDriver select = new SelectDriver(); public testLogin(){ if(driver == null){ driver = select.driverName("chrome"); } } public void loginScript(String username,String userpass) throws Exception{ String url = "http://www.imooc.com"; driver.get(url); driver.manage().window().maximize(); driver.findElement(By.id("js-signin-btn")).click(); Thread.sleep(2000); WebElement user = this.element(this.byStr("username")); user.isDisplayed(); WebElement password = this.element(this.byStr("userpass")); password.isDisplayed(); WebElement loginButton = this.element(this.byStr("loginbutton")); loginButton.isDisplayed(); user.sendKeys(username); password.sendKeys(userpass); loginButton.click(); Thread.sleep(3000); WebElement header = this.element(this.byStr("header")); header.isDisplayed(); Actions actions = new Actions(driver); actions.moveToElement(header).perform(); String userInfo = this.element(this.byStr("nameInfo")).getText(); System.out.println(userInfo); if(userInfo.equals("xxxx")){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } driver.close(); } /** * 封装By by * */ public By byStr(String username){ ProUtil properties = new ProUtil("element.properties"); String locator = properties.getPro(username); String locatorType = locator.split(">")[0]; String locatorValue = locator.split(">")[1]; if(locatorType.equals("id")){ return By.id(locatorValue); }else if(locatorType.equals("name")){ return By.name(locatorValue); }else if(locatorType.equals("className")){ return By.className(locatorValue); }else{ return By.xpath(locatorValue); } } /** * 封装Element * */ public WebElement element(By by){ WebElement ele = driver.findElement(by); return ele; } @Test public void loginpage() throws Exception{ this.loginScript("xxxx", "xxxx"); } }
这个是测试类,不知道你懂了么?因为我很多都封装了的,所以看不到,但是不影响大家理解testng自动截图思想。动手操作吧。