Taking Screenshots With Selenium WebDriver – 用Selenium WebDriver拍摄截图

最后修改: 2020年 7月 6日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

When working with automated tests using Selenium, we often need to take a screenshot of a web page or part of a web page. This can be useful, particularly when debugging test failures or verifying our application behavior is consistent across different browsers.

在使用Selenium进行自动测试时,我们经常需要对网页或网页的一部分进行截图。这可能很有用,特别是在调试测试失败或验证我们的应用程序行为在不同的浏览器上是否一致时。

In this quick tutorial, we’ll take a look at a couple of ways we can capture screenshots using Selenium WebDriver from our JUnit tests. To learn more about testing with Selenium, check out our great guide to Selenium.

在这个快速教程中,我们将看一下使用 Selenium WebDriver 从JUnit测试中捕获屏幕截图的几种方法。要了解有关使用 Selenium 测试的更多信息,请查看我们伟大的 Selenium 指南

2. Dependencies and Configuration

2.依赖性和配置

Let’s start by adding the Selenium dependency to our pom.xml:

让我们先把Selenium的依赖关系添加到我们的pom.xml

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

As always, the latest version of this artifact can be found in Maven Central. Furthermore, the latest version of the Chrome Driver may be downloaded from its website.

一如既往,该工件的最新版本可以在Maven中心找到。此外,最新版本的Chrome驱动程序可以从其网站下载。

Now let’s configure our driver to use Chrome from our unit test:

现在让我们来配置我们的驱动程序,以使用单元测试中的Chrome浏览器。

private static ChromeDriver driver;

@BeforeClass
public static void setUp() {
    System.setProperty("webdriver.chrome.driver", resolveResourcePath("chromedriver.mac"));

    Capabilities capabilities = DesiredCapabilities.chrome();
    driver = new ChromeDriver(capabilities);
    driver.manage()
      .timeouts()
      .implicitlyWait(5, TimeUnit.SECONDS);

    driver.get("http://www.google.com/");
}

As we can see, this is a pretty standard Selenium configuration for a ChromeDriver which will let us control the Chrome browser running on our local machine. We also configure the amount of time the driver should wait when searching for an element on the page to five seconds.

正如我们所见,这是一个相当标准的Selenium配置,用于ChromeDriver ,它将让我们控制运行在本地机器上的Chrome浏览器。我们还配置了驱动程序在搜索页面上的元素时应等待的时间为5秒。

Finally, before any of our tests run, we open a favorite web page, www.google.com in the current browser window.

最后,在我们的任何测试运行之前,我们在当前浏览器窗口中打开一个最喜欢的网页,www.google.com

3. Take a Screenshot of the Viewable Area

3.对可查看的区域进行截图

In this first example, we’ll take a look at the TakesScreenShot interface, which Selenium provides out-of-the-box. As the name suggests, we can use this interface for taking screenshots of the viewable area.

在第一个例子中,我们将看看Selenium提供的TakesScreenShot接口,它是开箱即用的。顾名思义,我们可以用这个接口对可视区进行截图。

Let’s create a simple method for taking screenshots using this interface:

让我们创建一个简单的方法来使用这个界面进行屏幕截图。

public void takeScreenshot(String pathname) throws IOException {
    File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(src, new File(pathname));
}

In this concise method, we first convert our driver into a TakesScreenshot using a cast. Then we can call the getScreenshotAs method, with the specified OutputType to create an image file.

在这个简明的方法中,我们首先使用cast将我们的驱动转换为TakesScreenshot然后我们可以调用getScreenshotAs方法,用指定的OutputType来创建一个图像文件

After that, we can copy the file to any desired location using the Apache Commons IO copyFile method. Pretty cool! In just two lines we’re able to capture screenshots.

之后,我们可以使用Apache Commons IO copyFile方法将文件复制到任何想要的位置。相当酷!只用两行字,我们就能抓取屏幕截图

Now let’s see how we can use this method from a unit test:

现在让我们看看如何从单元测试中使用这个方法。

@Test
public void whenGoogleIsLoaded_thenCaptureScreenshot() throws IOException {
    takeScreenshot(resolveTestResourcePath("google-home.png"));

    assertTrue(new File(resolveTestResourcePath("google-home.png")).exists());
}

In this unit test, we save the resulting image file to our test/resources folder using the filename google-home.png before asserting to see if the file exists.

在这个单元测试中,我们使用文件名google-home.png将生成的图像文件保存到我们的test/resources文件夹中,然后再断言该文件是否存在。

4. Capturing an Element on the Page

4.捕捉页面上的一个元素

In this next section, we’ll take a look at how we can capture a screenshot of an individual element on the page. For this, we’ll use a library called aShot, a screenshot utility library that is natively supported by Selenium 3 onwards.

在下一节中,我们将看看如何对页面上的单个元素进行截图。为此,我们将使用一个名为aShot的库,这是一个屏幕截图工具库,Selenium 3以上版本都支持该库

Since aShot is available from Maven Central, we can just include it in our pom.xml:

由于aShot可从Maven中心获得,我们只需在pom.xml中包含它。

<dependency>
    <groupId>ru.yandex.qatools.ashot</groupId>
    <artifactId>ashot</artifactId>
    <version>1.5.4</version>
</dependency>

The aShot library provides a Fluent API for configuring how exactly we want to capture are screenshots.

aShot库提供了一个Fluent API,用于配置我们究竟要如何捕捉屏幕截图。

Now let’s see how we can capture the logo from the Google home page from one of our unit tests:

现在让我们看看如何从我们的一个单元测试中捕获谷歌主页的标识。

@Test
public void whenGoogleIsLoaded_thenCaptureLogo() throws IOException {
    WebElement logo = driver.findElement(By.id("hplogo"));

    Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000))
      .coordsProvider(new WebDriverCoordsProvider())
      .takeScreenshot(driver, logo);

    ImageIO.write(screenshot.getImage(), "jpg", new File(resolveTestResourcePath("google-logo.png")));
    assertTrue(new File(resolveTestResourcePath("google-logo.png")).exists());
}

We start by finding a WebElement on the page using the id hplogo. Then we create a new AShot instance and set one of the builtin shooting strategies – ShootingStrategies.viewportPasting(1000). This strategy will scroll the viewport while we are taking our screenshot for a maximum of one second (1oooms).

我们首先在页面上找到一个WebElement,使用id hplogo。然后我们创建一个新的AShot实例,并设置一个内置的拍摄策略 – ShootingStrategies.viewportPasting(1000)该策略将在我们进行截图时滚动视口,最长时间为一秒钟(1oooms)

Now we have the policy for how we want to take our screenshot configured.

现在我们已经配置好了如何进行截图的策略。

When we want to capture a specific element on the page, internally, aShot will find an element’s size and position and crop the original image. For this, we call the coordsProvider method and pass a WebDriverCoordsProvider class which will use the WebDriver API to find any coordinates.

当我们想捕捉页面上的一个特定元素时,在内部,aShot将找到一个元素的大小和位置,并裁剪原始图像。为此,我们调用coordsProvider方法,并传递一个WebDriverCoordsProvider类,它将使用WebDriver API来寻找任何坐标。

Note that, by default, aShot uses jQuery for coordinate resolution. But some drivers have problems with Javascript.

注意,默认情况下,aShot使用jQuery进行坐标解析。但有些驱动程序在使用Javascript时有问题

Now we can call the takeScreenshot method passing our driver and logo element which will, in turn, give us a Screenshot object containing the result of our screen capture. As before, we finish our test by writing an image file and verifying its existence.

现在我们可以调用takeScreenshot方法,传递我们的driverlogo元素,这将反过来给我们一个Screenshot对象,包含我们屏幕捕捉的结果。像以前一样,我们通过写一个图像文件并验证其存在来完成我们的测试。

5. Conclusion

5.结论

In this quick tutorial, we’ve seen two approaches to capturing screenshots using Selenium WebDriver.

在这个快速教程中,我们看到了使用Selenium WebDriver捕获屏幕截图的两种方法。

In the first approach, we saw how to capture the whole screen using Selenium directly. Then we learned how to capture a specific element on the page using a great utility library called aShot.

在第一个方法中,我们看到了如何直接使用Selenium捕获整个屏幕。然后,我们学习了如何使用一个叫做aShot的伟大的工具库来捕获页面上的特定元素。

One of the main benefits of using aShot is that different WebDrivers behave differently when taking screenshots. Using aShot abstracts us away from this complexity and gives us transparent results irrespective of the driver we are using. Be sure to check out the complete documentation to see all the supported features available.

使用aShot的主要好处之一是,不同的WebDrivers在拍摄屏幕截图时有不同的表现。使用aShot将我们从这种复杂性中抽象出来,并为我们提供透明的结果,无论我们使用的是何种驱动程序。请务必查看完整的文档以了解所有可用的支持功能。

As always, the full source code of the article is available over on GitHub.

一如既往,文章的完整源代码可在GitHub上获得