@Suite JUnit 4, передача данных, @Rule и устаревшие @Before и @After

Я работаю с некоторым устаревшим тестовым кодом, который использует класс TestSetup для настройки и отключения сервера вокруг тестового набора классов, содержащих тесты. Я преобразовал классы для использования аннотаций junit и попытался использовать аннотации @Suite и @Suite.Classes для определения набора. Но я ударился о стену.

Старая версия тестов расширяет TestSetup, чтобы перебирать все экземпляры тестовых классов и вводить в них различные ссылки на серверные объекты. Примером является ссылка на веб-контекст Spring framework.

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

Я изучил новые методы @Rule и MethodRule, но (честно говоря) они кажутся сложным, но ограниченным решением проблемы, которая на самом деле не ясна. Во всяком случае, я не мог понять, как они могли решить мою проблему. Дополнительная проблема заключается в том, что авторы JUnit намерены в конечном итоге удалить концепцию @Before/@After из JUnit.

Итак, кто-нибудь знает, как передавать данные из класса, аннотированного @Suite, в каждый тест, который выполняет класс Suite?


person drekka    schedule 04.02.2011    source источник
comment
Что такое передача данных фикстуры в созданные тестовые классы?   -  person 卢声远 Shengyuan Lu    schedule 04.02.2011


Ответы (2)


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

Известно, что наборы тестов в стиле JUnit4 более ограничены, чем наборы тестов в стиле JUnit3. Я слышал жалобы на это, но не знаю официального решения. Я думаю, что могут быть какие-то сторонние решения, которые пытаются решить эту проблему. Что касается вашей конкретной проблемы, я не думаю, что вы можете получить доступ к тестовым экземплярам из пакета в стиле JUnit4, потому что JUnit4 создает экземпляр теста прямо перед запуском метода.

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

Другой подход заключается в том, чтобы решить проблему общих ресурсов изнутри: в вашем случае тестовые классы объявляют с помощью @Rule, что им необходимо присутствие сервера. При первом выполнении правила оно запускает сервер, сохраняет соответствующую информацию в статических полях и делает все необходимое для подготовки теста. Например, он может внедрить некоторые поля теста или просто позволить тесту использовать API правила для получения необходимой информации. При следующем выполнении правило пропускает шаг «запустить сервер». Да, статическое состояние — зло, но иногда это единственный способ обойти ограничения JUnit. (Я не буду касаться здесь темы использования других фреймворков для тестирования.)

Большим преимуществом подхода «изнутри наружу» является то, что он позволяет вам запускать тестовые классы напрямую (без использования набора) и независимо друг от друга. Недостатком является то, что его может быть сложнее реализовать, и это затрудняет удаление ресурсов, не связанных с памятью (в вашем случае: выключение сервера). Чтобы выполнить последнее, вам придется использовать ловушку отключения JVM, потому что JUnit не обеспечивает адекватного обратного вызова. Хотя это, вероятно, сработает (поскольку инструменты сборки и IDE обычно используют отдельную JVM для каждого тестового запуска), тем не менее, это некрасиво.

Третий подход заключается в том, чтобы позволить вашему Ant/Maven/Gradle/любой сборке настроить/отключить общие ресурсы до/после запуска тестов. Опять же, это менее гибко и удобно, чем подход наизнанку, и поднимает вопрос о том, как передать информацию из сборки в JVM, на которой выполняются тесты (при необходимости). Типичным примером такого подхода является подключаемый модуль Maven Cargo.

И последнее, но не менее важное: вы можете попытаться быть прагматичным и запускать/останавливать сервер один раз за тестовый класс. Это очень просто реализовать, но может быть или не быть адекватным в вашей ситуации (например, это может занять слишком много времени).

Я изучил новые методы @Rule и MethodRule, но (честно говоря) они просто кажутся сложным, но ограниченным решением проблемы, которая на самом деле не ясна.

Правила — это способ написания модульных и многоразовых расширений JUnit. Гораздо лучше, чем использование базовых классов, где вы вскоре столкнетесь с проблемой одиночного наследования. Это еще более актуально для библиотек, поставляющих расширения JUnit.

Дополнительная проблема заключается в том, что авторы JUnit намерены в конечном итоге удалить концепцию @Before/@After из JUnit.

где ты услышал это? Не путаете ли вы это с xUnit.net, что настоятельно не рекомендует использовать метод установки/демонтажа? В любом случае, выполнение какого-либо действия до или после теста является одним из наиболее важных вариантов использования правил, поэтому я не думаю, что вам следует беспокоиться.

person Peter Niederwieser    schedule 04.02.2011
comment
Я не уверен, где я читал, что они уходят, но меня могли смутить комментарии к классу BlockJUnit4ClassRunner. Я прочитал так много блогов и руководств, пытаясь понять это, что легко запутаться. :-) - person drekka; 04.02.2011
comment
Спасибо за публикацию, это огромно. - person drekka; 04.02.2011

JUnit 4.9 готовит лучшее решение для этого в виде компоновщика, но я думаю, что до этого самый чистый (хотя и немного сложный в реализации) способ решить эту проблему — создать собственную реализацию Runner (расширить одну из существующих) . @Peter совершенно прав в том, что создание Suite имеет слабые стороны по сравнению с JUnit 3.8, хотя у него также есть некоторые сильные стороны.

person Yishai    schedule 04.02.2011