JUnit путаница: использовать "extends TestCase" или "@Test"?
Я нашел правильное использование (или, по крайней мере, документацию) JUnit очень запутанным. Этот вопрос служит как будущей ссылкой, так и реальным вопросом.
Если я правильно понял, есть два основных подхода к созданию и запуску теста JUnit:
Подход A (стиль JUnit 3): создайте класс, расширяющий TestCase, и запустите методы тестирования со словом test
, При запуске класса в качестве теста JUnit (в Eclipse) все методы начинаются со слова test
автоматически запускаются.
import junit.framework.TestCase;
public class DummyTestA extends TestCase {
public void testSum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}
Подход B (стиль JUnit 4): создайте "нормальный" класс и добавьте @Test
аннотация к методу. Обратите внимание, что вам не нужно начинать метод со слова test
,
import org.junit.*;
import static org.junit.Assert.*;
public class DummyTestB {
@Test
public void Sum() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}
Смешение этих двух не является хорошей идеей, см., Например, этот вопрос stackru:
Теперь мои вопросы:
- Какой предпочтительный подход, или когда вы бы использовали один вместо другого?
- Подход B позволяет тестировать исключения, расширяя аннотацию @Test, как в
@Test(expected = ArithmeticException.class)
, Но как вы проверяете исключения при использовании подхода А? При использовании подхода A вы можете сгруппировать несколько классов тестов в набор тестов следующим образом:
TestSuite suite = new TestSuite("All tests");
suite.addTestSuite(DummyTestA.class);
suite.addTestSuite(DummyTestAbis.class);
Но это не может быть использовано с подходом B (поскольку каждый тестовый класс должен быть подклассом TestCase). Как правильно группировать тесты для подхода B?
Изменить: я добавил версии JUnit для обоих подходов
5 ответов
Различие довольно простое:
- простирающийся
TestCase
способ написания модульных тестов в JUnit 3 (конечно, он все еще поддерживается в JUnit 4) - с использованием
@Test
аннотация - способ, представленный JUnit 4
Как правило, вы должны выбирать путь аннотации, если только не требуется совместимость с JUnit 3 (и / или версией Java более ранней, чем Java 5). Новый способ имеет несколько преимуществ:
-
@Test
annotaton более явный и его легче поддерживать в инструментах (например, таким образом легко найти все тесты) - Несколько методов могут быть аннотированы
@Before
/@BeforeClass
а также@After
/@AfterClass
обеспечение большей гибкости - Поддержка для
@Rule
аннотации на такие вещи, какExpectedException
- Поддержка для
@Ignored
аннотирование - Поддержка альтернативных тестовых бегунов, использующих
@RunWith
Чтобы проверить ожидаемые исключения в JUnit 3 TestCase
Вы должны сделать текст явным.
public void testMyException() {
try {
objectUnderTest.myMethod(EVIL_ARGUMENT);
fail("myMethod did not throw an Exception!");
} catch (MyException e) {
// ok!
// check for properties of exception here, if desired
}
}
У меня есть предпочтение JUnit 4 (аннотированный подход), потому что я считаю его более гибким.
Если вы хотите собрать набор тестов в JUnit 4, вы должны создать класс, объединяющий все тесты, подобные этому:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
Test1.class,
Test2.class,
Test3.class,
Test4.class
})public class TestSuite
{
/* empty class */
}
В вашем вопросе есть неотвеченная часть, а именно: "Как правильно группировать тесты для подхода B"?
Официальный ответ заключается в том, что вы аннотируете класс с помощью @RunWith(Suite.class), а затем используете аннотацию @Suite.SuiteClasses для вывода списка классов. Вот как это делают разработчики JUnit (перечисляя каждый класс в наборе вручную). Во многих отношениях этот подход является улучшением в том смысле, что его тривиально и интуитивно понятно добавить до поведения пакета и после пакета (просто добавьте методы @BeforeClass и @AfterClass в класс, аннотированный @RunWith - гораздо лучше, чем старая TestFixture).).
Тем не менее, он имеет шаг назад, поскольку аннотации не позволяют динамически создавать список классов, и решение этой проблемы становится немного уродливым. Вы должны создать подкласс класса Suite и динамически создать массив классов в подклассе и передать его конструктору Suite, но это неполное решение в том смысле, что другие подклассы Suite (такие как Categories) не работают с ним и по существу не поддерживают динамический набор классов Test.
Вы должны использовать JUnit 4. Это лучше.
Многие фреймворки начали осуждать поддержку JUnit 3.8.
Это из справочной документации по Spring 3.0:
[Предупреждение] Устаревшая иерархия классов JUnit 3.8 устарела
В общем, вы всегда должны пытаться использовать последнюю стабильную версию фреймворка, когда запускаете что-то новое.
"Предпочтительным" подходом будет использование аннотаций, которые были введены начиная с Junit 4. Они облегчают многие вещи (см. Ваш второй вопрос)
Вы можете использовать простой блок try/catch для этого:
public void testForException() {
try {
Integer.parseInt("just a string");
fail("Exception should have been thrown");
} catch (final Exception e) {
// expected
}
}