Test::More

Test::More - фреймворк для написания тестовых скриптов


Для начала необходимо составить тестовый план. Количество выполняемых тестов в скрипте с помощью:

use Test::More tests => 23;

В случае, если вы заранее не знаете, сколько тестов будет выполнено в скрипте, тогда вы объявляете их в конце файла.

use Test::More;
... ваши тесты ...
done_testing($number_of_tests_run);


Но если тестов очень много или вам лень их считать, то вы можете вообще не указывать $number_of_tests_run

В некоторых случаях вам нужно пропустить весь тестовый файл, так:

use Test::More skip_all => $skip_reason;


Используйте опцию 'import', если вы хотите контролировать какие функции будет экспортировать Test::More

use Test::More tests => 23, import => ['!fail'];


Когда вам нужно вычислить количество тестов, используйте plan() функцию.

use Test::More;
plan tests => keys %Stuff * 3;

Или вообще планировать запуск тестов, так:


use Test::More;
if( $^O eq 'MacOS' ) {
    plan skip_all => 'Test irrelevant on MacOS';
}
else {
    plan tests => 42;
}

done_testing();
done_testing($number_of_tests);

$number_of_tests - тоже самое, что plan()

Каждому тесту присваивается порядковый номер. Но еще полезно присваивать название каждому тесту.

Основная цель модуля - узнать, прошел тест на OK или not OK.


Методы


ok

ok($got eq $expected, $test_name);

Проверяем любое действие на успешность выполнения.


is
isnt

Сравнивает 1й аргумент со 2м. is - если равны, то ок, а isnt - если НЕ равны то ок.

# Is the ultimate answer 42?
is( ultimate_answer(), 42,          "Meaning of Life" );

# $foo isn't empty
isnt( $foo, '',     "Got some foo" );


like

like($got, qr/expected/, $test_name);

Проверяет на соответствие регулярному выражению.


unlike

unlike($got, qr/expected/, $test_name);

Проверяет на НЕсоответствие регулярному выражению.


cmp_ok

cmp_ok($got, $op, $expected, $test_name);

Вместо $op - можно использовать любую бинарную операцию (+, &&, и т.д)


can_ok

can_ok($module, @methods);
can_ok($object, @methods);

Проверяет, что модуль или объект может выполнить @methods.


isa_ok

isa_ok($object,   $class, $object_name);
isa_ok($subclass, $class, $object_name);
isa_ok($ref,      $type,  $ref_name);


Проверяет, что объект является экземпляром класса.


new_ok

my $obj = new_ok( $class );
my $obj = new_ok( $class => \@args );
my $obj = new_ok( $class => \@args, $object_name );
 
 
Комбинирует создание объекта и вызова isa_ok() на этом объекте.
 
 
subtest

subtest $name => \&code;

use Test::More tests => 3;
 
pass("First test");
 
subtest 'An example subtest' => sub {
    plan tests => 2;
 
    pass("This is a subtest");
    pass("So is this");
};
 
pass("Third test");
 
 
Вызывает подтест, со своим планом тестов, в главном скрипте подтест рассматривается, как один тест.


pass
fail
 
pass($test_name);
fail($test_name);


Просто говорят, что тест прошел на ok или на not ok.


Модульные тесты



use_ok

Проверяет, что модуль загружен удачно


BEGIN { use_ok($module); }
BEGIN { use_ok($module, @imports); }
 
обычно используется в блоке BEGIN, чтобы быть  уверенным, что модуль загружен удачно.


require_ok
 
require_ok($module);
require_ok($file);
 
Подобно use_ok(), но не загружает, а проверяет на доступность.
 

Смешанные структуры данных


is_deeply
 
is_deeply( $got, $expected, $test_name );


Подобно is(), но проверяет на равенство структуры данных, сравнивая данные на вложенных уровнях(подуровнях).
Для более точного сравнения используйте модули Test::Differences и Test::Deep.

Диагностика

diag
 
diag(@diagnostic_message);
ok( grep(/foo/, @users), "There's a foo user" ) or
    diag("Since there's no foo, check that /etc/bar is set up right");


Выводит диагностическое сообщение, в случае неудачного выполнения теста.


note

note(@diagnostic_message);

Просто заметка, которую хорошо использовать в отладке.



explain

my @dump = explain @diagnostic_message;
is_deeply($have, $want) || diag explain $have;
 
Используется для представления данных diag и note, в удобный для чтения вид.


Условные тесты


SKIP: BLOCK

SKIP: {
skip $why, $how_many if $condition;
...normal testing code goes here...
}
 
Пропускаем блок тестов, при определенных условиях.


SKIP: {
    eval { require HTML::Lint };
 
    skip "HTML::Lint not installed", 2 if $@;
 
    my $lint = new HTML::Lint;
    isa_ok( $lint, "HTML::Lint" );
 
    $lint->parse( $html );
    is( $lint->errors, 0, "No errors found in HTML" );
}



TODO: BLOCK
 
TODO: {
    local $TODO = $why if $condition;
 
    ...normal testing code goes here...
}


Тесты в TODO блоке ожидаются, что будут не выполнены.


todo_skip
TODO: {
    todo_skip $why, $how_many if $condition;
 
    ...normal testing code...


Пропускает тесты, помеченные, как TODO.


Контроль тестов


BAIL_OUT

BAIL_OUT($reason);

Прекращает выполнение тестов, если критическая часть программы недоступна (например соединение с БД)
Для лучшего контроля используйте Test::Most


builder
 
my $test_builder = Test::More->builder;


Для расширения возможностей Test::More когда получаем объект Test::Builder, который использует Test::More.

Коды выхода

0 - все тесты прошли успешно
255 - все не успешно
любое число - количество неудачных тестов (включая те, которые не запланированы)

Примечание: если у вас неудачно выполнилось больше чем 254 тестов, все равно будет выведено 254.

Заметки и предостережения

Использование utf-8

my $builder = Test::More->builder;
binmode $builder->output,         ":utf8";
binmode $builder->failure_output, ":utf8";
binmode $builder->todo_output,    ":utf8";


Использование потоков

use threads;
use Test::More;
# желательно именно в таком порядке