Принудительно запускать JUnit по одному тесту за раз - PullRequest
7 голосов
/ 13 февраля 2009

У меня проблемная ситуация с некоторыми довольно продвинутыми модульными тестами (использующими PowerMock для mocking и JUnit 4.5). Не вдаваясь в подробности, первый тестовый пример тестового класса всегда будет успешным, но любые последующие тестовые примеры в одном и том же тестовом классе не пройдены. Однако, если я выберу запускать тестовый пример 5 из 10, например, он пройдет. Таким образом, все тесты проходят при индивидуальном запуске. Есть ли способ заставить JUnit запускать по одному тесту за раз? Я звоню JUnit из муравьиного сценария.

Мне известна проблема зависимых тестовых случаев, но я не могу точно определить, почему это так. В тестовых примерах нет сохраненных переменных, поэтому ничего не нужно делать в аннотации @Before. Вот почему я ищу экстренное решение, например, принудительное выполнение JUnit тестов по отдельности.

Ответы [ 9 ]

14 голосов
/ 30 января 2013

Мне известны все рекомендации, но, наконец, ответить на ваш вопрос здесь - простой способ добиться того, чего вы хотите. Просто поместите этот код в ваш тестовый набор:

Lock sequential = new ReentrantLock();

@Override
protected void setUp() throws Exception {
    super.setUp();
    sequential.lock();
}

@Override
protected void tearDown() throws Exception {
    sequential.unlock();
    super.tearDown();
}

При этом ни один тест не может начаться, пока не будет получена блокировка, и одновременно может быть получена только одна блокировка.

10 голосов
/ 13 февраля 2009

Кажется, что ваши тесты являются зависимыми, то есть выполнение case-X влияет на выполнение case-Y. Такой системы тестирования следует избегать (например: нет никакой гарантии порядка, в котором JUnit будет запускать ваши дела).

Вам следует провести рефакторинг ваших дел, чтобы сделать их независимыми друг от друга. Много раз использование методов @Before и @After может помочь вам распутать такие зависимости.

6 голосов
/ 13 февраля 2009

Ваша проблема не в том, что JUnit запускает все тесты одновременно, а в том, что вы не видите , почему тест не пройден. Решения:

  1. Добавьте больше проверок в тесты, чтобы убедиться, что каждая переменная действительно содержит то, что вы думаете
  2. Загрузите IDE из Интернета и используйте встроенный отладчик для просмотра различных переменных
  3. Дамп состояния ваших объектов непосредственно перед точкой, где тест не пройден.
  4. Используйте часть утверждений "message", чтобы вывести больше информации о причинах сбоя (см. Ниже)
  5. Отключить все тесты, кроме нескольких (в JUnit 3: заменить все строки «void test» на «void dtest» в вашем источнике; в JUnit 4: заменить «@Test» на «// D @ TEST»).

Пример:

assertEquals(list.toString(), 5, list.size());
3 голосов
/ 14 февраля 2009

Поздравления. Вы нашли ошибку. ; -)

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

2 голосов
/ 13 февраля 2009

Извините, если я не отвечу на ваш вопрос напрямую, но разве ваша проблема не в том, что именно должны решить TestCase.setUp () и TestCase.tearDown ()? Это методы, которые среда JUnit будет всегда вызывать до и после каждого тестового примера, и обычно они используются, чтобы гарантировать, что вы начинаете каждый тестовый случай в одном и том же состоянии.

См. Также JavaDoc для TestCase.

1 голос
/ 14 февраля 2009

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

Maven и Ant содержат параметр "forkmode" для запуска тестов JUnit, который указывает, получает ли каждый класс тестирования свою собственную JVM или все тесты выполняются в одной и той же JVM. Но у них нет возможности запуска каждого метода тестирования в своей собственной JVM.

0 голосов
/ 14 февраля 2009

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

0 голосов
/ 13 февраля 2009

Я знаю о проблеме зависимых тестовые случаи, но я не могу точно определить, почему это. Там нет сохраненных переменных через контрольные примеры, так что ничего сделать на аннотации @Before. Вот почему Я ищу экстренное решение как заставить JUnit запускать тесты в индивидуальном порядке.

Оператор @Before безвреден, потому что он вызывается для каждого теста. @ Before Class опасен, потому что он должен быть статическим.

0 голосов
/ 13 февраля 2009

Ваше описание показывает мне, что ваши юнит-тесты зависят друг от друга. То есть настоятельно не рекомендуется в модульных тестах.

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

Я знаю, это тебе не поможет. Проблема будет в ваших @BeforeClass или @Before заявлениях. Будут зависимости. Поэтому проведите рефакторинг и попытайтесь изолировать проблему.

Возможно, ваши макеты созданы в вашем @BeforeClass. Подумайте о том, чтобы поместить его в оператор @Before. Так что нет экземпляра, который длится дольше, чем контрольный пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...