В 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!
Комментариев нет:
Отправить комментарий