Spec-Zone.ru › Perl 5.34

Тест

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • СИНОПСИС
  • ОПИСАНИЕ
  • РУКОВОДСТВО ПО БЫСТРОМУ НАЧАЛУ
    • Функции
  • ТИПЫ ТЕСТОВ
  • ПРИ НЕУДАЧЕ
  • ОШИБКИ И ОСОБЕННОСТИ
  • СРЕДА
  • ПРИМЕЧАНИЕ
  • СМОТРИТЕ ТАКЖЕ
  • АВТОР

НАЗВАНИЕ

Test - предоставляет простую структуру для написания скриптов тестов

СИНОПСИС

use strict;
use Test;

# use a BEGIN block so we print our plan before MyModule is loaded
BEGIN { plan tests => 14, todo => [3,4] }

# load your module...
use MyModule;

# Helpful notes.  All note-lines must start with a "#".
print "# I'm testing MyModule version $MyModule::VERSION\n";

ok(0); # failure
ok(1); # success

ok(0); # ok, expected failure (see todo list, above)
ok(1); # surprise success!

ok(0,1);             # failure: '0' ne '1'
ok('broke','fixed'); # failure: 'broke' ne 'fixed'
ok('fixed','fixed'); # success: 'fixed' eq 'fixed'
ok('fixed',qr/x/);   # success: 'fixed' =~ qr/x/

ok(sub { 1+1 }, 2);  # success: '2' eq '2'
ok(sub { 1+1 }, 3);  # failure: '2' ne '3'

my @list = (0,0);
ok @list, 3, "\@list=".join(',',@list);      #extra notes
ok 'segmentation fault', '/(?i)success/';    #regex match

skip(
  $^O =~ m/MSWin/ ? "Skip if MSWin" : 0,  # whether to skip
  $foo, $bar  # arguments just like for ok(...)
);
skip(
  $^O =~ m/MSWin/ ? 0 : "Skip unless MSWin",  # whether to skip
  $foo, $bar  # arguments just like for ok(...)
);

ОПИСАНИЕ

Этот модуль упрощает задачу написания файлов тестов для Perl-модулей, чтобы их вывод был в формате, который Test::Harness ожидает увидеть.

РУКОВОДСТВО ПО БЫСТРОМУ НАЧАЛУ

Чтобы написать тест для вашего нового (и, вероятно, еще не законченного) модуля, создайте новый файл под названием t/test.t (в новом каталоге t). Если у вас есть несколько файлов тестов, чтобы протестировать наборы функций "foo", "bar" и "baz", то можете назвать свои файлы t/foo.t, t/bar.t и t/baz.t

Функции

Этот модуль определяет три публичные функции, plan(...), ok(...), и skip(...). По умолчанию все три экспортируются оператором use Test;.

plan(...)
BEGIN { plan %theplan; }

Это должно быть первое, что вы вызываете в своем скрипте теста. Оно объявляет ваш план тестирования, сколько будет тестов, если какие-либо из них должны быть разрешены к провалу, и так далее.

Типичное использование:

use Test;
BEGIN { plan tests => 23 }

Это то, что вы можете поместить в параметры plan:

tests => number

Количество тестов в вашем скрипте. Это означает все вызовы ok() и skip().

todo => [1,5,14]

Ссылка на список тестов, которые разрешено провалить. См. "TODO-ТЕСТЫ".

onfail => sub { ... }
onfail => \&some_sub

Ссылка на подпрограмму, которая будет запущена в конце скрипта теста, если какой-либо тест провалится. См. "ПРИ НЕУДАЧЕ".

Вы должны вызвать plan(...) один раз и только один раз. Вы должны вызвать его в BEGIN {...} блоке, как показано ниже:

BEGIN { plan tests => 23 }
ok(...)
ok(1 + 1 == 2);
ok($have, $expect);
ok($have, $expect, $diagnostics);

Эта функция — причина существования Test. Это основная функция, которая обрабатывает вывод "ok" или "not ok" вместе с текущим номером теста. (Это то, что Test::Harness хочет видеть.)

В самом простом использовании ok(...) принимает единственное скалярное выражение. Если его значение истинно, тест проходит; если ложно, тест проваливается. Примеры:

# Examples of ok(scalar)

ok( 1 + 1 == 2 );           # ok if 1 + 1 == 2
ok( $foo =~ /bar/ );        # ok if $foo contains 'bar'
ok( baz($x + $y) eq 'Armondo' );    # ok if baz($x + $y) returns
                                    # 'Armondo'
ok( @a == @b );             # ok if @a and @b are the same
                            # length

Выражение оценивается в скалярном контексте. Следующее будет работать:

ok( @stuff );                       # ok if @stuff has any
                                    # elements
ok( !grep !defined $_, @stuff );    # ok if everything in @stuff
                                    # is defined.

Особый случай — если выражение является ссылкой на подпрограмму (в синтаксисе sub {...} или \&foo). В этом случае она выполняется, и ее значение (истина или ложь) определяет, проходит тест или нет. Например,

ok( sub {   # See whether sleep works at least passably
  my $start_time = time;
  sleep 5;
  time() - $start_time  >= 4
});

В своей форме с двумя аргументами ok(arg1, arg2) сравнивает два скалярных значения, чтобы увидеть, совпадают ли они. Они совпадают, если оба неопределены, или если arg2 является регулярным выражением, которое соответствует arg1, или если они равны с помощью eq.

# Example of ok(scalar, scalar)

ok( "this", "that" );               # not ok, 'this' ne 'that'
ok( "", undef );                    # not ok, "" is defined

Второй аргумент считается регулярным выражением, если он является объектом регулярного выражения или строкой, которая выглядит как регулярное выражение. Объекты регулярных выражений создаются с помощью оператора qr// в последних версиях Perl. Строка считается похожей на регулярное выражение, если ее первый и последний символы — "/", или если первый символ — "m", а второй и последний символы — одинаковый неалфавитный, небуквенный символ. Эти регулярные выражения

Примеры регулярных выражений:

ok( 'JaffO', '/Jaff/' );    # ok, 'JaffO' =~ /Jaff/
ok( 'JaffO', 'm|Jaff|' );   # ok, 'JaffO' =~ m|Jaff|
ok( 'JaffO', qr/Jaff/ );    # ok, 'JaffO' =~ qr/Jaff/;
ok( 'JaffO', '/(?i)jaff/ ); # ok, 'JaffO' =~ /jaff/i;

Если любой (или оба!) являются ссылкой на подпрограмму, она выполняется, и ее возвращаемое значение используется в качестве реального значения этого параметра. Предположим, что $bytecount возвращает 4, ok заканчивает тестированием 4 eq 4. Поскольку это истинно, этот тест проходит.

Наконец, вы можете добавить необязательный третий аргумент в ok(arg1,arg2, note), где note — строковое значение, которое будет выведено, если тест провалится. Это должна быть полезная информация о тесте, касающаяся того, почему он провалился, и/или описание теста. Например:

ok( grep($_ eq 'something unique', @stuff), 1,
    "Something that should be unique isn't!\n".
    '@stuff = '.join ', ', @stuff
  );

К сожалению, примечание нельзя использовать со стилем одного аргумента в ok(). То есть, если вы попробуете ok(arg1, note), Test интерпретирует это как ok(arg1, arg2), и, вероятно, в итоге протестирует arg1 eq arg2 — а это не то, что вы хотите!

Все вышеперечисленные особые случаи могут иногда вызывать проблемы. См. "ОШИБКИ И ОСОБЕННОСТИ".

skip(skip_if_true, args...)

Используется для тестов, которые в некоторых условиях могут быть пропущены. Это по сути эквивалентно:

if( $skip_if_true ) {
  ok(1);
} else {
  ok( args... );
}

...кроме того, что ok(1) выводит не только "ok testnum", но фактически "ok testnum # skip_if_true_value".

Аргументы после skip_if_true — это то, что передается ok(...) , если этот тест не пропущен.

Пример использования:

my $if_MSWin =
  $^O =~ m/MSWin/ ? 'Skip if under MSWin' : '';

# A test to be skipped if under MSWin (i.e., run except under
# MSWin)
skip($if_MSWin, thing($foo), thing($bar) );

Или, наоборот:

my $unless_MSWin =
  $^O =~ m/MSWin/ ? '' : 'Skip unless under MSWin';

# A test to be skipped unless under MSWin (i.e., run only under
# MSWin)
skip($unless_MSWin, thing($foo), thing($bar) );

Важно помнить, что первый параметр истинно, если вы хотите пропустить тест, а не выполнить его; и он также выступает в качестве примечания о том, почему он пропускается. Таким образом, в первом блоке кода прочтите код как "пропустить, если MSWin — (иначе) проверить, является ли thing($foo) thing($bar)" или во втором случае "пропустить, если не MSWin...".

Кроме того, когда ваша строка skip_if_reason истинна, она действительно должна (для обратной совместимости с более старыми версиями Test.pm) начинаться со строки "Skip", как показано в вышеприведенных примерах.

Обратите внимание, что в вышеуказанных случаях thing($foo) и thing($bar) оцениваются — но до тех пор, пока skip_if_true истинно, мы skip(...) просто выбрасываем их значение (т.е. не беспокоясь об обработке их как значений для ok(...). Но если вам нужно не оценивать аргументы при пропуске теста, используйте этот формат:

skip( $unless_MSWin,
  sub {
    # This code returns true if the test passes.
    # (But it doesn't even get called if the test is skipped.)
    thing($foo) eq thing($bar)
  }
);

или даже этот, который по существу эквивалентен:

skip( $unless_MSWin,
  sub { thing($foo) }, sub { thing($bar) }
);

То есть, оба похожи на это:

if( $unless_MSWin ) {
  ok(1);  # but it actually appends "# $unless_MSWin"
          #  so that Test::Harness can tell it's a skip
} else {
  # Not skipping, so actually call and evaluate...
  ok( sub { thing($foo) }, sub { thing($bar) } );
}

ТИПЫ ТЕСТОВ

  • НОРМАЛЬНЫЕ ТЕСТЫ

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

  • ПРОПУЩЕННЫЕ ТЕСТЫ

    Функция skip(...) предназначена для тестов, которые могут или не могут быть запущены в зависимости от доступности платформозависимых функций. Первый аргумент должен оцениваться как истинный (думайте "да, пожалуйста, пропустите"), если необходимая функция не доступна. После первого аргумента skip(...) работает точно так же, как ok(...).

  • ТЕСТЫ TODO

    Тесты TODO предназначены для ведения исполняемого списка TODO. Эти тесты должны провалиться. Если тест TODO проходит успешно, то функция, о которой идет речь, больше не должна быть в списке TODO, не так ли?

    Пакеты не должны выпускаться с успешными тестами TODO. Как только тест TODO начинает работать, он должен быть переведен в нормальный тест, а новая работающая функция должна быть задокументирована в примечаниях к релизу или в журнале изменений.

ПРИ НЕУДАЧЕ

BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } }

Хотя провалы тестов должны быть достаточны, дополнительные диагностические данные могут быть вызваны в конце выполнения теста. onfail получает массив ссылок на хэши, описывающие каждый провал теста. Каждый хэш будет содержать по крайней мере следующие поля: package, repetition, и result. (Вы не должны полагаться на наличие других полей.) Если тест имел ожидаемое значение или диагностическую (или «примечание») строку, они также будут включены.

Необязаемый onfail хук может быть использован просто для вывода версии вашего пакета и/или как сообщать о проблемах. Он также может быть использован для создания чрезвычайно сложной диагностики для особо странного провала теста. Однако это не панацея. Ошибки с записью в дамп памяти или другие невосстановимые ошибки препятствуют запуску onfail хука. (Он запускается внутри END блока.) Кроме того, onfail — вероятно, избыточно в большинстве случаев. (Ваш код теста должен быть проще, чем код, который он тестирует, верно?)

ОШИБКИ И ОСОБЕННОСТИ

  • ok(...)'s special handling of strings which look like they might be regexes can also cause unexpected behavior. An innocent:

    ok( $fileglob, '/path/to/some/*stuff/' );

    will fail, since Test.pm considers the second argument to be a regex! The best bet is to use the one-argument form:

    ok( $fileglob eq '/path/to/some/*stuff/' );
  • ok(...)'s use of string eq can sometimes cause odd problems when comparing numbers, especially if you're casting a string to a number:

    $foo = "1.0";
    ok( $foo, 1 );      # not ok, "1.0" ne 1

    Your best bet is to use the single argument form:

    ok( $foo == 1 );    # ok "1.0" == 1
  • As you may have inferred from the above documentation and examples, ok's prototype is ($;$$) (and, incidentally, skip's is ($;$$$)). This means, for example, that you can do ok @foo, @bar to compare the size of the two arrays. But don't be fooled into thinking that ok @foo, @bar means a comparison of the contents of two arrays -- you're comparing just the number of elements of each. It's so easy to make that mistake in reading ok @foo, @bar that you might want to be very explicit about it, and instead write ok scalar(@foo), scalar(@bar).

  • This almost definitely doesn't do what you expect:

    ok $thingy->can('some_method');

    Why? Because can returns a coderef to mean "yes it can (and the method is this...)", and then ok sees a coderef and thinks you're passing a function that you want it to call and consider the truth of the result of! I.e., just like:

    ok $thingy->can('some_method')->();

    What you probably want instead is this:

    ok $thingy->can('some_method') && 1;

    If the can returns false, then that is passed to ok. If it returns true, then the larger expression $thingy->can('some_method') && 1 returns 1, which ok sees as a simple signal of success, as you would expect.

  • The syntax for skip is about the only way it can be, but it's still quite confusing. Just start with the above examples and you'll be okay.

    Moreover, users may expect this:

    skip $unless_mswin, foo($bar), baz($quux);

    to not evaluate foo($bar) and baz($quux) when the test is being skipped. But in reality, they are evaluated, but skip just won't bother comparing them if $unless_mswin is true.

    You could do this:

    skip $unless_mswin, sub{foo($bar)}, sub{baz($quux)};

    But that's not terribly pretty. You may find it simpler or clearer in the long run to just do things like this:

    if( $^O =~ m/MSWin/ ) {
      print "# Yay, we're under $^O\n";
      ok foo($bar), baz($quux);
      ok thing($whatever), baz($stuff);
      ok blorp($quux, $whatever);
      ok foo($barzbarz), thang($quux);
    } else {
      print "# Feh, we're under $^O.  Watch me skip some tests...\n";
      for(1 .. 4) { skip "Skip unless under MSWin" }
    }

    But be quite sure that ok is called exactly as many times in the first block as skip is called in the second block.

СРЕДА

If PERL_TEST_DIFF environment variable is set, it will be used as a command for comparing unexpected multiline results. If you have GNU diff installed, you might want to set PERL_TEST_DIFF to diff -u. If you don't have a suitable program, you might install the Text::Diff module and then set PERL_TEST_DIFF to be perl -MText::Diff -e 'print diff(@ARGV)'. If PERL_TEST_DIFF isn't set but the Algorithm::Diff module is available, then it will be used to show the differences in multiline results.

ПРИМЕЧАНИЕ

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

Обратите внимание, что главная ценность этого модуля — его простота. Обратите внимание, что уже существуют более амбициозные модули, такие как Test::More и Test::Unit.

В некоторых ранних версиях этого модуля в документации были некоторые путающие опечатки в описании skip(...).

СМОТРИТЕ ТАКЖЕ

Test::Harness

Test::Simple, Test::More, Devel::Cover

Test::Builder для создания собственной библиотеки тестирования.

Test::Unit — интересная библиотека тестирования в стиле XUnit.

Test::Inline позволяет встраивать тесты в код.

АВТОР

Copyright (c) 1998-2000 Joshua Nathaniel Pritikin.

Copyright (c) 2001-2002 Michael G. Schwern.

Copyright (c) 2002-2004 Sean M. Burke.

Текущий основной разработчик: Jesse Vincent. <jesse@bestpractical.com>

Этот пакет — свободное программное обеспечение и предоставляется «как есть» без явных или подразумеваемых гарантий. Он может использоваться, перераспределяться и/или модифицироваться на тех же условиях, что и сам Perl.

© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.34.0/Test

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API