getScreenshotAs在哪里定义方法?

时间:2017-10-08 09:27:55

标签: java selenium selenium-webdriver webdriver takesscreenshot

我正在浏览selenium中的截图代码。以下是代码:

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

在上面一行中,TakesScreenshot是一个界面,getScreenshotAs是一种方法。所以我从中理解的是,我们将驱动程序类型转换为TakesScreenshot接口,这实际上意味着我们的驱动程序将从现在起像TakesScreenshot,之后将执行getScreenshotAs方法。

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

添加更多细节:

TakesScreenshot - >界面

驱动程序 - > ChromeDriver类的实例(WebDriver驱动程序=新的C​​hromeDriver())

getScreenshotAs - > TakesScreenshot界面中的方法。

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

3 个答案:

答案 0 :(得分:2)

方法getScreenshotAsRemoteWebDriver类中实现。您无法在driver实例中使用它,因为您使用了WebDriver接口(不扩展TakesScreenshot接口)来创建driver实例。

投放到(或首先使用)RemoteWebDriverChromeDriver也可以使用该方法。

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

答案 1 :(得分:1)

首先让我分解您的解释代码:

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

分为以下两行:

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

分析

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

  1. ChromeDriver
  2. FirefoxDriver
  3. InternetExplorerDriver
  4. EdgeDriver
  5. OperaDriver
  6. RemoteWebDriver
  7. RemoteWebElement`
  8. SafariDriver
  9. EventFiringWebDriver
  10. 在第一行中,我们将 TakesScreenshot 的实例初始化为ts,并将 WebDriver 实例(即driver)转换为该实例。< / p>

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

    1. 整页
    2. 当前窗口
    3. 当前帧的可见部分
    4. 包含浏览器的整个显示的屏幕截图
    5. getScreenshotAs()方法返回Object,其中包含有关屏幕截图的信息。失败java.lang.UnsupportedOperationException,这意味着底层实现不支持屏幕截图捕获机制。

      您可以找到详细信息文档here

答案 2 :(得分: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())

导致行“Hello,username”

编辑:

正如我在JavaDoc中看到的那样,WebDriver接口不会扩展TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须将其强制转换。 WebDriver driver = new ChromeDriver() - 编译器只有WebDriver类型的引用。尽管真正的类是ChromeDriver编译器不知道它。因此,在这种情况下,为了调用getScreenshotAs方法,您必须将driver投射到TakesScreenshot(并且它是安全的,因为driverChromeDriver的实例,它实现了两者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())

导致行“Hello,username”

编辑:

正如我在JavaDoc中看到的那样,WebDriver接口不会扩展TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须将其强制转换。 WebDriver driver = new ChromeDriver() - 编译器只有WebDriver类型的引用。尽管真正的类是ChromeDriver编译器不知道它。因此,在这种情况下,为了调用getScreenshotAs方法,您必须将driver投射到TakesScreenshot(并且它是安全的,因为driverChromeDriver的实例,它实现了两者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