JUnit путаница: использовать «extends TestCase» или «@Test»? - PullRequest
143 голосов
/ 14 апреля 2010

Я нашел правильное использование (или, по крайней мере, документацию) 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);
    }
}

Смешение двух, кажется, не очень хорошая идея, см. Например. этот вопрос переполнения стека :

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

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

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

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

Редактировать: я добавил версии JUnit для обоих подходов

Ответы [ 5 ]

109 голосов
/ 14 апреля 2010

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

  • расширение 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
  }
}
24 голосов
/ 14 апреля 2010

У меня есть предпочтение 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 */
}
15 голосов
/ 14 апреля 2010

В вашем вопросе есть неотвеченная часть, а именно: «Как правильно группировать тесты для подхода B?»

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

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

4 голосов
/ 14 апреля 2010

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

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

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

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

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

1 голос
/ 14 апреля 2010
  1. «Предпочтительным» подходом будет использование аннотаций, которые были введены начиная с Junit 4. Они облегчают многие вещи (см. Ваш второй вопрос)

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


public void testForException() {
    try {
        Integer.parseInt("just a string");
        fail("Exception should have been thrown");
    } catch (final Exception e) {
        // expected
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...