JUnit confusion: использовать '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-style): создайте класс "normal" и добавьте аннотацию @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);
    }
}

Смешивание двух, кажется, не очень хорошая идея, см., например, qaru.site/info/48641/...:

Теперь, мои вопросы (вопросы):

  • Какой предпочтительный подход, или когда вы используете его вместо другого?
  • Подход B позволяет тестировать исключения, расширяя аннотацию @Test, как в @Test(expected = ArithmeticException.class). Но как вы проверяете исключения при использовании подхода A?
  • При использовании подхода A вы можете сгруппировать несколько тестовых классов в тестовом наборе, например:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class);

    Но это нельзя использовать с подходом B (так как каждый тестовый класс должен подклассифицировать TestCase). Каков подходящий способ групповых тестов для подхода B?

Изменить: я добавил версии JUnit для обоих подходов

Ответ 1

Различие довольно просто:

  • расширение 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
  }
}

Ответ 2

Я предпочитаю 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 */
}

Ответ 3

На ваш вопрос есть неотвеченная часть, и это "Каков надлежащий способ группировать тесты для подхода B?"

Официальным ответом является то, что вы комментируете класс с @RunWith (Suite.class), а затем используйте аннотацию @Suite.SuiteClasses для перечисления классов. Вот как это делают разработчики JUnit (перечисление каждого класса в пакете вручную). Во многом этот подход является улучшением, поскольку тривиальным и интуитивно понятным для добавления перед набором и после поведения пакета (просто добавьте метод @BeforeClass и @AfterClass в класс, аннотированный с помощью @RunWith - намного лучше, чем старый TestFixture).

Однако он имеет шаг назад, в этом аннотации не позволяют динамически создавать список классов, и работа над этой проблемой становится немного уродливой. Вы должны подклассифицировать класс Suite и динамически создавать массив классов в подклассе и передавать его в конструктор Suite, но это неполное решение в том, что другие подклассы Suite (такие как Категории) не работают с ним и по существу не поддерживают динамическую коллекцию тестовых классов.

Ответ 4

Вы должны использовать JUnit 4. Это лучше.

Многие фреймворки начали обесценивать поддержку JUnit 3.8.

Это из справочной документации Spring 3.0:

[Предупреждение] Класс Legacy JUnit 3.8 иерархия устарела

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

Ответ 5

  • "Предпочтительным" подходом было бы использование аннотаций, которые были введены с июня 4. Они облегчают многое (см. второй вопрос)

  • Для этого можно использовать простой блок try/catch:


public void testForException() {
    try {
        Integer.parseInt("just a string");
        fail("Exception should have been thrown");
    } catch (final Exception e) {
        // expected
    }
}