问题
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