<div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace">Приветствую!</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">  Вышел и активно развивается модуль Assert::Refute[1], суть такова:</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">    use Assert::Refute qw(:all);<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">    my ($foo, $bar);<br></div><div class="gmail_default" style="font-family:monospace,monospace">    # тут куча кода, который сложно протестировать</div><div class="gmail_default" style="font-family:monospace,monospace">    refute_these {</div><div class="gmail_default" style="font-family:monospace,monospace">         like $foo, qr/f?o?r?m?a?t/;</div><div class="gmail_default" style="font-family:monospace,monospace">         isa_ok $bar, "My::Module";<br></div><div class="gmail_default" style="font-family:monospace,monospace">    }; # carp, если условия не выполняются</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">Таким образом, создаётся (1) защита от дурака при изменении кода, рефакторингах и т.п. и (2) прототип будущего юнит-теста. <br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div style="font-family:monospace,monospace" class="gmail_default">Даже если речь не о легаси-коде, проверка инвариантов и разумных границ может быть полезна:</div><div style="font-family:monospace,monospace" class="gmail_default"><br></div><div style="font-family:monospace,monospace" class="gmail_default">    use Assert::Refute;</div><div style="font-family:monospace,monospace" class="gmail_default">    use ​Assert::Refute::T::Numeric qw(is_between);</div><div style="font-family:monospace,monospace" class="gmail_default">    refute_these {</div><div style="font-family:monospace,monospace" class="gmail_default">         is_between $price, 0.01, 1000, "Price within bounds";<br></div><div style="font-family:monospace,monospace" class="gmail_default">    };<br></div><br><div style="font-family:monospace,monospace" class="gmail_default">​По сути это контрактное программирование [2], только в оцень легковесной форме.​</div><br><div style="font-family:monospace,monospace" class="gmail_default">Что ещё есть:<br><br></div><div style="font-family:monospace,monospace" class="gmail_default"> * refute $reason, "explanation"; - очень мощный базовый метод, по сути это ok и diag в одном флаконе - если причина не тру, то всё хорошо, а если она тру, то понятно, что именно не так. </div><div style="font-family:monospace,monospace" class="gmail_default"><br></div><div style="font-family:monospace,monospace" class="gmail_default"> * subcontract "name" => sub { # тут условия } <br><br></div><div style="font-family:monospace,monospace" class="gmail_default">Аналог subtest, но работает не только в юнит-тестах (в юнит-тестах, таки да, просто вызов Test::Builder->subtest внутри). <br></div><div style="font-family:monospace,monospace" class="gmail_default"><br></div><div style="font-family:monospace,monospace" class="gmail_default"> * Assert::Refute::Build - конструирование собственных условий/проверок. В простейшём случае всё, что нужно - чистая функция, которая возвращает ложь, если всё хорошо, и _что именно_ пошло не так, если что-то пошло не так (ср. diff)<br><br></div><div style="font-family:monospace,monospace" class="gmail_default">  Под Test::More тоже будет работать точно так же, если его (или что угодно на базе Test::Builder, напр. Test::Exception) подключили раньше. <br></div><div style="font-family:monospace,monospace" class="gmail_default"><br></div><div style="font-family:monospace,monospace" class="gmail_default"> * Assert::Refute::Contract - прототип _настоящего_ контрактного программирования, пока что наиболее применим для тестирования тестов, написанных в предыдущем пункте. <br></div><div style="font-family:monospace,monospace" class="gmail_default"><br></div><div style="font-family:monospace,monospace" class="gmail_default"> * Assert::Refute::Exec - объектно-ориентированный интерфейс, если неохота поганить неймспейс всякими is и like и вообще хочется более тонкого контроля. <br></div><br><div class="gmail_default" style="font-family:monospace,monospace"> * Assert::Refute::T::* - немного дополнительный проверок, вроде "массив отсортирован так-то", "у хеша такие-то ключи" или "число от и до". <br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">А что с производительностью? Как-то так: <br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">bash# perl -MAssert::Refute=:all -we '$SIG{ALRM} = sub { $stop++ }; alarm 1; refute_these { like ++$i, qr/[0-9]/ while !$stop}; print $i'; <br>278022<br></div><div class="gmail_default" style="font-family:monospace,monospace">bash# grep MHz /proc/cpuinfo <br>cpu MHz         : 2400.070<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">Далее планируется: <br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">* управление тестами - plan, skip, bail_out, TODO</div><div class="gmail_default" style="font-family:monospace,monospace">* больше собственно проверок</div><div class="gmail_default" style="font-family:monospace,monospace">* полезные дополнения типа работы с временными файлами</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">Репо и анонс на perlmonks:</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><a href="https://github.com/dallaylaen/assert-refute-perl">https://github.com/dallaylaen/assert-refute-perl</a></div><div class="gmail_default" style="font-family:monospace,monospace"><a href="http://perlmonks.org/?node_id=1206533">http://perlmonks.org/?node_id=1206533</a><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">[1] <a href="https://metacpan.org/pod/Assert::Refute">https://metacpan.org/pod/Assert::Refute</a><br></div><div style="font-family:monospace,monospace" class="gmail_default">​[2]​ <a href="https://metacpan.org/pod/Class::Contract">https://metacpan.org/pod/Class::Contract</a></div><br>-- <br><div class="gmail_signature"><div dir="ltr"><div><div><div><font face="monospace,monospace">Konstantin S. Uvarin<br></font></div><font face="monospace,monospace">jabber: see <from><br></font></div><font face="monospace,monospace">skype: kuvarin<br></font></div><font face="monospace,monospace"><a href="http://github.com/dallaylaen" target="_blank">http://github.com/dallaylaen</a><br></font></div></div>
</div>