0

Can any one please help taking screen shots and saving on specific folder on Mac while running selenium webdriver automation scripts using java??

Note: I used static in my code so i cannot use below code

File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\screenshot.jpg"));

Thanks in advance !!

vamc
  • 125
  • 1
  • 2
  • 13
  • 1
    possible duplicate of [Take a screenshot with Selenium WebDriver](http://stackoverflow.com/questions/3422262/take-a-screenshot-with-selenium-webdriver) – threesixnine Aug 28 '15 at 11:55
  • But that code is the same as above which can be taken only one screen shot and not when failed so need some more for above code... Can you please help me?? @Mystia – vamc Aug 28 '15 at 12:17
  • Honestly I cannot completely understand what is your actual problem? – threesixnine Aug 28 '15 at 12:20
  • The above code gives me only one screenshot for all test cases, due to the code above has single name "screenshot.jpg". I want a code for screenshot on multiple test cases when failed !! I hope you got me?? – vamc Aug 28 '15 at 12:24

6 Answers6

4

If you're using JUnit 4, you can create a class that extends the TestWatcher class.

public class ScreenShotRule extends TestWatcher {

    private WebDriver webDriver;

    public ScreenShotRule(WebDriver webDriver) {
        this.webDriver = webDriver;
    }

    @Override
    protected void failed(Throwable e, Description description) {
        String methodName = description.getMethodName();
        String fileName = description.getTestClass().getSimpleName() + "-" + methodName + ".png";

        try {
            File destiny = new File(fileName);
            FileUtils.copyFile(((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE), destiny);
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    @Override
    protected void finished(Description description) {
        webDriver.quit();
    }
}

In you're test, add a public field of this class and when the test fails, the rule will take the screenshot.

@Rule
public ScreenShotRule screenshotRule;
1

Make folder

File file = new File("Screenshots" + fileSeperator + "Results");
            if (!file.exists()) {
                file.mkdir();
            }


//Now take the screens shot with name of your test method and copy to folder
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
File targetFile = new File("Screenshots" + fileSeperator + "Results" + fileSeperator + testName, screenShotName);
FileUtils.copyFile(screenshotFile, targetFile);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Samir 007
  • 179
  • 2
  • 8
1

We can place TakeScreenshot method in separate method using @AfterMethod in testNG. ITestResult interface in selenium gives you the status of test execution and the name of the test case.

Eg :

@AfterMethod
public void invokeScreenshotMethod(ItestResult res)
{
if (ItestResult.Failure==res.getStatus()){
try{
TakeScreenshot ts=(TakeScreenShot) driver;

File src= ts.getScreenshotAs(OUTPUTTYPE.FILE);
FileUtils.copyFile(src, new File("e://destination 
location+"res.getName()+".png");
}

Catch(Exception e)
{

System.out.println("");
}
}
Ashika
  • 11
  • 2
0

Instead of creating a static name for a screenshot file like ( "screenshot.jpg" ), all you need to do is to make it change each time you take a screenshot. What you can do in many different ways.

One of the options you have in this case can be, to create a string of date and time that is going to be unique, like this:

var myUniqueScreenshot = "D:\\"+DateTime.Now.ToString("F").Replace(":", "-")+".jpg";

File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(myUniqueScreenshot));

The first line of code is c# hope you can translate it to Java if it's not the same.

threesixnine
  • 1,733
  • 7
  • 30
  • 56
  • Thanks Mystia, I will try and let you know :) – vamc Aug 28 '15 at 12:35
  • Mystia, this code which you gave is taking screenshots for passed test cases as well, but can I get the code only for failed test cases please... – vamc Aug 28 '15 at 13:22
  • @vamc Where are you setting up when to take a screenshot? – threesixnine Aug 28 '15 at 13:27
  • @vamc What I meant was how are you telling selenium when to take a screenshot ? – threesixnine Aug 28 '15 at 13:37
  • sry Mystia, I want the code to take screenshot where the issue happens... but I think there is no code for that.right?? Example like: There are 5 lines of code for log-in, where 4th line of code is password ,when i run my script, the test case fails on 4th line coz i gave wrong password so I need a screenshot for that line of the browser. Actually, You can say that we get the details on console but can i get the screenshot also of the browser?? – vamc Aug 28 '15 at 13:43
  • @vamc That is exactly the reason why I am asking you this , because you can always create try and catch block and whenever you catch an exception inside of the catch block you set a screenshot method that will fire on that event. – threesixnine Aug 28 '15 at 13:45
  • Dont mind Mystia, I m new to selenium so can you please give me steps how to add try catch. Here is the code which you gave have been set to, please click on the link for image. https://drive.google.com/file/d/0B0ICpjAv5p_oLVVGSVV3ekp5M3c/view?usp=sharing – vamc Aug 28 '15 at 13:55
  • @vamc Inside of the try block you put your actual test , and if it fails, catch block will catch an exception that has been thrown and also you should call your TakeScreenshot method inside of the catch block so it will run whenever your test fail. – threesixnine Aug 28 '15 at 14:01
  • No problem, glad to help! – threesixnine Aug 28 '15 at 14:57
  • Mystia, sry I could not make it, Can you give with small example like please !! – vamc Aug 28 '15 at 15:02
  • Hi Mystia, Can we get the screen shot names as Test case names ?? Eg: like if i have test case-1 and i need the screen shot name also be test case-1. Thanks – vamc Sep 03 '15 at 11:35
0

You are able to create some wrappers for operation to resolve your problem. Here I share an java example for you. Hope it helps.

ScreenshotUtil.java

public class ScreenshotUtil {
     public static void capture(WebDriver driver) {
         File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
         StringBuffer failedPicPath = new StringBuffer();
         failedPicPath.append("D:\\");
         String fn = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString(); //Or the name you want. I suggest don't use static name.
         failedPicPath.append(fn);
         failedPicPath.append(".jpg");
     }
}

Click.java

public void click(WebDriver driver, String xpath) {   //Assume you are using Xpath
     try {
          WebElement e = FindElementUtil.find(driver, xpath); //Here you can design a class named FindElementUtil to search any elements and construct your own Exception. Then catch it here and out put Screenshots.

          e.click():
     } catch(ANYEXCETPION e) {
         ScreenshotUtil.capture(driver); //OR you want to capture pic in all situations, capture it in 'finally' block.
     }
}
J.Lyu
  • 932
  • 7
  • 16
  • Hi J.Lyu, Can we get the screen shot names as Test case names ?? Eg: like if i have test case-1 and i need the screen shot name should also be test case-1. Thanks – vamc Sep 03 '15 at 11:33
  • @vamc Sure you can. It depends on how you control your cases. One suggestion is that you set up a Context class and put the information you want(e.g testcase name) in it. Once you trigger your case, initialize the Context and pass it to the operation wrapper like 'Click', 'InputText' then get the info from the Context while doing screenshot stuff. – J.Lyu Sep 06 '15 at 02:01
0

Below is something that works for me, I am using junit4 with selenium. Also, it used the name of the scenario for the screenshot which is very helpful.

@After
public void closeBrowser(Scenario scenario){
    if(scenario.isFailed()){
        try{
            TakesScreenshot screenshot = (TakesScreenshot)browser;
            File source = screenshot.getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(source, new File("logs/screenshots/" + scenario.getName() + ".png"));
            System.out.println("Screenshot taken");
        } catch (Exception e){
            System.out.println("Exception while taking screenshot " + e.getMessage());
        }
    }
    browser.quit();
}

Hope this helps :)

Anshu
  • 1
  • 3