В Junit runner для Ecpipse есть одна очень удобная фича. На View JUnit есть область Failure Trace. В ней отображается информация о stack trace в случае падения теста (1). Если там кликнуть дважды по какой-то строчке (2), то Eclipse отыщет файл и установит курсор в заданной строке (3).
Очень удобно! Но... Читать дальше...
Но в случае использования тихих asserts такая возможность пропадает - там в Failure Trace выведется путь к методу
public static void throwAllAssertionErrors(AssertionError... errors), который и генерирует исключение.А что если я напишу свое исключение (Exception), которое будет давать возможность добавлять не только разные сообщения но и stack traces? Сказано сделано. Покопавшись немного в дебрях класса Throwable, я написал свою реализацию, которая реализует необходимое мне свойство.
package test;
import java.io.PrintWriter;
public class CombinedAssertionError extends AssertionError {
private Throwable[] throwables;
public CombinedAssertionError(String message, Throwable... throwables) {
super(message);
this.throwables = throwables;
}
public void printStackTrace(PrintWriter s) {
synchronized (s) {
super.printStackTrace(s);
for (Throwable throwable : throwables) {
if (throwable != null) {
printStackTraceAsCause(throwable, s);
}
}
}
}
private void printStackTraceAsCause(Throwable cause, PrintWriter s){
StackTraceElement[] trace = cause.getStackTrace();
s.println("By exception: " + cause);
for (StackTraceElement element : trace) {
s.println("\tat " + element);
}
// Recurse if we have a cause
Throwable ourCause = cause.getCause();
if (ourCause != null) {
printStackTraceAsCause(ourCause, s);
}
}
}
Вот, как это выглядит на практике. Допустим есть два тихих assert's и оба слетели в тесте (1). В данном случае CombinedAssertionError примет на вход два этих assert's и сформирует stack trace таким образом, что в нем будет 3 раздела. Первый будет сообщать о месте расположения CombinedAssertionError (2), второй - об месте расположения первого слетевшего assert (3) и третий - информацию про второй assert (4).
А вот пример для поиграться.
package test;
import test.CombinedAssertionError;
import junit.framework.TestCase;
public class MyTest extends TestCase {
private int count = 0;
public void test1() {
count++;
assertCount(0);
}
private void assertCount(int expected) {
AssertionError error1 = assertQuietEquals(expected, count);
AssertionError error2 = assertQuietEquals(expected + 1, count + 1);
if (error1 != null && error2 != null) {
throw new CombinedAssertionError("Bad count", error1, error2);
}
}
private AssertionError assertQuietEquals(int expected, int actual) {
try {
assertEquals(expected, actual);
} catch (AssertionError error) {
return error;
}
return null;
}
public void test2(){
count++;
assertCount(1);
}
}
Enjoy!



Комментариев нет:
Отправить комментарий