Using soft assertion does not attach correct snapshot for failed test

854 views
Skip to first unread message

garvitag...@gmail.com

unread,
Dec 7, 2017, 4:07:30 AM12/7/17
to testng-users
Hi,

I am using soft assertion for validating charts. At end of test i write assertAll() because i am using multiple assertions in one test. Assertion failures are reported correctly. Screenshot is attached for every failed test case.

Issue is :
As assertAll() is last line in test(supposed to be), when it reports that test is failed- screenshot is taken for current open page. Can we add screenshot when assertion fails?

Example :
Class util
{
  // contains create_chart(String parameter) method

  // 3 assertions are done everytime create_chart() method is called.
}

Class PieChart()
{
    util.create_chart("companies");    // if one assertion fails here, test continues and as test is reported fail after executing last line in test, screenshot is                                                                take for that screen.
    util.create_chart("year");
    assertAll();
}


Can i attach screenshot at time when assertion fails?

Thanks !!

⇜Krishnan Mahadevan⇝

unread,
Dec 7, 2017, 4:18:31 AM12/7/17
to testng...@googlegroups.com
Here's how you do it.

  1. subclass org.testng.asserts.SoftAssert
  2. Override org.testng.asserts.Assertion#onAssertFailure(org.testng.asserts.IAssert<?>, java.lang.AssertionError) and include your screenshot recording logic
  3. Have all of your tests use the subclassed variant of SoftAssert [ That you created in (1) ]

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users+unsubscribe@googlegroups.com.
To post to this group, send email to testng...@googlegroups.com.
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

garvitag...@gmail.com

unread,
Jan 11, 2018, 7:08:46 AM1/11/18
to testng-users
Hi Krishnan,

I tried above way, i am facing few concerns :

1. I overrided onAssertFailure(), here i called method from Base class to capture screenshot.
 Below is code in Base class to capture screenshot and add it to allure report :

Class Base()
{
// screenshot taken if test case fails

@AfterMethod
    protected void screenShotIfFail(ITestResult result) throws IOException {
        if (!result.isSuccess()) {
            takeScreenShot(result.getMethod());
        }
    }
  
 @Attachment(value = "Page Screenshot", type = "image/png")
    private byte[] takeScreenShot(String name) throws IOException {
        String path = getRelativePath(name);
        File screenShot = ((TakesScreenshot) driver)
                .getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenShot, new File(path));

        String filename = makeScreenShotFileName(name);
        System.out.println("Taking Screenshot! " + filename);
        // Allure.addAttachment(filename, screenShot);
        Reporter.log("<a href=" + path + " target='_blank' >" + filename
                + "</a>");
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    }

    protected void takeScreenShot(ITestNGMethod testMethod) throws IOException {
        String nameScreenShot = testMethod.getTestClass().getRealClass()
                .getSimpleName()
                + "_" + testMethod.getMethodName();
        takeScreenShot(nameScreenShot);
    }
    
    private String makeScreenShotFileName(String name) {
        DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy_hh.mm.ss");
        Date date = new Date();
        return dateFormat.format(date) + "_" + name + ".png";
    }

    private String getRelativePath(String name) throws IOException {
        Path path = Paths.get(".", "target", "surefire-reports", "screenShots",
                makeScreenShotFileName(name));
        File directory = new File(path.toString());
        return directory.getCanonicalPath();
    }
}

Solutions tried :
1. I tried passing method name by this in Assertions class that extends SoftAssert :

ITestNGMethod name;

    public void setUp(ITestResult result) {

        name = result.getMethod();
    }
public void onAssertFailure(org.testng.asserts.IAssert A,
            java.lang.AssertionError ax) {
                Base b = new Base();
                b.takeScreenShot(name);
     }

But it passed null.

2. I tried getting method name using Thread.currentThread.getStackTrace() and called takeScreenShot(ITestNGMethod testMethod) from base class.
it returned calling method not test method. But snapshots were taken correctly. If i use this, snapshots are not attached to corresponding test method in allure report. 

Now, snapshots are taken at point when assertion fails but as test completes, softassertall() declares test as failed. and due to this snapshot code is written in @After test, it takes a snapshot again of last screen.

Is there any way to solve above?

Thanks !!
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users...@googlegroups.com.

Krishnan Mahadevan

unread,
Jan 11, 2018, 11:46:40 AM1/11/18
to testng...@googlegroups.com

I didn’t quite understand what is the problem. But it looks like you are trying to grab hold of the current @Test method’s ITestResult object from within some method that is invoked via a @Test method.

 

For doing that, you can always access the current @Test method’s ITestResult via Reporter.getCurrentTestResult() method.

 

Thanks & Regards

Krishnan Mahadevan

 

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"

My Scribblings @ http://wakened-cognition.blogspot.com/

My Technical Scribbings @ http://rationaleemotions.wordpress.com/

 

garvitag...@gmail.com

unread,
Jan 12, 2018, 12:15:51 AM1/12/18
to testng-users
Reporter.getCurrentTestResult() helped .  Correct screenshots are attached to report.

Class chart()
{

softassert.assertTrue(expected, actual); // it fails, screenshot taken

// other functionalities

softassert.assertAll();  // @Test failed and screenshot taken again of last screen because of @After Test method
}

Is there a way to skip @AfterTest in case there is only assertion failure in test?

Thanks !1

garvitag...@gmail.com

unread,
Jan 12, 2018, 12:55:18 AM1/12/18
to testng-users
I found a workout, set a Boolean flag before assertAll() to true. It worked.

Thanks a lot !!!

⇜Krishnan Mahadevan⇝

unread,
Jan 12, 2018, 11:04:48 AM1/12/18
to testng...@googlegroups.com

No out of the box exists. You would need to build this on your own by retrieving the current ITestContext and then checking if it has any failures and if so then skip the execution of @AfterTest.

satish trimukhe

unread,
Feb 25, 2019, 2:58:45 AM2/25/19
to testng-users
Hi Garvit

I am beginner in automation, I am using above code  and screenshot is taken for current open page only.
can you please let me know where and how you have set the  Boolean flag before assertAll() to true.

Arun Mozhi

unread,
Jun 9, 2020, 3:59:47 AM6/9/20
to testng-users

Hi, 

Can you please share you solution for this. i am facing similar issue.

Regards,
Arun Mozhi S
Reply all
Reply to author
Forward
0 new messages