其中定义了getScreenshotAs方法



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

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

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

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


添加更多细节:

TakeScreenshot-->一个接口

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

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

上面的代码用于对selenium中的网页进行截图。

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

转换为(或首先使用)RemoteWebDriverChromeDriver也可以使用该方法。

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

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

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

进入这两行:

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

分析

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

  1. ChromeDriver
  2. FirefoxDriver
  3. InternetExplorerDriver
  4. 边缘驱动程序
  5. 操作驱动程序
  6. 远程Web驱动程序
  7. 远程WebElement `
  8. SafariDriver
  9. EventFiringWebDriver

在第一行中,我们将TakesScreenshot的一个实例初始化为ts,并将WebDriver实例(即driver)强制转换为该实例。

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

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

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

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


参考

您可以在"如何使用Selenium WebDriver 进行屏幕截图"中找到详细的讨论

好吧,据我所知,这实际上不是一个特定于硒的问题,而是一个基本的Java问题。

您提供的表达式的含义:

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

如下:无论driver变量的类型是什么,在这一行中,我们确信它实现了具有getScreenshotAs方法的TakesScreenshot接口。因此,我们将类型强制转换为TakesScreenshot,并在driver对象上调用getScreenshotAs方法。这个方法的实现是在实际的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到selenium中看到的,WebDriver接口并没有扩展TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须强制转换它。WebDriver driver = new ChromeDriver()-编译器只有WebDriver类型的引用。尽管真正的类是ChromeDriver,但编译器并不知道。因此,在这种情况下,为了调用getScreenshotAs方法,您必须将driver强制转换为TakesScreenshot(这是安全的,因为driverChromeDriver的实例,它同时实现了WebDriverTakesScreenshot接口)。之后才能从TakesScreenshot接口调用getScreenshotAs方法。

好吧,据我所知,这实际上不是一个硒特定的问题,而是一个基本的Java问题。

您提供的表达式的含义:

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

如下:无论driver变量的类型是什么,在这一行中,我们确信它实现了具有getScreenshotAs方法的TakesScreenshot接口。因此,我们将类型强制转换为TakesScreenshot,并在driver对象上调用getScreenshotAs方法。这个方法的实现是在真正的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到selenium中看到的,WebDriver接口并没有扩展TakesScreenshot接口。因此,如果driver变量的类型是WebDriver接口,则必须强制转换它。WebDriver driver = new ChromeDriver()-编译器只有WebDriver类型的引用。尽管真正的类是ChromeDriver,但编译器并不知道。因此,在这种情况下,为了调用getScreenshotAs方法,您必须将driver强制转换为TakesScreenshot(这是安全的,因为driverChromeDriver的实例,它同时实现了WebDriverTakesScreenshot接口)。之后才能从TakesScreenshot接口调用getScreenshotAs方法。

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

最新更新