Пропускать или падать в параметризованных тестах, если нет входных данных (Junit Vintage vs Jupiter)

parameterized
jupiter
junit
java
Теги: #<Tag:0x00007fedb8ab5290> #<Tag:0x00007fedb8abbfa0> #<Tag:0x00007fedb8abbe60> #<Tag:0x00007fedb8abbcf8>

(Михаил Братухин) #1

Добрый день!
Вопрос к бывалым о junit5, он же junit-jupiter.
Столкнулся с такой его особенностью, что на винтажной версии (или на 4.12), если задавать @Parameterized.Parameter поле, то если из метода вернётся пустая коллекция значений, то данный тест не будет запущен вовсе и не будет никаких ошибок. Это если запускать класс, а не метод.
Пример такого кода:

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

@RunWith(Parameterized.class)
public class TestVintage {

    @Parameterized.Parameter
    public Integer number;

    @Parameterized.Parameters
    public static Collection<Integer> data() {
        return Arrays.asList(new Integer[] {
//                 0 , 1, 2 , 3, 4, 5, 6, 8
        });
    }

    @Before
    public void setup(){
        Assume.assumeFalse(number == 4);
    }

    @Test
    public void getTest(){
        System.out.println("number = " + number);
    }
}

В то же время в новой версии junit’а данная технология претерпела изменения:
Вот пример, кода:

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class JupiterTests{

    @BeforeEach
    void init() {
    }

    @ParameterizedTest(name = "Test №{0} Параметризированный тест! Value = {arguments}")
//    @ValueSource(ints = {1, 2, 3, 4, 5, 6, 7})
    @ValueSource(ints = {})
    void parametrizedTest(int num, TestInfo testInfo) {
        Assumptions.assumeFalse(num == 4 || num == 7);
        System.out.println("number = " + num);
    }
}

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

И вот у меня вопрос, если так было сделано, то наверно за этим стоит какая-то идея и почему работа в том виде, как было в junit4 не устроила разработчиков junit5? Стоит ли мне заниматься доработкой функционала, чтобы параметризованные сценарии вели себя максимально приближенно к предыдущей версии junit’а или же это неправильно запускать пустые классы без входных данных и нужно обязательно падать при этом?

Раньше я на эту логику накручивал построение динамического дерева тестов по категориям внутри самих данных. Спорное решение, конечно, но зато местами было весьма удобно запускать/отлаживать не все тесты, а только часть по каким-то категориям, а также исключать не удаляя полностью тесты из выборки, например, убирая их в категорию для доработки.

В текущей реализации из того, что увидел пока работает только через Assumptions внутри теста, но тогда он будет запущен, а также выполнены все блоки BeforeEach, BeforeAll, конструкторы и статик блоки. В старой же версии, успевали сработать только статичные блоки, даже BeforeClass не отрабатывал. Либо же не пытаться Skip’ать тест, и падать…

P.S. новые динамические тесты не предлагайте, это как по мне вообще какая-то шляпа с кучей непонятных проблем и ограничений.


(rpwheeler) #2

По-моему тут дело не в бывалости, а в простом довольно таки вопросе: Является ли ситуация когда “из метода вернётся пустая коллекция значений” нормальной?

Я даже своего мнения тут предлагать не буду, для себя решайте. Если она является, то на нее особой реакции не надо, пусть все идет как есть. Если она не является, то по идее достаточно вставки одного ассерта на то что эта коллекция не пустая — и если она пустая, то тест будет падать ровно на этом ассерте.


(Михаил Братухин) #3

Да, всё упирается в виденье инстумента и как его применять. У меня вопрос вообще не один, а из трех частей. По какой-то причине разработчики junit изменили поведение своего фрейморка и у меня возник закономерный вопрос: сделали ли они так специально и чем руководствовались или же так произошло непреднамеренно.

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

Вторая проблема - нет возможности напрямую передать данные параметризированного теста в BeforeEach метод, либо в конструктор класса. В итоге Before методы становятся менее востребованными, т.к. они не владеют данными теста. Причем TestInfo объект передается нормально, а вот параметр специально обрезается при передаче. Это мне кажется уже большей проблемой, чем exeption для пустой коллекции.

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