How to capture a screenshot after each step in tests with JAVA and Cucumber?

17,188

Solution 1

Solved this using Aspects. Was pretty tricky, note the annotation:

@After("call(public * cucumber.runtime.StepDefinitionMatch.runStep(..)) && within(cucumber.runtime.Runtime)")

Below is the full code, written by Viviana Cattenazzi.

pom.xml

 <dependencies>
         <dependency>
             <groupId>org.aspectj</groupId>
             <artifactId>aspectjweaver</artifactId>
             <version>1.8.9</version>
         </dependency>
         <dependency>
             <groupId>org.aspectj</groupId>
             <artifactId>aspectjrt</artifactId>
             <version>1.8.9</version>
         </dependency>
         <dependency>
             <groupId>org.aspectj</groupId>
             <artifactId>aspectjtools</artifactId>
             <version>1.8.9</version>
         </dependency>
         <dependency>
             <groupId>info.cukes</groupId>
             <artifactId>cucumber-core</artifactId>
             <version>1.2.4</version>
         </dependency>
     </dependencies>

......

         <plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>aspectj-maven-plugin</artifactId>
             <version>1.10</version>
             <configuration>
                 <weaveDependencies>
                     <weaveDependency>
                         <groupId>info.cukes</groupId>
                         <artifactId>cucumber-core</artifactId>
                     </weaveDependency>
                 </weaveDependencies>
                 <showWeaveInfo>true</showWeaveInfo>
                 <source>1.8</source>
                 <target>1.8</target>
                 <complianceLevel>1.8</complianceLevel>
             </configuration>
             <executions>
                 <execution>
                     <phase>process-test-classes</phase>
                     <goals>
                         <goal>compile</goal>
                         <goal>test-compile</goal>
                     </goals>
                 </execution>
             </executions>
         </plugin>

.......

StepsInterceptor.java

@Aspect
 public class StepsInterceptor {


     @After("call(public * cucumber.runtime.StepDefinitionMatch.runStep(..)) && within(cucumber.runtime.Runtime)")
     public void beforeRunningStep(JoinPoint thisJoinPoint) throws Exception {

         try {
             StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) thisJoinPoint.getTarget();
             Step step = (Step) retrievePrivateField(stepDefinitionMatch, "step");
             String stepName = step.getKeyword().trim();

             if ("Given".equals(stepName) || "When".equals(stepName)) {
                 Object theRealStepDef = extractJavaStepDefinition(stepDefinitionMatch);
                // take screen shot here
             }
         } catch (ClassCastException exc) { ....
}
}
}

Solution 2

Can this post help you?

Embedding screenshots in Cucumber JVM

Solution 3

Here is the Answer to your Question:

  1. Lets assume your methods are as follows:

    @Given("^Open$")
    public void Open() throws Throwable 
    {
        //your code
    }
    
    @When("^I$")
    public void I(String uname, String pass) throws Throwable 
    {
        //your code
    }
    
    @Then("^User$")
    public void User() throws Throwable 
    {
        //your code
    }
    
  2. You can write a library to take screenshots like:

    public static void screenshot(WebDriver driver, long ms)
    {
    
    try {
        TakesScreenshot ts = (TakesScreenshot) driver;
        File source = ts.getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(source, new File("./ScreenShots/"+ms+"Facebook.png"));
        System.out.println("ScreenShot Taken");
    } 
    catch (Exception e) 
    {
        System.out.println("Exception while taking ScreenShot "+e.getMessage());
    }
    
    
    }
    
  3. Now you can easily call the library after every method to take the screenshot as follows:

    @Given("^Open$")
    public void Open() throws Throwable 
    {
        //your code
        Utility.screenshot(driver, System.currentTimeMillis());
    }
    
    @When("^I$")
    public void I(String uname, String pass) throws Throwable 
    {
        //your code
        Utility.screenshot(driver, System.currentTimeMillis());
    }
    
    @Then("^User$")
    public void User() throws Throwable 
    {
        //your code
        Utility.screenshot(driver, System.currentTimeMillis());
    }
    

Let me know if this Answers your Question.

Share:
17,188
tetchen9
Author by

tetchen9

Updated on June 04, 2022

Comments

  • tetchen9
    tetchen9 almost 2 years

    What would be the best way to capture screenshots after each step when running integration tests?

    Tests are written in Java using Selenium(3.0.1) and Cucumber(1.2.4).

    Code for taking a screenshot after a test is below, but I need a screenshot after each method annotated with @Given, @When, @Then.

    @After
    public void after(Scenario scenario){
        final byte[] screenshot = driver.getScreenshotAs(OutputType.BYTES);
        scenario.embed(screenshot, "image/png");
    }
    

    Thank you for any hints.