如何从TestNG IInvokedMethodListener获得测试字段?

时间:2013-05-20 06:50:56

标签: java webdriver integration-testing screenshot testng

我正在使用TestNG 6.8 + Selenium WebDriver 2.32来测试Web应用程序的GUI。在测试失败的情况下,我想截取应用程序GUI的屏幕截图。

我有什么:

  • 我可以通过实现testng的IInvokedMethodListener
  • 来检测测试失败
  • 我也知道如何使用webdriver截取屏幕截图

我需要什么:

  • 获取我在AbstractGuiTest类中声明的WebDriver实例以截取屏幕截图。

这是我的代码的骨架:

import org.testng.annotations.Listeners;
...
@Listeners(GuiTestListener.class)
public abstract class AbstractGuiTest {
    protected WebDriver driver; //Used by all tests
    ...
}

这是我的测试监听器类,它对失败的测试作出反应:

public class GuiTestListener implements IInvokedMethodListener {
    @Override
    public void afterInvocation(IInvokedMethod method, ITestResult itr) {
        if (method.isTestMethod() && !itr.isSuccess()) {
            //Take a screenshot here. But how do I get at the intance of WebDriver declared in the AbstractGuiTest?
        }
    }
}

您能否建议如何获取在AbstractGuitTest中声明的WebDriver实例,以便我可以使用它在GuiTestListener类中截取屏幕截图?

3 个答案:

答案 0 :(得分:2)

你可以从ITestResult获得它:

Object x = itr.getInstance();
AbstractGuiTest currentCase = (AbstractGuiTest)x;
WebDriver driver  = currentCase.getDriver();

答案 1 :(得分:1)

您可能的解决方案很好地捕获了这个想法 - 应该有一些地方在测试和监听器之间共享WebDriver实例。我想到了另外两个解决方案,这些解决方案用于我参与的项目或我在互联网上阅读过。

  1. 通过Singleton“holder”类共享它,就像在这个blogpost中一样。它是关于Groovy和Geb的,但它提出了这个想法。

  2. 使用依赖注入(例如guiceberry)在需要它的所有地方注入WebDriver。 guiceberry tutorial中有一个例子。

答案 2 :(得分:0)

我有一些类似的东西,我需要在测试失败时使用selenium截取屏幕截图。我的所有测试类扩展AbstractTestNGSpringContextTests实现TestWithSeleniumDriver,它们有注释@Listeners(ScreenshotForFailedTestListener.class)

public interface TestWithSeleniumDriver {
    public RemoteWebDriver getDriver();
}

public class ScreenshotForFailedTestListener implements IInvokedMethodListener {


    @Override
    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {

        // nothing
    }

    @Override
    public void afterInvocation(IInvokedMethod method, ITestResult testResult) {

        if (method.isTestMethod() && ITestResult.FAILURE == testResult.getStatus()) {
            if (method.getTestResult().getInstance() instanceof TestWithSeleniumDriver) {
                TestWithSeleniumDriver instance = (TestWithSeleniumDriver) method.getTestResult().getInstance();
                RemoteWebDriver driver = instance.getDriver();
                if (driver != null) {
                    TestingUtils.captureScreen(driver, method);
                }
            }
        }

    }

}

public class TestingUtils {

    private static final Logger logger = LogManager.getLogger(TestingUtils.class);



    public static String captureScreen(RemoteWebDriver driver, IInvokedMethod method) {


        String path;
        try {
            Throwable throwable = method.getTestResult().getThrowable();
            String testClass = method.getTestMethod().getRealClass().getName();
            String packageName = method.getTestMethod().getRealClass().getPackage().getName();
            String shortClassName = method.getTestMethod().getRealClass().getSimpleName();
            String testMethod = method.getTestMethod().getMethodName();

            StackTraceElement stackTraceElement = null;
            for (StackTraceElement traceElement : throwable.getStackTrace()) {
                if (traceElement.getClassName().equals(testClass) && traceElement.getMethodName().equals(testMethod)) {
                    stackTraceElement = traceElement;
                    break;
                }
            }
            WebDriver augmentedDriver = new Augmenter().augment(driver);
            File source = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
            String drvName = "unknown";
            if (driver instanceof FirefoxDriver)
                drvName = "firefox";
            else if (driver instanceof ChromeDriver)
                drvName = "chrome";
            else if (driver instanceof OperaDriver)
                drvName = "opera";
                // else if ( driver instanceof AndroidDriver )
                // drvName = "android";
            else if (driver instanceof RemoteWebDriver)
                if (driver.getCapabilities().getBrowserName() != null)
                    drvName = driver.getCapabilities().getBrowserName();
            String day = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            String hour = new SimpleDateFormat("HH-mm-ss").format(new Date());
            if (stackTraceElement == null) {
                path = ("./target/screenshots/" + drvName + "/" + "failed" + "/" + //
                        day + "/" + //
                        packageName + "/" + shortClassName + "/" + testMethod + "_noLineInfo_" + //
                        driver.getCurrentUrl().replaceAll("https://", "").replaceAll("/", "_") + "_" + //
                        hour + ".png").replaceAll("__", "_");//
            } else {
                path = ("./target/screenshots/" + drvName + "/" + "failed" + "/" + //
                        day + "/" + //
                        packageName + "/" + shortClassName + "/" + testMethod + "_line-" + stackTraceElement.getLineNumber() + "_" + //
                        driver.getCurrentUrl().replaceAll("https://", "").replaceAll("/", "_") + "_" + //
                        hour + ".png").replaceAll("__", "_");//
            }

            FileUtils.copyFile(source, new File(path));
            String stackTrace = ExceptionUtils.getStackTrace(throwable);
            logger.error("===========================");
            logger.error("screnshot captured to : " + path);
            logger.error("===========================");
        } catch (IOException e) {
            path = "Failed to capture screenshot: " + e.getMessage();
        }
        return path;
    }
}

代码必须根据您的需求进行调整