0

我正在浏览 selenium 中的屏幕截图代码。下面是它的代码:

File src = ((TakesScreenshot)driver).getScreenshotAs(OutputType.File);

在上一行中, TakesScreenshot 是一个接口,而 getScreenshotAs 是一个方法。所以我从中了解到的是,我们正在将驱动程序类型转换为 TakesScreenshot 接口,这本质上意味着我们的驱动程序从现在开始将表现得像 TakesScreenshot,之后将执行 getScreenshotAs 方法。

我的问题是接口只能有抽象方法。那么,getScreenshotAs 方法是如何通过 TakesScreenshot 接口执行的,因为它没有该方法的任何定义。更准确地说,getScreenshotAs 方法在哪里定义,上面的代码行是如何工作的?


添加更多细节:

TakesScreenshot --> 一个界面

driver --> ChromeDriver 类的实例 (WebDriver driver = new ChromeDriver())

getScreenshotAs --> TakesScreenshot 接口中的方法。

上面的代码用于截取 selenium 中的网页截图。

4

3 回答 3

2

该方法getScreenshotAsRemoteWebDriver类中实现。您不能从您的driver实例中使用它,因为您使用了WebDriver不扩展TakesScreenshot接口的接口来创建driver实例。

投射到(或首先使用)RemoteWebDriverChromeDriver也将允许您使用该方法。

File src = ((RemoteWebDriver)driver).getScreenshotAs(OutputType.File);
于 2017-10-08T11:12:30.037 回答
1

首先,让我分解您的代码以进行解释:

File src = ((TakesScreenshot)driver).getScreenshotAs(OutputType.File);

进入这两行:

TakesScreenshot ts = (TakesScreenshot) driver;
File source = ts.getScreenshotAs(OutputType.FILE);

分析

根据文档,TakesScreenshotSelenium包中的一个接口org.openqa.seleniumpublic interface TakesScreenshot表示可以捕获屏幕截图并以下面提到的不同方式存储的驱动程序。public interface TakesScreenshot有一个称为WebElement子接口。已知的实现类是:

  1. 铬驱动程序
  2. 火狐驱动
  3. InternetExplorer驱动程序
  4. 边缘驱动程序
  5. OperaDriver
  6. 远程网络驱动程序
  7. 远程网络元素`
  8. Safari驱动程序
  9. 事件触发WebDriver

在第一行中,我们将TakesScreenshot实例初始化为ts并将WebDriver实例driver转换为该实例。

在第二行中,我们尝试捕获屏幕截图并将其存储在指定位置。对于WebDriver扩展TakesScreenshot,这将尽最大努力根据浏览器(强制转换)按优先顺序返回以下对象:

  1. 整个页面
  2. 当前窗口
  3. 当前帧的可见部分
  4. 包含浏览器的整个显示的屏幕截图

getScreenshotAs()方法返回包含有关屏幕截图的存储信息的对象。失败java.lang.UnsupportedOperationException意味着底层实现不支持屏幕截图捕获机制。

您可以在此处找到详细文档。


参考

您可以在如何使用 Selenium WebDriver 截屏中找到详细讨论

于 2017-10-09T04:53:07.660 回答
0

好吧,据我了解,这实际上不是特定于硒的问题,而是基本的 Java 问题。

您提供的表达式的含义:

((TakesScreenshot) driver).getScreenshotAs(OutputType.File)

如下:无论driver变量的类型是什么,在这一行中我们确定它实现TakesScreenshot了具有getScreenshotAs方法的接口。所以我们将类型转换为对象TakesScreenshot并调用getScreenshotAs方法driver。此方法的实现在真实driver类中,无论它是什么。

给你一个非常接近问题代码的例子(我让这个方法接受Object,所以我们真的需要转换o到目标接口。不要在实际代码中这样做):

public void log(Object o) {
  ((Printable) o).print();
}

Printable方法的一些接口在哪里print

public interface Printable {
  void print();
}

所以如果我们有一些Printable类似的实现

public class Greeting implements Printable {

  @Override
  public void print() {
    System.out.println("Hello, username");
  }

}

我们可以打电话

log(new Greeting())

这导致行“你好,用户名”

编辑:

正如我在 JavaDoc to selenium 中看到的那样,WebDriver接口不扩展 TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须对其进行强制转换。-编译器WebDriver driver = new ChromeDriver()只有类型参考。WebDriver尽管真正的类是ChromeDriver编译器并不知道它。因此,在这种情况下,为了调用getScreenshotAs方法,您必须强制driver转换为TakesScreenshot(它是安全的,因为它的driver实例ChromeDriver同时实现了接口WebDriverTakesScreenshot接口)。只有在那之后,您才能从接口调用getScreenshotAs方法。TakesScreenshot

好吧,据我了解,这实际上不是特定于硒的问题,而是基本的 Java 问题。

您提供的表达式的含义:

((TakesScreenshot) driver).getScreenshotAs(OutputType.File)

如下:无论driver变量的类型是什么,在这一行中我们确定它实现TakesScreenshot了具有getScreenshotAs方法的接口。所以我们将类型转换为对象TakesScreenshot并调用getScreenshotAs方法driver。此方法的实现在真实driver类中,无论它是什么。

给你一个非常接近问题代码的例子(我让这个方法接受Object,所以我们真的需要转换o到目标接口。不要在实际代码中这样做):

public void log(Object o) {
  ((Printable) o).print();
}

Printable方法的一些接口在哪里print

public interface Printable {
  void print();
}

所以如果我们有一些Printable类似的实现

public class Greeting implements Printable {

  @Override
  public void print() {
    System.out.println("Hello, username");
  }

}

我们可以打电话

log(new Greeting())

这导致行“你好,用户名”

编辑:

正如我在 JavaDoc to selenium 中看到的那样,WebDriver接口不扩展 TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须对其进行强制转换。-编译器WebDriver driver = new ChromeDriver()只有类型参考。WebDriver尽管真正的类是ChromeDriver编译器并不知道它。因此,在这种情况下,为了调用getScreenshotAs方法,您必须强制driver转换为TakesScreenshot(它是安全的,因为它的driver实例ChromeDriver同时实现了接口WebDriverTakesScreenshot接口)。只有在那之后,您才能从接口调用getScreenshotAs方法。TakesScreenshot

WebDriver driver = new ChromeDriver();
// driver.getScreenshotAs(OutputType.File); // compilation error as there is no method getScreenshotAs in WebDriver interface
((TakesScreenshot) driver).getScreenshotAs(OutputType.File); // ok after explicit casting
于 2017-10-08T09:51:12.013 回答