Как стать автором
Обновить

Комментарии 6

и еще одна презентация Spock vs JUnit, чтобы вдохновится и перестать бояться.
Я уже смотрел в сторону spock. Но, если честно, не вдохновляет. Если по существу, то, во-первых, одно другого не исключает, а скорее дополняет. А, во-вторых, spock — это груви, который далеко не всегда уместен.

Всё же не надо позволять функциональному подходу съедать мозг полностью. Вот, например, это:


public static BiFunction<String, Predicate<WebElement>, BaseMatcher<WebElement>> customMatcher = 
          (desc, pred) -> new BaseMatcher<T>() { ... };

Функциональное программирование во все поля. Кто мешал написать обычный метод?


public static BaseMatcher<WebElement> customMatcher(String desc, Predicate<WebElement> pred) {
    return new BaseMatcher<T>() { ... };
}

И вызывать не customMatcher.apply(desc, e -> blahblah), а просто customMatcher(desc, e -> blahblah)? А typedMatcher2 это просто должен быть метод от трёх аргументов (Class<T> cls, String desc, Predicate<WebElement> pred). Если по какой-то причине хочется класс зафиксировать (который вы, кстати, никак не используете), это делается с помощью карирования или частичного применения — стандартных ФП-паттернов. Зачем их изобретать вручную? Возьмите какой-нибудь javaslang и наслаждайтесь. Хотя мне здесь всё это кажется надуманной проблемой.

А вы в курсе что есть hamcrest, для которого можно просто обертку написать? И параметризация каким нить дата провайдером в JUnit? И junit5 с инжектами параметров, для того чтобы не нужно было делать странные конструкции по сопоставлению методов и названий?

Я, кстати, в библиотеке StreamEx активно использую ФП при тестировании в связке с обычным JUnit. Например, у меня есть методы mapFirst() и mapLast() (преобразовать первый и последний элементы стрима, оставив остальное как есть). Тест может выглядеть так:


streamEx(() -> StreamEx.of(0, 343, 999), 
          s -> assertEquals(asList(2, 343, 997), s.get().mapFirst(x -> x + 2).mapLast(x -> x - 2).toList()));

Метод streamEx принимает сапплаер стрима (должен уметь выдавать идентичные стримы) и консюмер сапплаера стрима. Казалось бы, можно было написать просто:


assertEquals(asList(2, 343, 997), StreamEx.of(0, 343, 999).get().mapFirst(x -> x + 2).mapLast(x -> x - 2).toList());

Но так тест становится гораздо хуже. Эта штука streamEx за кадром скрывает много магии, вызывая консюмер в разных условиях. Во первых, естественно, стрим может быть параллельным или последовательным. Параллельный стрим может быть создан просто так, а ещё к нему могут быть конкатенированы пустые стримы слева или справа (это покрывает некоторые специфические частные случаи, про которые можно забыть). Ещё есть специальный режим, когда параллельный стрим модифицируется так, что промежуточные вызовы trySplit помимо нормальной работы иногда случайно отщепляют пустые куски в произвольных местах (по спецификации это не должно влиять на результат). Ещё один режим — стрим транслируется в сплитератор, а сплитератор назад в стрим (это добавляет обёрток, но не должно ничего сломать). По факту каждый такой однострочный тест — шесть тестов в разных условиях. И я могу при желании добавить новые (например, искусственно удалять некоторые характеристики, которые должны влиять только на быстродействие, но не на результат).


А вот другая штука — тест сплитераторов:


checkSpliterator("Distinct-3", Arrays.asList("b"), 
                  () -> new DistinctSpliterator<>(Arrays.asList("a", null, "b", "c", "b", null, "c", "b").spliterator(), 3));

(DistinctSpliterator должен из входного сплитератора выбирать элементы, повторяющиеся не менее, чем заданное количество раз). Сплитератор (как и итератор) обходится только один раз, поэтому я подаю сапплайер сплитераторов. А эта штука checkSpliterator ничего не знает конкретно про DistinctSpliterator, но знает всё про контракт сплитератора и тестирует его во все поля. Обход через tryAdvance, forEachRemaining, частично tryAdvance, частично forEachRemaining, произвольное дерево сплитов с произвольным порядком дальнейшего обхода — всё должно дать одинаковый результат. Сапплаер по факту больше тысячи раз дёргается. С помощью этой штуки удавалось отловить очень хитрые баги.


В общем, ФП действительно полезно в юнит-тестировании, как многие другие техники программирования.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории