WebDriver 之测试失败自动截图(2)

发表于:2012-08-24来源:test China作者:lihuazhang点击数: 标签:WebDriver
import java.net.URL; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.CapabilityType;

  import java.net.URL;

  import org.openqa.selenium.OutputType;

  import org.openqa.selenium.TakesScreenshot;

  import org.openqa.selenium.WebDriverException;

  import org.openqa.selenium.remote.CapabilityType;

  import org.openqa.selenium.remote.DesiredCapabilities;

  import org.openqa.selenium.remote.DriverCommand;

  import org.openqa.selenium.remote.RemoteWebDriver;

  public class CustomRemoteWebDriver extends RemoteWebDriver implements

  TakesScreenshot {

  public CustomRemoteWebDriver(URL url, DesiredCapabilities dc) {

  super(url, dc);

  }

  @Override

  public X getScreenshotAs(OutputType target)

  throws WebDriverException {

  if ((Boolean) getCapabilities().getCapability(

  CapabilityType.TAKES_SCREENSHOT)) {

  return target

  .convertFromBase64Png(execute(DriverCommand.SCREENSHOT)

  .getValue().toString());

  }

  return null;

  }

  }

  然后,我们在加一个封装类, 将截图方法放进去。

  WebDriverWrapper.screenShot :

  /**

  * Function to take the screen shot and save it to the classpath dir.

  * Usually, you will find the png file under the project root.

  *

  * @param driver

  * Webdriver instance

  * @param desc

  * The description of the png

  */

  public static void screenShot(WebDriver driver, String desc) {

  Date currentTime = new Date();

  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");

  String dateString = formatter.format(currentTime);

  File scrFile = ((TakesScreenshot) driver)

  .getScreenshotAs(OutputType.FILE);

  try {

  desc = desc.trim().equals("") ? "" : "-" + desc.trim();

  File screenshot = new File("screenshot" + File.separator

  + dateString + desc + ".png");

  FileUtils.copyFile(scrFile, screenshot);

  } catch (IOException e) {

  e.printStackTrace();

  }

  }

  下面,就是添加 Junit 的 TestRule:

  import org.junit.rules.TestRule;

  import org.junit.runner.Description;

  import org.junit.runners.model.Statement;

  import org.openqa.selenium.WebDriver;

  public class TakeScreenshotOnFailureRule implements TestRule {

  private final WebDriver driver;

  public TakeScreenshotOnFailureRule(WebDriver driver) {

  this.driver = driver;

  }

  @Override

  public Statement apply(final Statement base, Description description) {

  return new Statement() {

  @Override

  public void evaluate() throws Throwable {

  try {

  base.evaluate();

  }

  catch (Throwable throwable) {

  WebDriverWrapper.screenShot(driver, "assert-fail");

  throw throwable;

  }

  }

  };

  }

  }

  代码很简单,在抛出 evalate 方法的错误之前,截图。

  然后就是使用这个 TestRule, 很简单,只要在你的 测试用例里面加入:

  public class MyTest {

  ...

  @Rule

  public TestRule myScreenshot = new TakeScreenshotOnFailureRule(driver);

  ...

  @Test

  public void test1() {}

  @Test

  public void test2() {}

  ...

  }

  即可。关于 Junit 的 Rule 请自行 google!

  两则的比较

  总得来说,两种方法都很方便, 也很有效果, 基本都能截图成功。

  不同之处在于,

  RemoteWebDriver 监听器是在 RemoteWebDriver 抛出异常的时候截图。

  TestRule 是在 assert 失败的时候截图。

  我在项目中最早是用第一种方法,后来改用第二种,主要是因为,在自定义的监听器里, 它遇到所有的异常都会截图,这个时候,如果你用了 condition wait 一个 Ajax 的元素, 那就会很悲剧,你会发现在你的目录下面有无数的截图。当初我没有找到解决方法,期待有人提出。

原文转自:http://www.ltesting.net