SoftAssert:: why onAssertSuccess is called when assertion is failed

660 views
Skip to first unread message

sunny sachdeva

unread,
Sep 18, 2015, 4:50:15 AM9/18/15
to testng-users
Hi All,

I am trying to understand SoftAssert in TestNG. I have implemented own class extending Assertion class. As shown below my TestNG class contains only 1 test method which would fail. I dont understand since test assertion would fail then why onAssertSuccess is called.

Can some one help me in understanding this.

public class SoftAssert extends Assertion{
	private final Map<AssertionError, IAssert>	m_errors	= Maps.newHashMap();
	
	public  SoftAssert() {
	}
	@Override
	public void executeAssert(IAssert a)
	{
		try {
			a.doAssert();
		} catch (AssertionError ex) {
			m_errors.put(ex, a);
			onAssertFailure(a, ex);
		}
	}
	public void assertAll()
	{
		if (!m_errors.isEmpty()) {
			StringBuilder sb = new StringBuilder("The following asserts failed:\n");
			boolean first = true;
			for (Map.Entry<AssertionError, IAssert> ae : m_errors.entrySet()) {
				if (first) {
					first = false;
				} else {
					sb.append(", ");
				}
				sb.append(ae.getValue().getMessage());
			}
			throw new AssertionError(sb.toString());
		}
	}
	@Override
	public void onBeforeAssert(IAssert a)
	{
		Reporter.log("");
		Reporter.log("ASSERT DESCRIPTION: " + a.getMessage());
	}
	@Override
	public void onAssertFailure(IAssert a, AssertionError ex)
	{
		try {
			Reporter.log("Test Case Validation :: FAILED");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onAfterAssert(IAssert a)
	{
	}
	@Override
	public void onAssertSuccess(IAssert a){
		try{
			Reporter.log("On Assert Success");
		}catch(Exception e){
			
		}
	}
}

TestNG Class
public class TestSoftassert {
	private SoftAssert s_Assert=null;
	@BeforeMethod
	public void bm(Method m){
		s_Assert= new SoftAssert();
	}
	@Test
	public void testA(){
		s_Assert.assertTrue(false,"this is a failed test case");
		s_Assert.assertAll();
	}
}



Krishnan Mahadevan

unread,
Sep 19, 2015, 3:04:33 AM9/19/15
to testng...@googlegroups.com
Sunny,

The problem is because your version of executeAssert() doesn't throw an AssertionFailure when there is a failure encountered. Please change it to as below and try again.

@Override
public void executeAssert(IAssert a) {
try {
a.doAssert();
} catch (AssertionError ex) {
m_errors.put(ex, a);
        throw ex;
}
}
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...@googlegroups.com.
To post to this group, send email to testng...@googlegroups.com.
Visit this group at http://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

sunny sachdeva

unread,
Sep 19, 2015, 8:55:39 AM9/19/15
to testng-users
Yes it worked,Krishnan but still need to know more about its design. I thought doAssert would just stores the assert failures in a Map and at the end its assert all which marks the test case be it Pass/Fail/Skip. Would really appreciate if you can put some insight on this,

Thanks
Sunny

Krishnan Mahadevan

unread,
Sep 19, 2015, 10:51:39 PM9/19/15
to testng...@googlegroups.com
Sunny,

Here's how doAssert looks like in the Assertion class

protected void doAssert(IAssert<?> assertCommand) {
onBeforeAssert(assertCommand);
try {
executeAssert(assertCommand);
onAssertSuccess(assertCommand);
} catch(AssertionError ex) {
onAssertFailure(assertCommand, ex);
throw ex;
} finally {
onAfterAssert(assertCommand);
}
}

As you can see, if executeAssert() method wouldn't throw any Exceptions, then Java would continue to execute onAssertSuccess() which is what is happening in your case. By making executeAssert() throw assertion errors we are forcing Java to get into the catch() block and have it skip executing onAssertSuccess section !






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/

sunny sachdeva

unread,
Sep 20, 2015, 11:33:08 AM9/20/15
to testng-users
I got it. Sir thanks a lot for the explanation. As usual you are very prompt in helping the forum members.

Thanks again,

sunny sachdeva

unread,
Sep 30, 2015, 3:36:25 AM9/30/15
to testng-users
HI Krishnan,

There is one issue I encountered.Whats happening is If I throw AssertionError inside executeAssert then it is working exactly as Hard Asserts.

Second Assertion should be executed but its not working because I am throwing AssertionError inside executeAssert

public class TestSoftassert {
	private SoftAssert s_Assert=null;
	@BeforeMethod
	public void bm(Method m){
		s_Assert= new SoftAssert();
	}
	@Test
	public void testA(){
		s_Assert.assertTrue(false,"this is a failed test case");
                s_Assert.assertTrue(True,"this should be executed and shown in report");
s_Assert.assertAll(); } }

Could you please suggest what I am doing wrong here.

sunny sachdeva

unread,
Sep 30, 2015, 4:33:18 AM9/30/15
to testng-users
I guess I resolved it. What worked is , instead of overriding executeAssert, I actually overrided doAssert . In my version of doAssert, I am catching the assert failures in a Map and instead of throwing assertionError in doAssert , I am throwing it in assertAll.

protected void doAssert(IAssert assertCommand) {
 onBeforeAssert(assertCommand);
 try {
   executeAssert(assertCommand);
   onAssertSuccess(assertCommand);
 } catch(AssertionError ex) {
 m_errors.put(ex, assertCommand);
   onAssertFailure(assertCommand, ex);
  // throw ex;
 } finally {
   onAfterAssert(assertCommand);
Reply all
Reply to author
Forward
0 new messages