2015-05-15 3 views
1

Я использую правило JUnit для немедленного повторного запуска любых неудачных тестов. Мое дополнительное требование заключается в том, что если повторный запуск также завершился неудачей, определите, не удалось ли они по той же причине.Каков правильный способ сравнить два комбайна?

Для этого я скорректировал код от this answer, чтобы сохранить записи об ошибках и сравнить их. Однако сравнение (.equals) всегда оценивается как ложное, несмотря на то, что они не работают по той же причине. Каков наилучший способ сделать это?

private Statement statement(final Statement base, final Description description) { 
    return new Statement() { 
     @Override 
     public void evaluate() throws Throwable { 

     for (int i = 0; i < retryCount; i++) { 
      try { 
      base.evaluate(); 
      return; 
      } catch (Throwable t) { 
      System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); 

      // Compare this error with the one before it. 
      if (errors.size() > 0) { 
       if (t.equals(errors.get(errors.size() - 1))) { 
       System.out.println("The error is the same as the previous one!"); 
       } else { 
       System.out.println("The error is different from the previous one."); 
       } 
      } 

      errors.add(t); 
      } 
     } 
     System.err.println(description.getDisplayName() + ": giving up after " + retryCount 
      + " failures"); 

     // Throw most recent error. 
     throw errors.get(errors.size() - 1); 
     } 
    }; 
    } 
+5

В чем заключается причина, по которой вы хотите сравнить их? Что должно быть «по той же причине»? (Одинаковые строки стека? Тот же оператор 'throw'? Идентичные аргументы метода, вызвавшие сбой?) Правильный способ может быть многого. – Radiodef

+2

Если ваши тесты могут не работать по разным причинам без изменения кода, они не очень надежны – nicopico

ответ

1

Равенство для Throwable определяется как «то же самое Throwable». (Он сравнивает ссылки.)


«По той же причине» - это то, о чем вам нужно подумать и определить для своего приложения.

Одним из способов мы могли бы определить это "тот же самый тип и свободно тот же throw заявление":

static boolean sameTypeAndLine(Throwable t1, Throwable t2) { 
    if (t1.getClass() == t2.getClass()) { 
     StackTraceElement[] trace1 = t1.getStackTrace(); 
     StackTraceElement[] trace2 = t2.getStackTrace(); 
     return trace1[0].equals(trace2[0]); 
    } else { 
     return false; 
    } 
} 

Но до сих пор двусмысленность:

  • if (bad1 || bad2) { 
        // same throw site, different conditions 
        throw new Exception(...); 
    } 
    
  • // throws NullPointerExeption 
    // (was it foo or the result of bar() that was null?) 
    Object baz = foo.bar().baz(); 
    

Итак, лучшая вещь лет и можно сделать, это четко определить причины для исключения:

class MyException { 
    final Reason reason; 

    MyException(Reason reason) { 
     this.reason = reason; 
    } 

    // or a class, or whatever you need 
    enum Reason {A, B, C} 
} 

И проверить против них. Затем дополнительно используйте стиль кодирования, который предотвращает неоднозначность.

1

Equals не применяется должным образом для исключений. Вам придется сравнивать сообщение и/или трассировку стека самостоятельно.

1

Вы можете только сравнить:

по имени

t.getClass().getName() 

или InstanceOf

t instanceof XXXXXXX 
2

Используйте instance of, если хотите знать, только если тип любого класса, как :

if(t instanceof Throwable){ 
    //... 
} 
Смежные вопросы