3

I am currently using the following method to take screenshots after each test, and it works fine:

@After
public void takeScreenshotAtEndOfTest() throws IOException {
    File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
    String currentDir = System.getProperty("user.dir");
    FileUtils.copyFile(scrFile, new File(currentDir + "\\screenshots\\" + System.currentTimeMillis() + ".png"));

}

My question is, how can I improve this method so that it takes the name of the current test that has been run, and puts that into the filename of the image (instead of System.currentTimeMillis)?

This is one of my tests, if that helps:

@Test
public void pf01_activateQsmart_NoAddon_Cash(){
    guestWebsite.startOfTest("pf01_activateQsmart_NoAddon_Cash");
    doRegularServiceLevelActivation();
    doCashPayment();
    guestWebsite.endOfTest("pf01_activateQsmart_NoAddon_Cash");
}
1
  • But how to pass string to screenshot method? I want to name it based on by inputting some string.
    – user13255
    Sep 1, 2015 at 13:25

3 Answers 3

3

The answer provided by Sam nearly worked for me, but still had some problems as described above.

Basically I needed to use TestRule instead of MethodRule, and TestWatcher() instead of TestWatchman() - since the former ones have been depreciated.

I also needed to pass in "Description" instead of "FrameworkMethod" to get the name.

Finally I need to surround the copyFile with try / catch to avoid exceptions.

This is the code that worked for me and allowed me to take a screenshot on failure with the method name (and improved timestamp)

@Rule
public TestRule testWatcher = new TestWatcher() {
  @Override
  public void failed(Throwable e, Description test){
      File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
      String currentDir = System.getProperty("user.dir");
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
      try {
          FileUtils.copyFile(scrFile, new File(currentDir + "\\screenshots\\" + test.getMethodName() + timeStamp + ".png"));
      } catch (IOException e1) {
          e1.printStackTrace();
      }
  }
};

Thanks again for your help

3

You can use the TestWatchman class which is part of JUnit to get the test case name, as well as the status, so you could take screenshots only on failure. Here's an example that takes a screenshot on failure:

@Rule
MethodRule watchman = new TestWatchman(){

    @Override
    public void failed(Throwable e, FrameworkMethod method){
        File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        String currentDir = System.getProperty("user.dir");
        FileUtils.copyFile(scrFile, new File(currentDir + "\\screenshots\\" +
        method.getName() + System.currentTimeMillis() + ".png"));
    }

}

JUnit Documentation: https://github.com/junit-team/junit/wiki/Rules#testwatchmantestwatcher-rules

2
  • 1
    Thanks for your answer Sam, but it didn't quite work for me. I ran into some problems with casting the driver in the overide method, and it also seems that MethodRule and TestWatchman() have been depreciated. However your answer led to find a similar method that worked, as described below. Nov 6, 2014 at 10:35
  • 2
    Just so you know, the method was deprecated, but it was de-deprecated in junit 4.11: github.com/junit-team/junit/pull/519. Your solution also works though and technically is probably the more correct solution. Thanks.
    – Sam Woods
    Nov 6, 2014 at 16:33
1

Add this screenshot class to your project:

public class ScreenshotRule implements MethodRule {

    public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, Object o) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    statement.evaluate();
                } catch (Throwable t) {
                    captureScreenshot(frameworkMethod.getName());
                    throw t;
                }
            }
        };
    }

    public void captureScreenshot(String methodName){
        try {
            new File("build/reports/tests/screenshots/").mkdirs(); //this is the default directory for reports generated by gradle
            FileOutputStream outPutFile = new FileOutputStream("build/reports/tests/screenshots/" + methodName + ".jpg");
            outPutFile.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
            out.close();
        } catch (Exception e) {
        }
    }
}

And then add this to your BaseTest or a test file where you want the screenshot to be taken:

@Rule
public ScreenshotRule screenshotRule = new ScreenshotRule();

Also check this post out on saving screenshots and then adding them to reports https://automatedqa.wordpress.com/2016/09/20/html-report-with-screenshots-with-gradle-and-webdriver/

1
  • 1
    Could you please provide some context to the link? Links have a tendency to either change or become unusable and without any context to the information provided in the link the answer wouldn't stand on it's own.
    – Paul Muir
    Sep 23, 2016 at 17:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.