Мокове

7 views
Skip to first unread message

Stefan Kanev

unread,
Oct 4, 2010, 9:14:58 AM10/4/10
to software-crafts...@googlegroups.com
Димитър Аз-Съм-Явар-Ама-Уча-Руби Панайотов попита нещо за мокове на [блога си](http://idimitar.blogspot.com/2010/10/mocks.html), при което и аз и Христо му отговорихме в леко различни посоки. Написах коментар, пуснах го, после си помислих че глупавия blogspot ме е отрязал и го написах наново, доста по-чисто. Оказа се че не, ама така и така си играх, ето по-ревизираната версия:

Аз съм от тези, които мокват за щяло и нещяло. Тествам в пълна изолация. Или поне опитвам. Ето няколко причини.

Първо, позволява ми да държа дизайна чист. За да можеш да тестваш нещо с мокове се налага ред неща да бъдат изрядни. Трябва да имаш добра кохезия, трябва да имаш loose coupling и трябва да спазваш single responsibility principle. Иначе просто не става.

Второ, позволява ми да правя interface discovery. Представи си, че искам да добавя нещо, за което ми трябват два класа, единия клиент на другия. Започвам с по-външния, като по-вътрешния моквам в теста. Когато съм готов, имам ясна идея какъв е дизайнът на другия клас. Още повече, измислил съм добри имена на съобщенията и съм начертал ясни граници между двата. Така също се фокусирам на едно нещо в даден момент.

Трето, тестовете в изолация ми позволяват да рефакторирам агресивно. В Rails има модели и контролери. Ако тестовете на контролерите са написани в интеграция, те периодично се чупят докато рефакторираш модела. Като правя така ми се случва да имам 52 червени теста -- 2 за модела, който пипам в момента и 50 за контролери, които въобще не ме интересуват, понеже още не съм приключил с модела (демек има лош defect isolation). Това ме забавя драматично, понеже или трябва да стоя на червено дълго, или трябва за всяка единица време прекарана в модела да прекарвам поне още толкова в оправяне на контролери.

Четвърто, моковете ми дават добра обратна връзка за дизайна ми. Когато нещо се моква трудно, това обикновено значи че дизайнът му е лош. Когато нещо се моква лесно, значи е добър. Тази неща са доста по-трудно забележими без тестове в изолация, понеже са качество на група от обекти и не си личат ясно докато гледаш кода на само един от тях. Важно е човек да слуша тестовете си.

Пето, прави тестовете бързи. Ако пишеш тестове за контролери в интеграция, те са много бавни. Скоростта на тестовете е важна, ако се опираш на тях да дизайн.

Впрочем, когато ползваш мокове, пишеш два слоя тестове. Вътрешен, от unit тестове в изолация (rspec) и външен, който тества системата от край до край (cucumber). Първите са бързи и се пускат много често, докато вторите може да са малко по-бавни, понеже се пускат по-рядко.

Ако искаш да схванеш идеята ясно, прочети Growing Object-Oriented Software, Guided by Tests. Тя показва много по-добре за какво служат моковете и как те ръководят дизайна. Говори и за идеята с двата слоя тестове. Пълна е с примери, което е важно, понеже това е единствения начин да научиш мокове, който знам. Другата добра книга и The RSpec Book, разбира се.

Та, въпроса ми? Кой тук тества догматично в изолация и кой избягва мокове, освен по краищата на системата (където се наричат "стъбове"). И защо?

Petyo Ivanov

unread,
Oct 4, 2010, 10:12:14 AM10/4/10
to software-crafts...@googlegroups.com
Не знам доколко моците са лесни в другите езици. В руби да мандахерцаш
моци наляво надясно е лесно и евтино. В C# - май не толкова.

Съгласен съм с всичко което изброи, и ще изброя притесненията си,
по-скоро за пълнота.

Опасна играчка са в ръцете на неопитен човек. Лесно можеш да се
"намочиш", и да тестваш "въздух", или прекалена специфика. После те е
страх да рефакторнеш, щото ще потрошиш прекалено много тестове. Ако
имаш по-неопитен човек в екипа, могат да забъркат големи каши, дори и
при най-добро желание от страна на всички.

Аз самия моча винаги, когато не знам как да дизайна нещо. Което е често.

2010/10/4 Stefan Kanev <stefan...@gmail.com>:

Radoslav Stankov

unread,
Oct 5, 2010, 5:26:24 AM10/5/10
to Software craftsmanship Bulgaria
Когато започвах да пиша тестове, имах доста проблеми с mocks когато се
налагаше промяна по кода. Но с времето тези неща изчезнаха. Като цяло
дву-слойното тестване ми се струва най-удачния варянт. От една страна
за скоростта на тестовете, от друга много често докато си правя mock
обектите доста по-лесно ми се изяснява какво се иска от кода по лесно.
Още повече че напоследък гледам да избягам от много дебелия модел в
Rails и пробвам някой неща с композии на класове. И в този случай mock
става доста помага, защото ясно се вижда кой части от модела са
"независими" една от други.

Колкото до другите езици, честно казано там нямам на наблюдения. В
JavaScript съм пробвал 2-3 неща и там нещата ставах доста лесно.

Hristo Deshev

unread,
Oct 4, 2010, 12:03:36 PM10/4/10
to software-crafts...@googlegroups.com
2010/10/4 Petyo Ivanov <unde...@gmail.com>

Не знам доколко моците са лесни в другите езици. В руби да мандахерцаш
моци наляво надясно е лесно и евтино. В C# - май не толкова.

И в C# не е трудно с правилната библиотека. Просто има два начина на писане и това да избереш единия или другия зависи от много неща: езикът, конкретният проблем, личните предпочитания. За мен често е по-ясно и по-лесно да имам някакъв междинен обект, който представя състоянието и да напиша тест срещу него отколкото да разхвърляш моци. Ето една хубава статия с истински код за едно нещо написано в двата стила:


Аз самият използвам и двата стила. В сегашния ми проект имам DI и мок библиотеки и за много неща моквам и проверявам интеракциите. За други пък правя точно обратното - имам междинно състояние, което проверявам или подавам като параметър. Когато мога работя със обекти-състояния и правя кода във възможно най-функционален стил. Ако се стремиш да избягваш екзотични странични ефекти и повечето ти код е прости операции, които получават параметри и връщат стойности отиваш и естествено в стила на състоянията. Предимството там е, че в повечето време работиш с истинските обекти. Недостатъкът е, че, ако не внимаваш, може да получиш странно не-OO решение, което нарушава "Tell, Don't Ask" правилото. Интеракциите ми изглеждат странни и трудни за следене - кой кого е викнал и кога.

Аз самия моча винаги, когато не знам как да дизайна нещо. Което е често.

Аналогът при състоянията е да произвеждаш малки и различни обекти, които да ти дават информация за конкретния момент. После евентуално ги обединяваш в по-големи, триеш едни, слагаш други и така докато стане :-)

Сега, за да сме максимално полезни трябва да разпишем още няколко примера за различни решения на един и същи проблем но от гледна точка на състоянията и интеракциите.

Поздрави,
Христо
Reply all
Reply to author
Forward
0 new messages