Подтвердить что ты не робот

Повторное использование тестовых реализаций в JUnit 4?

У меня есть интерфейс, например:

public interface Thing {
  FrobResult frob(FrobInput); 
}

И несколько реализаций этого интерфейса (например, NormalThing, ImmutableThing, AsyncThing), которые я пытаюсь проверить.

Многие из моих методов тестирования действительно касаются обеспечения правильной реализации интерфейса и, таким образом, дублируются в каждой реализации Thing. В JUnit 3 общим решением для этого было бы создание базового класса (расширение TestCase), которое затем подклассифицировано каждым классом реализации. Но является ли это правильным подходом для JUnit 4?

Возможные альтернативы в (по-моему) возрастающем порядке предпочтения:

  • Cut'n'paste дублированные методы тестирования. Не СУХОЙ вообще, но я думаю, что менее опасно в тестах, чем в производственном коде.

  • Создайте абстрактный класс с помощью методов @Test и подкласс для каждого класса тестирования реализации. (Обычно видели с JUnit 3-тестами - это все-таки хороший способ пойти в JUnit 4?)

  • Поместите общие методы тестирования в класс-помощник и вызовите его для каждой реализации. (Состав вместо наследования.)

Какая лучшая практика для № 3? Может быть, тест @RunWith(Parameterized.class), который параметризуется при каждой реализации? Или есть лучший способ сделать это?

4b9b3361

Ответ 1

Да, это правильный подход к созданию базового класса, который затем подклассифицируется каждым классом реализации в JUnit4 тоже.

Я предпочитаю, чтобы базовый тестовый класс для интерфейса был abstract, т.е. ваш "альтернативный" 2, так как я получил хороший опыт в подделке иерархии наследования из производственного кода для тестового кода. Поэтому, если у вас есть интерфейс I и реализации S1, S2 и S3, вы создаете абстрактный тестовый класс TestI и тестовые классы TestS1, TestS2 и TestS3.

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

Ответ 2

Я использую подход № 2 для JUnit и TestNG тестовых примеров. Это наиболее удобно и легко поддерживать. Его также прямо подбирают (поскольку его родной для OOD является базовый класс, который имеет общие методы). Для меня классы unit test не отличаются от обычных классов проектов... поэтому я применяю аналогичные соображения дизайна.