前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TestNG小技巧

TestNG小技巧

作者头像
Criss@陈磊
发布2020-04-24 19:26:22
6490
发布2020-04-24 19:26:22
举报
文章被收录于专栏:测试技术圈测试技术圈

前言

TestNG是目前很流行的Java测试框架之一,作为Java技术栈的小伙伴,TestNG也是我们做单元、接口、UI自动化的常用技术(当然Junit5很不错),所以也是入门技术之一。

那么,在实际应用中,我们常遇到的两个情况:

1、一个case有N个断言,我想执行全部断言后,最后给出testcase的执行结果,而不是在执行一个断言错误后,就终止该条testcase,判定失败。

2、在半夜执行某个testcase失败后,害怕testcase失败是因为网络等原因,期望在失败后重新再重试下。

今天介绍一下解决第一种场景的2种办法。

一、

  • 硬断言的修改方法。

①重新创建Assertion类,重写断言方法

代码语言:javascript
复制
/**     * 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;        }    }

②创建新的监听类

代码语言:javascript
复制
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;  }}

③加入监听注解

代码语言:javascript
复制
@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);    }
  }}

运行结果:

代码语言:javascript
复制
FAILED: testAssertionjava.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中,例如:

代码语言:javascript
复制
<listeners>    <listener class-name="com.framework.util.assertion.AssertionListener"></listener></listeners>

二、

  • 软断言

软断言运用了SoftAssert这个类。

代码语言:javascript
复制
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();
  }

执行结果如下:

代码语言:javascript
复制
FAILED: testSoftAssertjava.lang.AssertionError: The following asserts failed:1 is wrong, 3 is wrong

注意assertEquals断言的message一定要写,否则会出现信息是null的情况,如下:

代码语言:javascript
复制
   @Test  public void testSoftAssert() {        assertion.assertEquals("aaa", "bbb");    assertion.assertEquals("aaa", "aaa");    assertion.assertEquals("aaa", "ccc");    assertion.assertAll();
  }

执行结果如下,判断不错误信息:

代码语言:javascript
复制
FAILED: testSoftAssertjava.lang.AssertionError: The following asserts failed:null, null

小技巧:

对于每次实例化SoftAssert这个类,可以写到一个basecase里面,然后采用extends继承的方式。

下次再介绍一下testng的失败重试。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 质问 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档