Исключить отдельные методы тестирования JUnit без изменения класса Test?

В настоящее время я повторно использую тесты JUnit 4 из другого проекта для своего кода. Я получаю их непосредственно из репозитория другого проекта как часть моей автоматизированной сборки Ant. Это здорово, так как это гарантирует, что мой код будет соответствовать самой последней версии тестов.

Однако есть подмножество тестов, которые я никогда не ожидаю пройти в своем коде. Но если я начну добавлять аннотации @Ignore к этим тестам, мне придется поддерживать собственную отдельную копию реализации теста, чего я действительно не хочу делать.

Есть ли способ исключить отдельные тесты без изменения источника теста? Вот что я просмотрел до сих пор:

  • Насколько я вижу, задача Ant JUnit позволяет исключить только целые классы Test, а не отдельные методы тестирования, так что мне это не подходит, мне нужна степень детализации методов.

  • Я решил собрать TestSuite, который использует отражение для динамического поиска и добавления всех исходных тестов, а затем добавить код для явного удаления тестов, которые я не хочу запускать. Но я отказался от этой идеи, когда заметил, что TestSuite API не предоставляет метод удаления тестов.

  • Я могу создавать свои собственные тестовые классы, которые расширяют исходные тестовые классы, переопределять определенные тесты, которые я не хочу запускать, и аннотировать их с помощью @Ignore. Затем я запускаю JUnit на своих подклассах. Недостатком здесь является то, что если в исходный проект добавляются новые тестовые классы, я не подберу их автоматически. Мне придется следить за новыми тестовыми классами по мере их добавления в исходный проект. Пока это мой лучший вариант, но он не идеален.

  • Единственный другой вариант, который я могу придумать, — это все равно запускать плохие тесты и игнорировать сбои. Тем не менее, эти тесты требуют времени для запуска (и проваливаются!), поэтому я бы предпочел не запускать их вообще. Кроме того, я не вижу способа указать задаче Ant игнорировать сбои в определенных методах тестирования (опять же - я вижу, как вы можете сделать это для отдельных тестовых классов, но не для методов).


person rewbs    schedule 02.09.2009    source источник


Ответы (7)


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

Создавайте тесты Ant специально, исключая суперклассы, чтобы запускались дополнительные классы, о которых вы не знаете.

Вы можете использовать аннотацию @Rule (новое для JUnit 4.7), чтобы узнать, какой тест выполняется, и прервать его (путем возврата пустой реализации оператора), а не переопределять определенные методы, что дает вам больше гибкости в том, чтобы знать, следует ли избегать теста. . Единственная проблема с этим методом заключается в том, что вы не можете остановить выполнение методов @Before с помощью этого метода, что может быть медленным. Если это проблема (и вы действительно не можете трогать тесты), то @Ignore в переопределенном методе - единственное, что я могу придумать.

Однако, если вы можете коснуться этих тестов, откроются некоторые дополнительные параметры:

Вы можете запустить их с помощью пользовательского бегуна, указав тег @RunWith в классе. Этот бегун просто передаст выполнение стандартному бегуну (JUnit4.class) в этом проекте, но в вашем проекте (через системное свойство или какой-либо другой механизм) проверит имя теста, а не запустит тест. Это имеет то преимущество, что оно наименее навязчиво, но наиболее сложно реализовать (бегуны — волосатые звери, одна из заявленных целей @Rule состояла в том, чтобы устранить большую часть необходимости их создавать).

Другой вариант — сделать в тесте оператор acceptThat, который будет проверять некоторые настройки конфигурации, которые будут истинными, если этот тест будет запущен. На самом деле это будет включать в себя внедрение прямо в тест, что, скорее всего, является нарушителем условий сделки во всем, что отдаленно помечено как «отдельный проект».

person Yishai    schedule 02.09.2009

Сейчас это вам не поможет, но TestNG поддерживает такую ​​возможность.

person Chris Kessel    schedule 02.09.2009

Хорошо, это довольно тяжеловесное решение, но не кидайте в меня вещами, если это звучит нелепо.

Ядром Junit4 является класс org.junit.runner.Runner и его различные подклассы, в первую очередь org.junit.runners.Suite. Эти бегуны определяют тесты для данного тестового класса, используя такие вещи, как @Test и @Ignore.

Довольно легко создавать пользовательские реализации бегуна, и обычно вы подключаете их, используя аннотацию @RunWith в своих тестовых классах, но очевидно, что это не вариант для вас.

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

Это было бы довольно много работы, и вам пришлось бы потратить время на копание в доисторической кодовой базе Ant Junit, чтобы узнать, как это работает. Однако инвестиции во времени могут быть оправданы.

Жаль только, что задача Junit Ant не предоставляет механизма для указания исполнителя тестов, что было бы идеально.

person skaffman    schedule 02.09.2009
comment
Я бы сказал, что реализация бегуна обманчиво проста. Я обнаружил, что копирую и вставляю код из других частей JUnit, чтобы пользовательский код работал должным образом, и он был очень хрупким - почти гарантированно сломается в новом выпуске. - person Yishai; 02.09.2009
comment
Все верно. Я никогда не утверждал, что это красиво :) - person skaffman; 03.09.2009

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

Если я не ошибаюсь, JUnit использует отражение, чтобы найти тестовые методы для выполнения. Затем операция переименования метода позволит вам удалить эти методы до того, как JUnit их найдет. Или метод можно модифицировать, чтобы он возвращался немедленно, без выполнения каких-либо операций.

Для изменения классов при загрузке можно использовать такую ​​библиотеку, как BCEL.

person Mario Ortegón    schedule 02.09.2009
comment
JUnit 4 использует аннотации вместо имен методов для определения запускаемых тестов. - person Yishai; 02.09.2009
comment
Было бы по-прежнему допустимо изменить метод для немедленного возврата. Но спасибо, я думал о JUnit3 - person Mario Ortegón; 02.09.2009
comment
Предположительно модификация байт-кода также может быть использована для добавления аннотаций @Ignore к методам в скомпилированных классах. - person rewbs; 02.09.2009

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

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

person Rob Spieldenner    schedule 02.09.2009

Если нежелательные тесты находятся в определенных классах/пакетах, вы можете использовать исключение набора файлов в Ant, чтобы исключить их во время импорта.

person Esko    schedule 02.09.2009
comment
Нет, к сожалению, мне нужно исключить определенные методы тестирования. То есть я хочу запустить некоторые тесты в данном классе Test, но не другие. - person rewbs; 02.09.2009

Два варианта

  1. Работайте с владельцем заимствованных тестов, чтобы выделить свои в отдельный класс, которым вы оба можете поделиться.
  2. Создайте свой собственный тестовый класс, который проксирует тестовый класс, который вы хотите использовать. Для каждого метода, который вы хотите включить, есть метод в вашем классе. Вам нужно будет создать экземпляр тестового класса, который вы вызываете, а также выполнить методы до и после, если они есть в оригинале.
  3. Создайте собственный бегун Junit на основе blockjunitrunner и используйте его для фильтрации или в тестах, которые вы хотите.
person Ashley Frieze    schedule 28.08.2015