Screenshot on failed tests using Junit 5 Selenium parallel execution



I would like to take a screenshot every single time test fails or if multiple tests then multiple screenshots of course.

So far I understand that I can just wrap my single test with a try catch block and proceed taking a screenshot, however I would not want to wrap it in every test I have. I want it to apply to all of them without wrapping each one, do I have to do that in my setup?

public class WebDriverSettings
{

    protected WebDriver driver;
    protected String TARGET_URL;

    @BeforeEach
    public void setUp()
    {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver(new ChromeOptions().addArguments("window-size=1920x1480"));
        driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
        loginToEnvironment();
    }
}

public class LoginServiceTest extends WebDriverSettings
{
    private LoginModal loginModal;
    private AccountApi accountApi;
    private Credentials credentials;

    @BeforeEach
    public void setUp()
    {
        super.setUp();
        credentials = new SignUp();
        accountApi = new AccountApi(credentials);
        accountApi.createAccount();
        loginModal = new HomePage(driver).acceptCookies().clickOnMyAccountTab().switchToLoginTab();
    }

    @Test
    public void shouldSuccessfullyLogin()
    {
        try
        {
            accountApi.createAccount();
            assertFalse(loginModal.login(credentials).getMyAccountName().getText().isEmpty());
        } catch (Exception e)
        {
            try
            {
                File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
                FileUtils.copyFile(screenshotFile, new File("path"));
            } catch (IOException ioException)
            {
                ioException.printStackTrace();
            }
            accountApi.closeAccount();
        }
    }
}

Solution advised by Jeff

So creating Util package and adding a class that would be responsible for creating a screenshot also it would generate random name but needs to be refactored i just made it quickly to make it work

public class ScreenShotCreator {

    public static void takeScreenShot(WebDriver driver) {
        try {
            File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(screenshotFile, new File(fileNameGenerator()));
        } catch (IOException e) {
            throw new RuntimeException("Could not make a screenshot");
        }
    }

    // creating this for test purposes , need to use string builder instead to append it instead of adding it
    private static String fileNameGenerator() {
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy-HH:mm");
        String path = ".....";
        return path + "screenshot" + formatter.format(new Date()) + " " + RandomStringUtils.randomAlphanumeric(10) + ".png";
    }

Then before closing it down just call the created method

@AfterEach
    public void tearDown() {
        ScreenShotCreator.takeScreenShot(driver);
        driver.manage().deleteAllCookies();
        driver.close();
        driver.quit();
    }

Answer

What I would suggest is

  1. Create a method to take a screenshot and put that in a Utils class and call it when you want to take a screenshot. This will make taking a screenshot a lot easier because all the code lives in one place and can be easily called from anywhere.

  2. Create a tearDown() method, if you don’t have one already. Looks like it would go in the WebDriverSettings class from your currently posted code. Mark it with an @AfterEach annotation and then detect a failed test case and if it failed, take a screenshot.

    If you aren’t sure how to do that, there’s a class in JUnit 4.9 and later called TestWatcher that you can use. There are lots of examples on the web on how to use it.



Source: stackoverflow