基于WebDriver&TestNG 实现自己的Annotation @TakeScreenshotOnFailure

相信用过Selenium WebDriver 的朋友都应该知道如何使用WebDriver API实现Take Screenshot的功能。

在这篇文章里,我主要来介绍对failed tests实现 take screenshot的功能, 并且我们也高大上一回,做成注解的形式。

 

效果如下:

 

目录
    前提
    Maven 配置
    Example
    简单类图
     TakeScreenshotOnFailure CustomTestListener WebDriverHost TestBase DemoListenerTest TestNG.xml Run as TestNG

  

前提

  • JDK 1.7
  • Maven 3

 

Maven 配置

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.9.5</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.46.0</version>
        </dependency>

 

Example

简单类图

 

首先创建一个类 如下 TakeScreenshotOnFailure.java

package test.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation informs CustomTestListener to take screenshot if test method fails. File name is method name + png suffix.
 * Test class must implement WebDriverHost in order for the screenshot to work.
 * 
 * @author wadexu
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value =
  {ElementType.METHOD})
public @interface TakeScreenshotOnFailure {
}

 ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4861024.html 

 

然后创建一个自己的CustomTestListener 继承TestNG 的 TestListenerAdapter 重写onTestFailure()方法, 加入take screenshot的功能

代码如下

package test.demo;

import java.io.File;
import java.lang.reflect.Method;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import org.testng.ITestResult;
import org.testng.TestListenerAdapter;

/**
* 
* @Description: A custom test listener extends TestListenerAdapter for take screen shot on failed test case.
* @author wadexu
*
* @updateUser
* @updateDate 
*/
public class CustomTestListener extends TestListenerAdapter {
    
    private static String fileSeperator = System.getProperty("file.separator");
    protected static final Logger logger = Logger.getLogger(CustomTestListener.class);

    @Override
    public void onTestFailure(ITestResult result) {
        super.onTestFailure(result);
        Object o = result.getInstance();
        WebDriver driver = ((WebDriverHost) o).getWebDriver();

        Method method = result.getMethod().getConstructorOrMethod().getMethod();
        TakeScreenshotOnFailure tsc = method.getAnnotation(TakeScreenshotOnFailure.class);

        if (tsc != null) {
            String testClassName = getTestClassName(result.getInstance().toString()).trim();

            String testMethodName = result.getName().toString().trim();
            String screenShotName = testMethodName + ".png";

            if (driver != null) {
                String imagePath =
                        ".." + fileSeperator + "Screenshots" + fileSeperator + "Results"
                                + fileSeperator + testClassName + fileSeperator
                                + takeScreenShot(driver, screenShotName, testClassName);
                logger.info("Screenshot can be found : " + imagePath);
            }
        }
    }

    /**
    * Get screen shot as a file and copy to a new target file
    * 
    * @Title: takeScreenShot
    * @param driver
    * @param screenShotName
    * @param testClassName
    * @return screenShotName
    */
    public static String takeScreenShot(WebDriver driver,
            String screenShotName, String testClassName) {
        try {
            File file = new File("Screenshots" + fileSeperator + "Results");
            if (!file.exists()) {
                logger.info("File created " + file);
                file.mkdir();
            }

            File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            File targetFile = new File("Screenshots" + fileSeperator + "Results" + fileSeperator + testClassName, screenShotName);
            FileUtils.copyFile(screenshotFile, targetFile);

            return screenShotName;
        } catch (Exception e) {
            logger.error("An exception occured while taking screenshot " + e.getCause());
            return null;
        }
    }

    /**
    * Get a test class name
    * 
    * @Title: getTestClassName
    * @param testName
    * @return testClassName
    */
    public String getTestClassName(String testName) {
        String[] reqTestClassname = testName.split("\\.");
        int i = reqTestClassname.length - 1;
        String testClassName = reqTestClassname[i].substring(0, reqTestClassname[i].indexOf("@"));
        logger.info("Required Test Name : " + testClassName);
        return testClassName;
    }

}

 

接口类 WebDriverHost 

package test.demo;

import org.openqa.selenium.WebDriver;

/**
 * Class implementing that interface is expected to return instance of web driver used in last test method.
 * 
 * @author wadexu
 */
public interface WebDriverHost {

  /**
   * Returns instance of web driver used in last test method.
   * 
   * @return WebDriver
   */
  public WebDriver getWebDriver();
}

 ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4861024.html 

 

测试基类TestBase

package test.demo;

import java.io.File;
import java.io.IOException;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;

/**
 * @Description: Abstract test base class, Test class must extends this class. 
 *               Initialize a firefox webDriver for tutorial purpose only. 
 * @author wadexu
 *
 * @updateUser
 * @updateDate
 */
public abstract class TestBase implements WebDriverHost{
    
    protected WebDriver webDriver = null;
    
    @Override
    public WebDriver getWebDriver() {
      return webDriver;
    }
    
    @BeforeClass
    public void setUp() throws IOException {
        FirefoxProfile firefoxProfile = new FirefoxProfile();
        // use proxy
        firefoxProfile.setPreference("network.proxy.type", 1);
        firefoxProfile.setPreference("network.proxy.http", "10.51.1.000");
        firefoxProfile.setPreference("network.proxy.http_port", "8080");

        //get rid of google analytics, otherwise it's too slow to access to cnblogs website
        firefoxProfile.addExtension(new File(getClass().getClassLoader().getResource("no_google_analytics-0.6-an+fx.xpi").getFile()));
        
        webDriver = new FirefoxDriver(firefoxProfile);
    }

    @AfterClass
    public void tearDown() {
        webDriver.close();
    }
    
}

 

DemoListenerTest 测试类

package test.demo;

import static org.testng.Assert.assertTrue;

import org.testng.annotations.Test;

/**
 * @Description: Demo a Test using custom Test Listener with an annotation TakeScreenshotOnFailure
 * @author wadexu
 * 
 * @updateUser
 * @updateDate
 */
public class DemoListenerTest extends TestBase{

    @Test
    @TakeScreenshotOnFailure
    public void testFail() {
        webDriver.get("http://www.cnblogs.com/");
        
        //Fail this test method for tutorial purpose only
        assertTrue(false);
    }

}

 

TestNG 的 xml 文件 配置如下,加入listener监听

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<!--<suite name="DMP_Test_Suite" -->
<suite name="Demo_Test_Suite" parallel="false">
    <listeners>
        <listener class-name="test.demo.CustomTestListener" />
    </listeners>
    <test name="Demo_Test">
        <classes>
            <class name="test.demo.DemoListenerTest" />
        </classes>
    </test> 
</suite>

 ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4861024.html 

 

Run as TestNG

断言故意错误 让test fail

 

控制台输出

2015-10-08 15:04:29,896 INFO [test.demo.CustomTestListener] - Required Test Name : DemoListenerTest
2015-10-08 15:04:31,985 INFO [test.demo.CustomTestListener] - Screenshot can be found : ..\Screenshots\Results\DemoListenerTest\testFail.png

 

图片以测试方法命名, 存在含类名的路径下

 

测试方法Pass 或者 fail但没加Annotation 都不会截屏。

 

 

感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。

##转载注明出处: http://www.cnblogs.com/wade-xu/p/4861024.html 

 

posted @ 2015-10-09 09:07  WadeXu  阅读(1653)  评论(0编辑  收藏  举报