TestNG-斷言失敗不中斷運行

發表于:2020-4-23 09:38  作者:貓哥   來源:測試小圈子

字體: | 上一篇 | 下一篇 |我要投稿 | 推薦標簽:

  前言
  TestNG是目前很流行的Java測試框架之一,作為Java技術棧的小伙伴,TestNG也是我們做單元、接口、UI自動化的常用技術(當然Junit5很不錯),所以也是入門技術之一。
  那么,在實際應用中,我們常遇到的兩個情況:
  1、一個case有N個斷言,我想執行全部斷言后,最后給出testcase的執行結果,而不是在執行一個斷言錯誤后,就終止該條testcase,判定失敗。
  2、在半夜執行某個testcase失敗后,害怕testcase失敗是因為網絡等原因,期望在失敗后重新再重試下。
  今天介紹一下解決第一種場景的2種辦法。
  1.硬斷言的修改方法
  ①重新創建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>
  2.軟斷言
  軟斷言運用了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繼承的方式。

      本文內容不用于商業目的,如涉及知識產權問題,請權利人聯系博為峰小編(021-64471599-8017),我們將立即處理

【福利】填問卷送精選測試禮包+接口測試課程!為測試行業做點事!

評 論

論壇新帖

頂部 底部


建議使用IE 6.0以上瀏覽器,800×600以上分辨率,法律顧問:上海瀛東律師事務所 張楠律師
版權所有 上海博為峰軟件技術股份有限公司 Copyright©51testing.com 2003-2020, 滬ICP備05003035號
投訴及意見反饋:webmaster@51testing.com; 業務聯系:service@51testing.com 021-64471599-8017

滬公網安備 31010102002173號

51Testing官方微信

51Testing官方微博

掃一掃 測試知識全知道

日本av