Есть ли способ заставить Eclipse запускать тест JUnit несколько раз до сбоя? - PullRequest
27 голосов
/ 02 декабря 2009

У нас иногда бывают ошибки, которые появляются один раз при каждом запуске X. Прежде чем люди проверят вещи (где это автоматически JUnit'd), наши разработчики должны передать JUnit локально через Eclipse.

Есть ли какой-нибудь удобный способ (встроенный или высококачественный плагин), чтобы Eclipse запускал один и тот же тест X раз и останавливался в случае сбоя? Альтернатива простому нажатию кнопки Run X times?

Обратите внимание, что я ищу что-то в пользовательском интерфейсе (например, щелкните правой кнопкой мыши и скажите «Выполнить X раз» вместо просто «Выполнить»).

Ответы [ 7 ]

11 голосов
/ 02 декабря 2009

Если цикл for работает, то я согласен с номерами.

Если вам нужно повторить все настройки-тест-демонтажа, вы можете использовать TestSuite:

  1. Щелкните правой кнопкой мыши на пакете, содержащем тест, чтобы повторить
  2. Перейдите на Новый и выберите создание тестового набора JUnit
  3. Убедитесь, что выбран только тот тест, который вы хотите повторить, и нажмите, чтобы закончить.
  4. Отредактируйте файл, чтобы запустить его несколько раз.

В файле вы просто найдете

addTestSuite(YourTestClass.class)

, и оберните это в цикл for.

Я почти уверен, что вы можете использовать addTest вместо addTestSuite, чтобы заставить его запускать только один тест из этого класса, если вы просто хотите повторить один метод тестирования.

7 голосов
/ 09 декабря 2009

Если вы действительно хотите запустить тестовый класс до сбоя, вам нужен собственный бегун.

@RunWith(RunUntilFailure.class)
public class YourClass {

    // ....

}

, который может быть реализован следующим образом ...

package com.example;

import org.junit.internal.runners.*;
import org.junit.runner.notification.*;
import org.junit.runner.*;

public class RunUntilFailure extends Runner {

    private TestClassRunner runner;

    public RunUntilFailure(Class<?> klass) throws InitializationError {
        this.runner = new TestClassRunner(klass);
    }

    @Override
    public Description getDescription() {
        Description description = Description.createSuiteDescription("Run until failure");
        description.addChild(runner.getDescription());
        return description;
    }

    @Override
    public void run(RunNotifier notifier) {
        class L extends RunListener {
            boolean fail = false;
            public void testFailure(Failure failure) throws Exception { fail = true; }
        }
        L listener = new L();
        notifier.addListener(listener);
        while (!listener.fail) runner.run(notifier);
    }

}

... выпуская непроверенный код, чувствуя вину TDD :)

3 голосов
/ 22 июня 2012

Основываясь на ответе @ akuhn, вот что я придумал - вместо того, чтобы работать вечно, он будет выполняться 50 раз или до отказа, в зависимости от того, что произойдет раньше.

package com.foo    

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class RunManyTimesUntilFailure extends Runner {

    private static final int MAX_RUN_COUNT = 50;

    private BlockJUnit4ClassRunner runner;

    @SuppressWarnings("unchecked")
    public RunManyTimesUntilFailure(final Class testClass) throws InitializationError {
        runner = new BlockJUnit4ClassRunner(testClass); 
    }

    @Override
    public Description getDescription() {
        final Description description = Description.createSuiteDescription("Run many times until failure");
        description.addChild(runner.getDescription());
        return description;
    }

    @Override
    public void run(final RunNotifier notifier) {
        class L extends RunListener {
            boolean shouldContinue = true;
            int runCount = 0;

            @Override
            public void testFailure(@SuppressWarnings("unused") final Failure failure) throws Exception {
                shouldContinue = false;
            }

            @Override
            public void testFinished(@SuppressWarnings("unused") Description description) throws Exception {
                runCount++;

                shouldContinue = (shouldContinue && runCount < MAX_RUN_COUNT);
            }
        }

        final L listener = new L();
        notifier.addListener(listener);

        while (listener.shouldContinue) {
            runner.run(notifier);
        }
    }
}
3 голосов
/ 08 апреля 2011

Вот пост, который я написал, который показывает несколько способов многократного запуска тестов с примерами кода: http://codehowtos.blogspot.com/2011/04/run-junit-test-repeatedly.html

Вы можете использовать @Parametrized runner или использовать специальный бегун, включенный в пост Также есть ссылка на реализацию @Retry

3 голосов
/ 02 декабря 2009

Я знаю, что он не отвечает на вопрос напрямую, но если тест не проходит каждый раз, когда он выполняется, это тестовый запах, известный как Ошибочный тест . Для этого есть несколько возможных причин (из xUnit Test Patterns ):

  • Взаимодействующие тесты
  • Взаимодействующие тестовые наборы
  • Одинокий тест
  • утечка ресурсов
  • Ресурсный оптимизм
  • Неповторимый тест
  • Test Run War
  • Недетерминированный тест

Подробности каждого из них описаны в главе 16 xUnit Test Patterns .

2 голосов
/ 10 июня 2015

Возможно реализовать такой цикл с TestRule с (начиная с JUnit 4.9)

Очень простая реализация, которая запускается каждый тест 10 раз:

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class SimpleRepeatRule implements TestRule {

    private static class SimpleRepeatStatement extends Statement {

        private final Statement statement;

        private SimpleRepeatStatement(Statement statement) {
            this.statement = statement;
        }

        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < 10; i++) {
                statement.evaluate();
            }
        }
    }

    @Override
    public Statement apply(Statement statement, Description description) {
        return new SimpleRepeatStatement(statement);
    }
}

использование:

public class Run10TimesTest {

   @Rule
   public SimpleRepeatRule repeatRule = new SimpleRepeatRule();

   @Test
   public void myTest(){...}
}

Для более полезной реализации , основанной на аннотации, которая определяет, какой метод тестирования должен выполняться, как часто вы смотрите на этот блог: http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/

2 голосов
/ 02 декабря 2009

Я не верю, что у junit есть какой-то способ сделать именно то, что вы просите.

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

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