Selenium 测试 - 在遇到失败时截图保存

转至:http://blogs.steeplesoft.com/posts/2012/01/24/grabbing-screenshots-of-failed-selenium-tests/

下面是在网上找到一篇文章,讲述了如何使用junit运行selenium,并且在失败的时候获得截图,亲测可行,不过有一点需要注意,那就是一定要用static的driver,并使用AfterClass来关闭driver,我测试的时候由于使用的不是静态的driver,也没有用AfterClass,而是用@After来关闭driver,结果driver在Rule被调用前就被关闭了。

For the GlassFish Administration Console, we have quite a few tests (about 133 at last count). Given the nature and architecture of the application, we’ve chosen Selenium to drive our tests. One of the problems we’ve faced, though, is understanding why a test failed due to the length of time the tests take (roughly 1.5 hours to run the whole suite). Sometimes, we can look at the log and know exactly what failed, but not the why. Did the screen render correctly? Did, perhaps, the click, etc. not get performed (we’ve seen instances of that) leaving the application in a state not expected by the test? Since I usually start the tests and move on to something else, we had no way of knowing. Until now. I finally sat down and figured out how to grab a screen shot when a test fails. I’ve distilled that technique down to its essentials, which I’ll share here.

In this example, we’re going make sure example.com works correctly. Sort of. : ) What we need to do first, though, is set up our project, which we’ll configure (for simplicity’s sake) as a simple Maven-based Java application. The important pom.xml elements are these:


   
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-server</artifactId>
        <version>2.14.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
                <showDeprecation>true</showDeprecation>
            </configuration>
        </plugin>
    </plugins>
</build>

Simple enough. Now, the test:


   
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ScreenshotDemoTest {
    private static WebDriver driver;
    private static Selenium selenium;

    @Rule
    public ScreenshotTestRule screenshotTestRule = new ScreenshotTestRule();

    @BeforeClass
    public static void beforeClass() {
        driver = new FirefoxDriver();
        selenium = new WebDriverBackedSelenium(driver, "http://example.com");
    }

    @AfterClass
    public static void afterClass() {
        selenium.close();
    }

    @Test
    public void testThatSucceeds() {
        selenium.open("/");
        assertTrue(selenium.isTextPresent("As described"));
    }

    @Test
    public void testThatFails() {
        selenium.open("/");
        assertTrue(selenium.isTextPresent("Your test should fail here"));
    }
}

This is an extremely simple test that should make sense to those familiar with Selenium. The interesting part here is lines 4 and 5. What’s that Rule? That little nugget is a means of extending JUnit in an AOP fashion. In our case, that’s where the magic is going to happen, so let’s take a look at ScreenshotTestRule:


   
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class ScreenshotTestRule implements MethodRule {
    public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    statement.evaluate();
                } catch (Throwable t) {
                    captureScreenshot(frameworkMethod.getName());
                    throw t; // rethrow to allow the failure to be reported to JUnit
                }
            }

            public void captureScreenshot(String fileName) {
                try {
                    new File("target/surefire-reports/").mkdirs(); // Insure directory is there
                    FileOutputStream out = new FileOutputStream("target/surefire-reports/screenshot-" + fileName + ".png");
                    out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
                    out.close();
                } catch (Exception e) {
                    // No need to crash the tests if the screenshot fails
                }
            }
        };
    }
}

Implementations of MethodRule act as an interceptor for your tests. You can do all the usual types of things you might do in an interceptor (in fact, in GlassFish, we use this is allow us to run only specific test methods, e.g.,mvn -Dtest=MyTest -Dmethod=testMethod1,testMethod3). Here, though, we want to run every test, but, in the case of failures, which present themselves as Exceptions, we wan’t to capture the screenshot. Once we’ve saved the image to a file (note the assumption that we’re running under Maven in captureScreenshot()), we rethrow the Throwable to make sure the failure is reported.

If you run these tests, you should see one success and one failure, and you should seetarget/surefire-reports/screenshot-testThatFails.png. How easy was that?! : )

Full source code can be found here. I hope this helps you as much as it has me. : )

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值