суббота, 5 декабря 2009 г.

Две маленьких истории про JUnit

Никогда не считал себя знатоком библиотеки junit, но несколько дней назад она меня удивила, при этом 2 раза.
А все началось с того, что после небольшого рeфакторинга все тесты из одного класса начали падать с неожиданной ошибкой.


junit.framework.AssertionFailedError
at com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:108)


код, тестов был похож на этот:


public abstract class AbstactTest extends TestCase {
public AbstactTest(String name) {
super();
// do something else...
}
}

public class FileTest extends AbstactTest {

public FileTest(String name) {
super(name);
}

public void test1(){/*...*/}
public void test2(){/*...*/}
}


Около 10 минут не мог понять в чем ошибка: вроде бы всегда для тестов делал абстрактные классы, наследовал от них другие классы и все работало. Но не в этом случае.

Пришлось обратиться за помощью к коллеге.

А проблема оказалась в том, что конструктор класса FileTest перекрывает конструктор класса TestCase, принимающий значение типа String - имя теста. И даже не смотря на то, что при создании объекта AbstactTest вызывается конструктор класса TestCase без параметров нас это не спасает.
По всей видимости при запуске тестов вызывается конструктор у класса FileTest, а параметру name присваивается значение null. И что самое неприятное, что конструктор все-таки отрабатывает и c AssertionFailedError падают уже тесты. Ну да, я давно знал, что reflection - это отличная возможность выстрелить себе в ногу и вот, очередной раз в этом убедился.

В ходе дебаггинга выяснилась еще одна удивительная для меня особенность этих тестов.
После изменения класса FileTest


public FileTest() {
super(name);
System.out.println("Constructor");
}

public void setUp() {
System.out.println("SetUp");
}

public void test1() {
System.out.println("Test 1");
}

public void test2() {
System.out.println("Test 2");
}


В консоль вывелось:

Constructor
Constructor
SetUp
Test 1
SetUp
Test 2


Я всегда считал, что конструктор для всех тестов должен вызываться только один раз, а метод setUp для каждого теста перед его запуском. А тут получается, что для каждого теста конструктор вызывается заново, по-моему это может сильно увеличить время выполнения тестов.

Комментариев нет:

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