Страницы

Поиск по вопросам

вторник, 27 ноября 2018 г.

юнит-тест для всех реализаций интерфейса

Есть некоторый java интерфейс. Он накладывает ограничения на сигнатуры методов. Хотелось бы еще ограничить возвращаемые значения некоторых методов или использование передаваемых аргументов заранее во всех реализациях. Т.е. зафиксировать это ограничение поведения в виде junit теста.
Например, есть
public interface Strategy { int choose(List choiceList) }
Метод choose должен выбирать только значение из передаваемого списка. Причем значения в списке могут быть только от 0 до 9. Т.е. возвращаемое значение тоже должно быть от 0 до 9. Да, можно было бы использовать enum вместо int, но это лишь упрощенная задача. Представьте, что может понадобится 100500 вариантов значений.
Можно ли написать junit тест, который будет запускаться для всех реализаций интерфейса, находящихся в проекте? Что для этого нужно сделать, прописать? Может есть альтернатива junit в данном вопросе?
Сам тест к интерфейсу из примера приводить не обязательно.


Ответ

Тут уж, как я полагаю, придется каждую реализацию интерфейса отправлять на тестирование. Но а если все реализации должны работать одинаково, то я бы сделал весь необходимый ряд тест-кейсов, которые работают именно с интерфейсом. Ну а все реализации кропотливо скармливать туда. Приведу пример:
abstract class StrategyTest { protected test(Strategy strategy) { test1(strategy); test2(strategy); } private test1(Strategy strategy){/* тест кейс 1 */ } private test2(Strategy strategy){/* тест кейс 2 */} }
Ну и по всем реализациям останется как-то так сделать:
class StrategyImplTest extends StrategyTest { @Test public void testCoose() throws Exception { Strategy s = new StrategyImpl(); super.test(s); } }
Ну и так для каждой реализации будет класс с единственным тестом, который будет скармливать своему суперклассу объект для тестирования. Все assert'ы и так далее будут нормально отрабатывать и выбрасывать ошибку построения в мавене, если какой-то тест не сработает.
Если же надо какие-то дополнительные аннотации для методов и т.д., можно сделать красивее.
abstract class StrategyTest { @Test public void testCoose() throws Exception { Strategy s = getStrategy(); /* ваш код тестирования тут*/ } @Test public void testCoose1() throws Exception { Strategy s = getStrategy(); /* ваш код тестирования тут и так далее*/ } protected abstract Strategy getStrategy(); }
Ну и по всем реализациям останется как-то так сделать:
class StrategyImplTest extends StrategyTest { @Override public Strategy getStrategy() { Strategy s = new StrategyImpl(); return s; } }
Я считаю, что исхищряться и придумывать гениальные алгоритмы с рефлексией или чем-то там еще, которые бы автоматом находили все реализации, не надо, иначе вы будете "Дартом Тестиусом" :) который сделает непонятные для всех тесты, которых будет сложно поддерживать.

Комментариев нет:

Отправить комментарий