Wednesday 3 August 2022

Screenshots in Selenium with Cucumber, TestNG

 Screenshots in Selenium with Cucumber, TestNG

  • Purpose: To analyze or de-bug or trace the test execution (or to analyze a bug)
  • Generally, used with failed scenarios/tests
  • Very handy when executing tests in Non GUI environments such as Jenkins, AzureDevOps and etc. 
  • In cucumber, write the screenshots code in After hook
  • Ensure to quit the driver immediately after taking the screenshot
  • If screenshot and quit has to go in two different methods use order for the After hook. 
  • For instance, give order=0 for quit the driver and give order=1 to take the screenshot. 

Example

Screenshot is implemented based on my previous example on page factory codebase. 

Refer this post on page factory
and in the Hooks.java class update the code of After hooks namely 
@After(order=0) and @After(order=1)


Download Screenshots source code from GitHub  OR
 click this to download as a Zip

  • In the order=0 After hook section, quit the driver and in the order=1 hook section take the screenshot. 

  • Use the attach method of scenario object
    (NOTE: This example is based on io.cucumber 7.1.0 and it doesn't support embed method)

  • isFailed() identifies the failed scenario , for instance in the DirectoryPageFactory.java file (refer the code from previous example above) xpath for the searchButtonLocator is deliberately updated to a bad entry so this produces an error in validation. 
// Search button locator
@FindBy(xpath = "//*[@id=\"searchBtnBAD\"]")
public WebElement searchButtonLocator;


Hooks.java
package com.sadakar.common;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;

public class Hooks extends BasePage {

	@Before //Cucumber Before Hook
	public  void setupDriver() throws InterruptedException {

		System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
		driver = new ChromeDriver();
		driver.manage().window().maximize();
		driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/login");
	}

	@After(order=0) // Cucumber After hook with order 0
	public  void quitDriver() throws Exception {
		driver.quit();
	}
	@After(order = 1) // Cucumber After Hook with order 1
	public void takeScreenShotOnFailedScenario(Scenario scenario) {

		System.out.println("This is from After hook, order=1");
		if ((scenario.isFailed())) {
			final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
			scenario.attach(screenshot, "image/png", scenario.getName());
		}
	}

}

Where does screenshots get stored ? 

The code above is a cucumber based screenshot in the Hooks so eventually the screenshots get stored in the cucumber related reports. 
For instance, below is the cucumber report folder in the target

As the cucumberreport.html is opened, we can see the screenshot appended at the end of the scenario. 



What if the order of After hooks for quit is 1 and
for screenshot is 0 

We end up with the following error message:
org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?

      org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
Build info: version: '4.3.0', revision: 'a4995e2c09*'
System info: host: 'SADAKARP', ip: '136.144.2.8', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '16.0.2'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Command: [null, screenshot {}]
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 103.0.5060.134, chrome: {chromedriverVersion: 103.0.5060.53 (a1711811edd7..., userDataDir: C:\Users\sadakarp\AppData\L...}, goog:chromeOptions: {debuggerAddress: localhost:64648}, networkConnectionEnabled: false, pageLoadStrategy: normal, platformName: WINDOWS, proxy: Proxy(), se:cdp: ws://localhost:64648/devtoo..., se:cdpVersion: 103.0.5060.134, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true}
	at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:145)
	at org.openqa.selenium.remote.service.DriverCommandExecutor.invokeExecute(DriverCommandExecutor.java:167)
	at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:142)
	at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:569)
	at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:624)
	at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:628)
	at org.openqa.selenium.remote.RemoteWebDriver.getScreenshotAs(RemoteWebDriver.java:353)
	at com.sadakar.common.Hooks.takeScreenShotOnFailedScenario(Hooks.java:29)
I hope this helped you a bit. Keep an eye this space for future posts.

No comments:

Post a Comment