Хрупкие тесты

zerkms

TDD infected
Команда форума
Alexandre
ты бредишь. при чём тут Log? я написал, что при любом, даже самом правильном и оправданном наследовании класс-предок вполне может взять и измениться. в связи с изменившимися требованиями. и ничего в этом неправильного и страшного нет.
TDD и XP техники используются, чтобы риски по модификации снизить, а не исключить их вообще - не существует такого специалиста, который возьмёт и спроектирует на год вперёд всю архитектуру.
 

Alexandre

PHPПенсионер
Я сказал А
ты сказал В
и кто из нас бредит?
все в этой жизни относительно...

-~{}~ 12.05.09 02:08:

ну а если без обидок,
то ты мне так и не ответи: правильно это или нет?
и если не правильно, то чем тебе не понравилась процитированная мною фраза?
а если правильно - то докажи!

-~{}~ 12.05.09 02:11:

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

zerkms

TDD infected
Команда форума
только вот если ты не правильно построишь отношение иерархий, то соответственно и переделки в дальнейшем обойдутся значительно дороже!
тредстартовый вопрос подразумевает правильное проектирование. т.е. ситуация с проектированием идеализирована, а вопрос касается лишь тестирования.
а теперь перечитай последние посты с этой установкой.
 

StUV

Rotaredom
имхо, ключевое заблуждение
Вот я меняю класс B и тест для него. У меня появляется много красных тестов. Но я то знаю, что код правильный.
тесты должны (усредненно) покрывать "боевой" режим использования классов
и если изменения предка приводят к "покраснению" тестов потомков - значит с огромной вероятностью рушится и боевой код (обратное - просто "удачное совпадение")

(что при нормальной архитектуре происходит при изменении интерфейса класса Б - вполне логично, что это изменение _должно_ затронуть и клиентов класса)

--
ну... или прав cDLEON и у тредстартера:

Если ты меняешь код класса б, а тесты в классах А1,А2 ломаются, значит ты в классах А1,А2 ЯВНО тестируешь класс Б, вместо того, что бы тестировать классы А1,А2.
что конечно криво и неправильно...
 

cDLEON

Онанист РНРСlub
и что? из этого следует, что поведение класса-предка в процессе развития проекта не может измениться?
Вообще я не могу представить себе ситуацию, когда меняя класс предок, в потомках поломаются тесты на тот функционал, который работает в боевом режиме...
 

Lightning

Трудоголик
cDLEON
Вообще я не могу представить себе ситуацию, когда меняя класс предок, в потомках поломаются тесты на тот функционал, который работает в боевом режиме...
http://tinyurl.com/yeh8dr
http://tinyurl.com/rc95ah
 

cDLEON

Онанист РНРСlub
Ну и ? ) КАК!?!?! Меняя методы родителя, можно обломать тесты тестирующие методы ребёнков? Пои это не сломав функционала ? о_О
Научи меня так :(
 

Lightning

Трудоголик
Меняя методы родителя, можно обломать тесты тестирующие методы ребёнков?
Например, если методы ребенков вызывают методы родителя.

Но первоначально твой вопрос стоял так:
Вообще я не могу представить себе ситуацию, когда меняя класс предок, в потомках поломаются тесты на тот функционал, который работает в боевом режиме...
В качестве примера я привел ссылку на описание паттерна Template method. Т.е. когда некоторая общая логика потомков содержится в одном методе родителя, который вызывает методы, перегруженные в потомках. Меняем этот метод - меняется логика во всех потомках. Функционал не ломается, т.к. интерфейс не меняется, меняется "кусок" логики в одном методе.

И т.д. и т.п, примеров можно привести много.
 

Black Raven

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

Если ты тестируешь прозрачный ящик, то можешь выполнять только тесты для родителя и не выполнять для потомков.

Если я не прав - поправьте меня.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Black Raven
обычно для тестирования чайлда пишется специальный класс, который потомком используется вместо реального родительского
он воспроизводит интерфейс родительского и возвращает нужные данные
главное - сохраненять интерфейс родительского класса
т.е. у ТС или интерфейс поменялся (надо вернуть совместимость через прокладки), или тесты пишутся без моков
 

Lightning

Трудоголик
Black Raven
Молодец. И что дальше?

-~{}~ 14.05.09 20:52:

grigori
Да, в данном случае без моков, черный ящик. Интерфейс не меняется. Меняется логика в родителе.

-~{}~ 14.05.09 20:53:

обычно для тестирования чайлда пишется специальный класс, который потомком используется вместо реального родительского
он воспроизводит интерфейс родительского и возвращает нужные данные
Ну это если методы потомков вызывают методы родителя.
А если наоборот (Template method pattern в качестве примера), то так не получится.

-~{}~ 14.05.09 20:56:

Я считаю, что whirlwind и zerkms правы, в том плане, что абсолютно все связи моками забивать не нужно.

-~{}~ 14.05.09 21:09:

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

whirlwind

TDD infected, paranoid
Моки там у тебя или не моки, если ты поменяешь интерфейс класса, нельза гарантировать что класс-затычка среагирует лучше чем мок. Тип возвращаемого значения не укажешь ни для мока, ни для затычки. А тестировать чисто как черный ящик очень часто слишком накладно. В общем тут надо золотую середину искать. Я так делаю - если тестирование функционала базового в тесте потомка составляет проблему, заменяю на агрегацию.
 

cDLEON

Онанист РНРСlub
Например, если методы ребенков вызывают методы родителя
И дальше что ? Ты в тестах ребёнка вызываешь методы ребёнка? Методы ребёнка возвращают свой результат. И если у тебя ни чего не ломается - результат остаётся тем же.
 

Lightning

Трудоголик
И дальше что ? Ты в тестах ребёнка вызываешь методы ребёнка? Методы ребёнка возвращают свой результат. И если у тебя ни чего не ломается - результат остаётся тем же.
Результаты, возвращаемые методами потомка, могут зависеть от результатов, возвращаемых методами родителя.

-~{}~ 15.05.09 00:12:

whirlwind
Какая затычка?
 

whirlwind

TDD infected, paranoid
Lightning например ты пишешь фронт-контроллер. Вместо контроллера ты что используешь реальный класс чтоле? А фикстуру под него в каждом тесте не задалбываешься задавать?
 

Lightning

Трудоголик
whirlwind
Тестовый контроллер, который ничего не делает, это реальный класс?

-~{}~ 15.05.09 00:22:

А не, посмотрел, у меня мок.
 

whirlwind

TDD infected, paranoid
А чем он отличается от мока в плане диагностики ошибок? Если он ниче не делает, то это фикция, а не класс. Таких ситуаций очень мало, например когда зависимые классы инжектятся в контроллер фабрикой. Но тогда в первую очередь для теста нужна такая фабрика. А ничего не делающая фабрика сломает воркфлоу твоего фронта. Так что без функционирующих классов это врядли. А вот в этом плане тут разницы я особой не вижу, мок это будет или ты класс напишешь

PHP:
class MockFactory {
    protected $return;

    function __construct($returnController)
    {
          $this->return = $returnController;
    }

    function produce($bp)
    {
          return $this->return;
    }
}
те же яйца тока с боку. Говоря про моки, я имел в виду частичные моки, когда ты перекрываешь например фабричный метод, делегирующий фабрике. Это конечно полная изоляция, но тут у тебя теряется взаимодействие с соседними интерфейсами. И это чревато.
 

Lightning

Трудоголик
whirlwind
Подожди, я не могу понять:
что такое затычка? Это когда сам пишешь класс, вместо мока?
как это все к теме относиться?
 

whirlwind

TDD infected, paranoid
Затычка это класс, вместо мока. Класс, написанный специально для использование в тестах. К теме относится потому что ты спросил что такое затычка. А изначально я хотел донести, что лучше моков по соотношению объем работ/результат все равно ничего не придумаешь для тестирования. Просто нужно четко понимать где моки нужны, а где они нежелательны.

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

Lightning

Трудоголик
А еще оптимизировать тестирование классов часть поведения которых потенциально известна (то есть мы знаем что у них один базовый класс), можно за счет создания специального тест-кейса, от которого будут наследоваться тесты наследников. Это тоже способ сократить дублирование в тестах, а следовательно и количество причин ломания.
Ты такое делал?
Я пробовал так делать, получился мрак полнейший.

-~{}~ 15.05.09 01:14:

Это если в тестах явное дублирование, то такое наверное прокатит. А если не явное, то часть боевого кода продублируется в его тестах и получится ...
 
Сверху