Junit4: Метод @Parameters выполняется перед инициализацией @ClassRule. Может ли быть наоборот?

Созданный на 2 мая 2013  ·  9Комментарии  ·  Источник: junit-team/junit4

У меня следующая проблема (с использованием _junit 4.11_):

    <strong i="6">@ClassRule</strong>
    public static TemporaryFolder tmp = new TemporaryFolder();
    ...
    <strong i="7">@Parameters</strong>
    public static Collection<Object[]> data() throws Exception {
        return java.util.Arrays.asList(new Object[][] {
            {0, tmp.getRoot().getPath()}
        });
    }

Это приводит к ошибке инициализации

java.lang.IllegalStateException: the temporary folder has not yet been created
    at org.junit.rules.TemporaryFolder.getRoot(TemporaryFolder.java:127)

Таким образом, кажется, что метод _@Parameters_ выполняется до фазы инициализации _ClassRule_, что делает сценарии, подобные приведенному выше, немного сложными.

Самый полезный комментарий

Текущий обходной путь:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Он работает, но ему нужна ручная очистка...

Все 9 Комментарий

Текущий обходной путь:

    protected static TemporaryFolder initStaticTemp() {
        try {
            return new TemporaryFolder() { { before(); } };
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    public static TemporaryFolder tmp = initStaticTemp();

    <strong i="6">@AfterClass</strong>
    public static cleanup() throws Exception {
        tmp.delete();
    }

Он работает, но ему нужна ручная очистка...

+1

Немного подумав об этом, я думаю, что хорошим способом реализовать это было бы введение аннотации для этого:

<strong i="7">@Parameters</strong>
<strong i="8">@AfterClassRules</strong>
public Object[][] generateParameters() {
    // do stuff
}

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

Я пишу дополнительный комментарий, потому что не уверен, вызывает ли обновление комментария уведомление.

Будет ли дизайн, предложенный в моем предыдущем комментарии, приемлемым для сопровождающих? Если да, то я бы начал работу над пулл-реквестом.

Здесь есть довольно сложная архитектурная проблема: JUnit обещает таким исполнителям, как Eclipse, что он может перечислить, сколько тестов существует, прежде чем любой из тестов будет запущен, но также хочет минимизировать любые ресурсы, потребляемые на этом этапе планирования. Поэтому мы действительно хотим знать, сколько параметров будет, прежде чем мы, например, создадим какие-либо временные папки или сделаем еще более радикальные вещи, которые отображаются в ClassRules, такие как запуск серверов.

Возможно, моим любимым ответом было бы включить что-то вроде @DataPoints в теориях: могут быть статические поля или статические методы с префиксом @ParameterSet , которые объединяются для создания полного набора параметров. Таким образом, ваш пример будет:

@ClassRule public static TemporaryFolder tmp = new TemporaryFolder();
@ParameterSet public static Object[] first = new Object[] { 0 };
@ParameterSet общедоступный статический объект [] второй () {
вернуть новый объект [] { tmp.getRoot().getPath(); }
}

Дело в том, что мы могли бы считать метод «вторым», фактически не выполняя его.

Как вы думаете?

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

Вот тест, в котором я изначально столкнулся с проблемой: CryptoAppExecReturnCodeTest.java

@dsaff Я подумаю над вашим предложением. Первоначальное впечатление: разбиение пар на отдельные массивы требует особого внимания к позициям элементов (немного подвержено ошибкам). Так что я могу в конечном итоге заполнить _first_ какими-то фиктивными вещами (просто сохраняя количество элементов); и в _second_ - я хотел бы, чтобы элементы пары находились рядом друг с другом:

{ 0, tmp...getPath() },
{ 1, ... }

Есть ли что-то еще, что нужно бегунам, кроме количества тестов? (Например, может быть, имена тестов?)

@javornikolov , я только что понял, что неправильно прочитал ваш первоначальный пост, поэтому мой ответ, вероятно, сбил с толку. Я читал ваш тест как два разных экземпляра тестового класса, построенного с одним параметром; теперь, когда я прочитал это снова, на самом деле это один экземпляр тестового класса, созданный с двумя параметрами. Чтобы скорректировать мое предложение, предлагаемый код будет таким:

<strong i="7">@ClassRule</strong> public static TemporaryFolder tmp = new TemporaryFolder();
<strong i="8">@ParameterSet</strong> public static Object[] only() {
return new Object[] { 0, tmp.getRoot().getPath(); }
}

Я надеюсь, что это делает мое намерение более ясным; извините за мое первоначальное замешательство.

(проходя через некоторые старые ошибки)

Возможно, нам следует переименовать эту проблему в «Включить что-то вроде @DataPoints в теориях»?

(проходя через некоторые старые ошибки)

Возможно, нам следует переименовать эту проблему в «Включить что-то вроде @DataPoints в теориях»?

Я бы сказал, что проблема заключается в том, чтобы иметь возможность использовать ресурсы Rule в списке параметров для параметризованных тестов. Подход с @ParameterSet , предложенный @dsaff , кажется мне жизнеспособным (при условии, что оценки происходят в такой последовательности, что исходная проблема решена).
Но если «что-то вроде @DataPoints» достаточно ясно и нет риска отклониться в каком-то направлении, не охватывающем исходный сценарий: для меня все в порядке.
Причина, по которой я предпочитаю параметризованные тесты теориям (которые используют DataPoints), заключается в том, что результаты последних не сообщаются независимо для каждого набора параметров, и что первая ошибка прерывает выполнение последующих параметров.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги