Добрый день.
Модуль Test::MockObject может оказаться полезным при эмуляции объектов и методов избранного класса. Для его установки и работы потребуются Module::Build, UNIVERSAL::isa, UNIVERSAL::can.
Рассмотрим небольшой пример. Пакет Bug.pm содержит методы для работы с багами, найденными в программном коде.
package Bug; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{SEVERITY} = undef; $self->{COMMENTS} = []; bless ($self, $class); return $self; } sub severity { my $self = shift; if (@_) { $self->{SEVERITY} = shift } return $self->{SEVERITY}; } sub comments { my $self = shift; if (@_) { $new_comment = shift; push(@{ $self->{COMMENTS} }, $new_comment); } return $self->{COMMENTS}; } 1;
Файл example1.pl служит примером обращения к методам класса:
#!/usr/bin/perl -w use Bug; use strict; my ($severity, $comment, $comments); my $bug = Bug->new(); $bug->severity ("Major"); $bug->comments("First Comment"); $bug->comments("Second Comment"); $comments = $bug->comments(); $severity = $bug->severity(); print "$severity\n"; foreach $comment (@ {$comments}) { print "$comment\n"; }
stylus:/tmp/Work # perl example1.pl Major First Comment Second Comment
Установим заглушки на класс и его методы:
#!/usr/bin/perl -w use Test::MockObject; use strict; my ($bug, $severity, $comment, $comments); my $mock = Test::MockObject->new(); Test::MockObject->fake_module('Bug', new => sub { $mock }); $mock->mock('comments', sub { return ["Mocked First Comment", "Mocked Second Comment", "Mocked Third Comment"]; }); $mock->set_always("severity", "Mocked Severity"); $bug = Bug->new(); $comments = $bug->comments(); $severity = $bug->severity(); print "$severity\n"; foreach $comment (@ {$comments}) { print "$comment\n"; }
Исходный класс Bug не загружен. Вместо него создан псевдокласс Bug с собственными методами.
stylus:/tmp/Work # perl example2.pl Mocked Severity Mocked First Comment Mocked Second Comment Mocked Third Comment
Подробные сведения о Test::MockObject можно почерпнуть в документации к модулю (perldoc Test::MockObject).
Отметим некоторую путаницу в терминах, которая возникает при использовании Test::MockObject. Согласно классификации Фаулера, представленное решение в большей степени подпадает под определение “заглушки” (stubs), нежели “имитаторы” (mocks). Терминология модульного тестирования не устоялась и по сей день, поэтому подобные расхождения легко объяснимы и не являются препятствием при создании тестов.
Управление модульными тестами в Perl легко организовать на основе пакетов, входящих в стандартную поставку (Test::Simple, Test::More). Дополнительную функциональность можно получить с помощью модулей, доступных на CPAN. Вот некоторые из них: Test::Unit, Test::Class, Test::SimpleUnit. Выбор в соответствии с контекстом будет наиболее эффективным.
См. также: Заглушки на подпрограммы в Perl.
Что такое качество программного обеспечения и как его улучшить: теория и практика, задачи и решения, подводные камни и обходные пути.
Автор комментария : Ivanych | March 3, 2009
Опять же, как и в предыдущей статье, про заглушки на подпрограммы, хотелось бы понять, зачем все это надо.
[Ответить]
Автор комментария : Капитан Аляска | March 3, 2009
Ivanych, ответил в комментарии к предыдущей статье.
[Ответить]
Автор комментария : Dmitry | March 3, 2009
А что это вы там пишете такое, не багтрекинговую ли систему на Perl?
[Ответить]
Автор комментария : Капитан Аляска | March 4, 2009
Dmitry, нет, это просто пример – раз объектом нашего внимания являются баги :) Системы отслеживания багов, написанные на Perl, есть уже довольно давно. Bugzilla, в частности.
[Ответить]
Автор комментария : Eldhenn | April 7, 2010
Замечательные статьи. Только примеры в них используются слишком сложные. Нужно было писать на примере программы “Hello, world!” для большей понятности. Тогда сразу будет ясно, как метод, прекрасно работающий в программе из одной строки, работает в проекте из десятков модулей и тысяч строк.
[Ответить]
Автор комментария : Капитан | April 8, 2010
Eldhenn, спасибо за теплые слова!
В какой-то мере соглашусь: чем проще пример, тем легче воспринимается. Но есть еще такой аспект: простейшие примеры есть в документации. И лично для меня сложность всегда состояла в том, что простенький пример из документации работает, но когда начинаешь делать что-то серьезное, то возникают трудности. Поэтому в статьях хочется идти чуть дальше: делать примеры чуть более сложными…
[Ответить]