在实际应用中,我们常遇到的两个情况:
1、一个case有N个断言,我想执行全部断言后,最后给出testcase的执行结果,而不是在执行一个断言错误后,就终止该条testcase,判定失败。
2、在半夜执行某个testcase失败后,害怕testcase失败是因为网络等原因,期望在失败后重新再重试下。
今天介绍一下解决第一种场景的2种办法。
①重新创建Assertion类,重写断言方法
/**
* String对比
* @param actual
* @param expected
*/
public static void verifyEquals(Object actual, Object expected){
try{
Assert.assertEquals(actual, expected);
}catch(Error e){
errors.add(e);
flag = false;
}
}
/**
* String对比+msg
* @param actual
* @param expected
* @param message
*/
public static void verifyEquals(Object actual, Object expected, String message){
try{
Assert.assertEquals(actual, expected, message);
}catch(Error e){
errors.add(e);
flag = false;
}
}
②创建新的监听类
public class AssertionListener extends TestListenerAdapter {
@Override
public void onTestStart(ITestResult result) {
Assertion.flag = true;
Assertion.errors.clear();
}
@Override
public void onTestFailure(ITestResult tr) {
this.handleAssertion(tr);
}
@Override
public void onTestSkipped(ITestResult tr) {
this.handleAssertion(tr);
}
@Override
public void onTestSuccess(ITestResult tr) {
this.handleAssertion(tr);
}
private int index = 0;
/**
* 得到测试类所需的测试异常信息
*
* @param tr
*/
private void handleAssertion(ITestResult tr) {
if (!Assertion.flag) {
Throwable throwable = tr.getThrowable();
if (throwable == null) {
throwable = new Throwable();
}
StackTraceElement[] traces = throwable.getStackTrace();
StackTraceElement[] alltrace = new StackTraceElement[0];
for (Error e : Assertion.errors) {
StackTraceElement[] errorTraces = e.getStackTrace();
StackTraceElement[] et = this.getKeyStackTrace(tr, errorTraces);
StackTraceElement[] message = new StackTraceElement[] { new StackTraceElement("message : " + e.getMessage() + " in method : ", tr
.getMethod().getMethodName(), tr.getTestClass().getRealClass().getSimpleName(), index) };
index = 0;
alltrace = this.merge(alltrace, message);
alltrace = this.merge(alltrace, et);
}
if (traces != null) {
traces = this.getKeyStackTrace(tr, traces);
alltrace = this.merge(alltrace, traces);
}
throwable.setStackTrace(alltrace);
tr.setThrowable(throwable);
Assertion.flag = true;
Assertion.errors.clear();
tr.setStatus(ITestResult.FAILURE);
}
}
/**
* 根据测试类名获得该测试类的StackTraceElement数组
*
* @param tr
* @param stackTraceElements
* @return
*/
private StackTraceElement[] getKeyStackTrace(ITestResult tr, StackTraceElement[] stackTraceElements) {
List<StackTraceElement> ets = new ArrayList<StackTraceElement>();
for (StackTraceElement stackTraceElement : stackTraceElements) {
if (stackTraceElement.getClassName().equals(tr.getTestClass().getName())) {
ets.add(stackTraceElement);
index = stackTraceElement.getLineNumber();
}
}
StackTraceElement[] et = new StackTraceElement[ets.size()];
for (int i = 0; i < et.length; i++) {
et[i] = ets.get(i);
}
return et;
}
/**
* 合并两个StackTraceElement数组
*
* @param traces1
* @param traces2
* @return
*/
private StackTraceElement[] merge(StackTraceElement[] traces1, StackTraceElement[] traces2) {
StackTraceElement[] ste = new StackTraceElement[traces1.length + traces2.length];
for (int i = 0; i < traces1.length; i++) {
ste[i] = traces1[i];
}
for (int i = 0; i < traces2.length; i++) {
ste[traces1.length + i] = traces2[i];
}
return ste;
}
}
③加入监听注解
@Listeners(AssertionListener.class)
public class MyTest {
@Test
public void testAssertion() {
beforeClass();
try {
Assertion.verifyEquals("aaa", "bbb", "aaa is wrong");
Assertion.verifyEquals("aaa", "aaa");
Assertion.verifyEquals("aaa", "ccc");
} catch (Exception e) {
logger.error("testAssertion:", e);
}
}
}
运行结果:
FAILED: testAssertion
java.lang.Throwable
at message : aaa is wrong expected [bbb] but found [aaa] in method : .testAssertion(LogonTest:41)
at com.testcase.LogonTest.testAssertion(LogonTest.java:41)
at message : expected [ccc] but found [aaa] in method : .testAssertion(LogonTest:43)
at com.testcase.LogonTest.testAssertion(LogonTest.java:43)
小技巧:
为了省事一些可以把@Listeners放到testng.xml中,例如:
<listeners>
<listener class-name="com.framework.util.assertion.AssertionListener"></listener>
</listeners>
-
软断言
软断言运用了SoftAssert这个类。
private SoftAssert assertion = new SoftAssert();
@Test
public void testSoftAssert() {
assertion.assertEquals("aaa", "bbb", "1 is wrong");
assertion.assertEquals("aaa", "aaa", "2 is wrong");
assertion.assertEquals("aaa", "ccc", "3 is wrong");
assertion.assertAll();
}
执行结果如下:
FAILED: testSoftAssert
java.lang.AssertionError: The following asserts failed:
1 is wrong, 3 is wrong
注意assertEquals断言的message一定要写,否则会出现信息是null的情况,如下:
@Test
public void testSoftAssert() {
assertion.assertEquals("aaa", "bbb");
assertion.assertEquals("aaa", "aaa");
assertion.assertEquals("aaa", "ccc");
assertion.assertAll();
}
执行结果如下,判断不错误信息:
FAILED: testSoftAssert
java.lang.AssertionError: The following asserts failed:
null, null
小技巧:
对于每次实例化SoftAssert这个类,可以写到一个basecase里面,然后采用extends继承的方式。
下次再介绍一下testng的失败重试。