How to take a screenshot for Soft Assert in Selenium or Java

安稳与你 提交于 2020-01-24 01:57:14

问题


Iam trying to take a screenshot for a testcase which fails using soft Assertion.I am using softAssertion for when a particular step fails it shows the failed step in the report but continues the execution.So in such case how can I take a screenshot whenever the tescase fails in soft Assert..plz help ?


回答1:


In the catch block of executeAssert either call a method that takes screenshot or implement the code there.

@Override
    public void executeAssert(IAssert a) {
    try {
        a.doAssert();
    } catch (AssertionError ex) {
        onAssertFailure(a, ex);
        takeScreenshot();
        m_errors.put(ex, a);
    }
    }

    private void takeScreenshot() {
    WebDriver augmentedDriver = new Augmenter().augment(driver);
    try {
        if (driver != null
            && ((RemoteWebDriver) driver).getSessionId() != null) {
        File scrFile = ((TakesScreenshot) augmentedDriver)
            .getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(scrFile, new File(("./test-output/archive/"
            + "screenshots/" + "_" + ".png")));
        }       
    } catch (Exception e) {
        e.printStackTrace();
    }
    }



回答2:


I had same problem and resolved with below approach.

Create your own SoftAssert class that extends Assertion class and methods of TestNG's soft assertion class. Customize doAssert() method as per your need.I am using allure to manage the screenshots. You can have steps here to create your snapshots.

import java.util.Map;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.testng.asserts.Assertion;
import org.testng.asserts.IAssert;
import org.testng.collections.Maps;

import io.qameta.allure.Attachment;
import io.qameta.allure.Step;

/**
 * When an assertion fails, don't throw an exception but record the failure.
 * Calling {@code assertAll()} will cause an exception to be thrown if at least
 * one assertion failed.
 */
public class SoftAssert extends Assertion {
    // LinkedHashMap to preserve the order
    private final Map<AssertionError, IAssert<?>> m_errors = Maps.newLinkedHashMap();
    private String assertMessage = null;

    @Override
    protected void doAssert(IAssert<?> a) {
        onBeforeAssert(a);
        try {
            assertMessage = a.getMessage();
            a.doAssert();
            onAssertSuccess(a);
        } catch (AssertionError ex) {
            onAssertFailure(a, ex);
            m_errors.put(ex, a);
            saveScreenshot(assertMessage);
        } finally {
            onAfterAssert(a);
        }
    }

    public void assertAll() {
        if (!m_errors.isEmpty()) {
            StringBuilder sb = new StringBuilder("The following asserts failed:");
            boolean first = true;
            for (Map.Entry<AssertionError, IAssert<?>> ae : m_errors.entrySet()) {
                if (first) {
                    first = false;
                } else {
                    sb.append(",");
                }
                sb.append("\n\t");
                sb.append(ae.getKey().getMessage());
            }
            throw new AssertionError(sb.toString());
        }
    }

    @Step("Validation fail: {assertMessage}")
    @Attachment(value = "Page screenshot", type = "image/png")
    public byte[] saveScreenshot(String assertMessage) {
        byte[] screenshot = null;
        screenshot = ((TakesScreenshot) TestBase.driver).getScreenshotAs(OutputType.BYTES);
        return screenshot;
    }
}



回答3:


I was looking for a solution to get screenshot on both soft and hard asserts when using TestNG and I think I found what works for me. Generally, with SoftAssert you declare:

public static SoftAssert softAssert = new SoftAssert();

So you could soft assert like:

softAssert.assertEquals("String1","String1");
softAssert.assertAll();

still hard assert looks like:

Assert.assertEquals("String1","String1");

However, if you want to do screenshot with both soft and hard asserts, you have to @Override both soft and hard asserts separetely. Like:

package yourPackage;

import org.testng.asserts.IAssert;
import org.testng.asserts.SoftAssert;

public class CustomSoftAssert extends SoftAssert {

    @Override
    public void onAssertFailure(IAssert<?> a, AssertionError ex) {
          Methods.takeScreenshot();
    }
}

and

package yourPackage;

import org.testng.asserts.Assertion;
import org.testng.asserts.IAssert;

public class CustomHardAssert extends Assertion{

        @Override
        public void onAssertFailure(IAssert<?> assertCommand, AssertionError ex) {
              Methods.takeScreenshot();
        }
}

my Methods.takeScreenshot looks like this (it takes current time and uses it as a file name):

public static void takeScreenshot() {

    String pattern = "yyyy-MM-dd HH mm ss SSS";
    SimpleDateFormat simpleDateFormat =
            new SimpleDateFormat(pattern);

    String date = simpleDateFormat.format(new Date());

    try {
    File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(scrFile, new File("D:\\github\\path\\"
            + "Project\\test-output\\screenshots\\" + date + ".png"));
    }
    catch (Exception e) {
            e.printStackTrace();
        }
    }

Your Base or wherever you declare soft and hard asserts should have both of them:

public static CustomSoftAssert softAssert = new CustomSoftAssert();
public static CustomHardAssert hardAssert = new CustomHardAssert();

Now you can soft assert with screenshots like:

softAssert.assertEquals("String1","String1");
softAssert.assertAll();

and hard assert with screenshots like:

hardAssert.assertEquals("String1","String1");

I hope that helps, this all is new for me :)



来源:https://stackoverflow.com/questions/28080761/how-to-take-a-screenshot-for-soft-assert-in-selenium-or-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!