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();
}
What I would suggest is
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.
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.
The solution that worked for me was to create this extension:
package some.thing;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
public class Screenshotter implements AfterTestExecutionCallback {
private static final Logger LOG = LogManager.getLogger();
private static WebDriver driver;
public static void setDriver(WebDriver driver) {
Screenshotter.driver = driver;
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
if (context.getExecutionException().isPresent()) { // if the test execution has failed
String baseFileName = context.getRequiredTestClass().getSimpleName() + "-"
+ context.getRequiredTestMethod().getName()
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("-yyMMdd-HHmmss"));
File targetFile = new File("somewhere/" + baseFileName + ".png");
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Files.copy(scrFile.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
targetFile.setReadable(true, false);
LOG.info("Screenshot saved to " + targetFile.toPath());
}
}
}
Then apply it to the relevant test class like so:
@ExtendWith(Screenshotter.class)
public class SomeTest {
...
@BeforeAll
public void initialize() {
...
Screenshotter.setDriver(driver);
...
}
...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.