Test::More - 撰寫測試腳本的另一套架構
use Test::More tests => 23;
# or
use Test::More skip_all => $reason;
# or
use Test::More; # see done_testing()
require_ok( 'Some::Module' );
# Various ways to say "ok"
ok($got eq $expected, $test_name);
is ($got, $expected, $test_name);
isnt($got, $expected, $test_name);
# Rather than print STDERR "# here's what went wrong\n"
diag("here's what went wrong");
like ($got, qr/expected/, $test_name);
unlike($got, qr/expected/, $test_name);
cmp_ok($got, '==', $expected, $test_name);
is_deeply($got_complex_structure, $expected_complex_structure, $test_name);
SKIP: {
skip $why, $how_many unless $have_some_feature;
ok( foo(), $test_name );
is( foo(42), 23, $test_name );
};
TODO: {
local $TODO = $why;
ok( foo(), $test_name );
is( foo(42), 23, $test_name );
};
can_ok($module, @methods);
isa_ok($object, $class);
pass($test_name);
fail($test_name);
BAIL_OUT($why);
# UNIMPLEMENTED!!!
my @status = Test::More::status;
停止!如果您才剛開始撰寫測試,請先參考 Test2::Suite。
這是 Test::Simple 的替代方案,一旦您掌握基本測試後,就可以切換到此替代方案。
此模組的目的是提供廣泛的測試工具。各種方法來說「ok」並提供更好的診斷,跳過測試、測試未來功能以及比較複雜資料結構的工具。雖然您幾乎可以使用簡單的 ok()
函式來執行任何操作,但它無法提供良好的診斷輸出。
在進行其他任何事之前,你需要一個測試計畫。這基本上宣告你的指令碼將執行多少測試以防止過早失敗。
執行此操作的首選方式是在使用 Test::More
時宣告一個計畫。
use Test::More tests => 23;
有些情況下,你事先不會知道你的指令碼將執行多少測試。在這種情況下,你可以在結尾宣告你的測試。
use Test::More;
... run your tests ...
done_testing( $number_of_tests_run );
注意 done_testing()
不應在 END { ... }
區塊中呼叫。
有時你真的不知道執行了多少測試,或者計算起來太困難。在這種情況下,你可以省略 $number_of_tests_run。
在某些情況下,你會想要完全略過整個測試指令碼。
use Test::More skip_all => $skip_reason;
你的指令碼將宣告略過的原因,並立即以零(成功)退出。請參閱 Test::Harness 以取得詳細資訊。
如果你想要控制 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()
相同,這是你預計執行的測試數量。你可以省略這個,這樣一來,你執行的測試數量並不重要,重要的是你的測試執行到結論。
這比「no_plan」計畫更安全,並取代了它。
注意:你絕不能將 done_testing()
放在 END { ... }
區塊中。計畫的存在是為了確保你的測試在測試完成之前不會退出。如果你使用 END 區塊,你將完全繞過此保護措施。
根據慣例,每個測試按順序分配一個數字。這在很大程度上會自動為你完成。但是,通常將名稱分配給每個測試非常有用。你寧願看到
ok 4
not ok 5
ok 6
或
ok 4 - basic multi-variable
not ok 5 - simple exponential
ok 6 - force == mass * acceleration
後者讓你對失敗的原因有一些了解。它還讓你更容易在指令碼中找到測試,只需搜尋「簡單指數」即可。
所有測試函式都採用名稱引數。它是可選的,但強烈建議你使用它。
此模組的基本目的是列印「ok #」或「not ok #」,視特定測試是否成功或失敗而定。其他一切都只是附帶的。
以下所有內容會列印「ok」或「not ok」,視測試是否成功或失敗而定。它們也都會分別傳回 true 或 false。
ok($got eq $expected, $test_name);
這只會評估任何表達式($got eq $expected
只是個簡單的範例),並使用它來判斷測試是否成功或失敗。真的表達式會通過,假的表達式會失敗。非常簡單。
例如
ok( $exp{9} == 81, 'simple exponential' );
ok( Film->can('db_Main'), 'set_db()' );
ok( $p->tests == 4, 'saw tests' );
ok( !grep(!defined $_, @items), 'all items defined' );
(助記符:「這沒問題。」)
$test_name 是測試的非常簡短說明,會列印出來。當測試失敗時,它可以非常容易地在您的腳本中找到測試,並讓其他人了解您的意圖。$test_name 是選用的,但我們非常強烈建議使用它。
如果 ok()
失敗,它會產生一些診斷
not ok 18 - sufficient mucus
# Failed test 'sufficient mucus'
# in foo.t at line 42.
這與 Test::Simple 的 ok()
常式相同。
is ( $got, $expected, $test_name );
isnt( $got, $expected, $test_name );
類似於 ok()
,is()
和 isnt()
分別使用 eq
和 ne
比較它們的兩個引數,並使用結果來判斷測試是否成功或失敗。因此這些
# Is the ultimate answer 42?
is( ultimate_answer(), 42, "Meaning of Life" );
# $foo isn't empty
isnt( $foo, '', "Got some foo" );
類似於這些
ok( ultimate_answer() eq 42, "Meaning of Life" );
ok( $foo ne '', "Got some foo" );
undef
只會與 undef
相符。因此您可以像這樣測試值是否為 undef
is($not_defined, undef, "undefined as expected");
(助記符:「這是那個。」「這不是那個。」)
那麼為什麼要使用這些?它們在失敗時會產生更好的診斷。ok()
無法知道您要測試什麼(除了名稱之外),但 is()
和 isnt()
知道測試是什麼以及為什麼失敗。例如這個測試
my $foo = 'waffle'; my $bar = 'yarblokos';
is( $foo, $bar, 'Is foo the same as bar?' );
會產生類似這樣的內容
not ok 17 - Is foo the same as bar?
# Failed test 'Is foo the same as bar?'
# in foo.t at line 139.
# got: 'waffle'
# expected: 'yarblokos'
因此,您可以在不重新執行測試的情況下找出問題所在。
我們建議您盡可能使用 is()
和 isnt()
取代 ok()
,但不要想用它們來找出某件事是否為真或假!
# XXX BAD!
is( exists $brooklyn{tree}, 1, 'A tree grows in Brooklyn' );
這不會檢查 exists $brooklyn{tree}
是否為真,它會檢查它是否傳回 1。非常不同。對於 false 和 0 也有類似的警告。在這些情況下,請使用 ok()
。
ok( exists $brooklyn{tree}, 'A tree grows in Brooklyn' );
對 isnt()
的簡單呼叫通常不會提供強大的測試,但有些情況下,你無法對一個值說出比它與其他值不同更多的話
new_ok $obj, "Foo";
my $clone = $obj->clone;
isa_ok $obj, "Foo", "Foo->clone";
isnt $obj, $clone, "clone() produces a different object";
過去我們支援 isn't()
函數作為 isnt()
的別名,但在 Perl 5.37.9 中,使用撇號作為套件分隔符號的支援已不建議使用,且在 Perl 5.42.0 中將會完全移除。因此,使用 isn't()
也已不建議使用,且在使用時會產生警告,除非在使用的範圍中特別停用「已不建議使用」的警告。強烈建議你改用 isnt()
。
like( $got, qr/expected/, $test_name );
與 ok()
類似,like()
會將 $got 與正規表示式 qr/expected/
相符。
所以這
like($got, qr/expected/, 'this is like that');
與這類似
ok( $got =~ m/expected/, 'this is like that');
(助記符號「This is like that」)。
第二個引數是正規表示式。它可以作為正規表示式參考(即 qr//
)提供,或(為了與較舊的 perl 更好地相容)作為看起來像正規表示式的字串提供(目前不支援替代分隔符號)
like( $got, '/expected/', 'this is like that' );
正規表示式選項可以放在結尾('/expected/i'
)。
它相較於 ok()
的優點與 is()
和 isnt()
類似。在失敗時提供更好的診斷。
unlike( $got, qr/expected/, $test_name );
與 like()
完全相同,只不過它檢查 $got 不符合給定的模式。
cmp_ok( $got, $op, $expected, $test_name );
ok()
和 is()
之間的折衷是 cmp_ok()
。這允許你使用任何二元 perl 算子來比較兩個引數。如果比較為真,則測試通過,否則失敗。
# ok( $got eq $expected );
cmp_ok( $got, 'eq', $expected, 'this eq that' );
# ok( $got == $expected );
cmp_ok( $got, '==', $expected, 'this == that' );
# ok( $got && $expected );
cmp_ok( $got, '&&', $expected, 'this && that' );
...etc...
它相較於 ok()
的優點是,當測試失敗時,你會知道 $got 和 $expected 是什麼
not ok 1
# Failed test in foo.t at line 12.
# '23'
# &&
# undef
在比較數字且 is()
使用 eq
會造成干擾的情況下,它也很有用
cmp_ok( $big_hairy_number, '==', $another_big_hairy_number );
在比較值之間的大小關係時,它特別有用
cmp_ok( $some_value, '<=', $upper_limit );
can_ok($module, @methods);
can_ok($object, @methods);
檢查以確保 $module 或 $object 可以執行這些 @methods(也適用於函數)。
can_ok('Foo', qw(this that whatever));
幾乎完全等於說
ok( Foo->can('this') &&
Foo->can('that') &&
Foo->can('whatever')
);
只不過不用輸入所有內容且有更好的介面。方便快速測試介面。
無論你檢查多少個 @methods,單一的 can_ok()
呼叫都算作一個測試。如果你希望有其他結果,請使用
foreach my $meth (@methods) {
can_ok('Foo', $meth);
}
isa_ok($object, $class, $object_name);
isa_ok($subclass, $class, $object_name);
isa_ok($ref, $type, $ref_name);
檢查以查看給定的 $object->isa($class)
。還會檢查以確保物件一開始就有定義。方便用於這類事情
my $obj = Some::Module->new;
isa_ok( $obj, 'Some::Module' );
否則你必須寫
my $obj = Some::Module->new;
ok( defined $obj && $obj->isa('Some::Module') );
以防範測試指令碼爆炸。
您也可以測試類別,以確保它有正確的祖先
isa_ok( 'Vole', 'Rodent' );
它也適用於參照
isa_ok( $array_ref, 'ARRAY' );
此測試的診斷通常只參照「物件」。如果您希望它們更具體,您可以提供 $object_name(例如「測試客戶」)。
my $obj = new_ok( $class );
my $obj = new_ok( $class => \@args );
my $obj = new_ok( $class => \@args, $object_name );
一種便利函數,結合建立物件和對該物件呼叫 isa_ok()
。
它基本上等於
my $obj = $class->new(@args);
isa_ok $obj, $class, $object_name;
如果未提供 @args,將使用空清單。
此函數僅適用於 new()
,並且假設 new()
只會傳回單一 isa $class
的物件。
subtest $name => \&code, @args;
subtest()
將 &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");
這將產生。
1..3
ok 1 - First test
# Subtest: An example subtest
1..2
ok 1 - This is a subtest
ok 2 - So is this
ok 2 - An example subtest
ok 3 - Third test
子測試可以呼叫 skip_all
。不會執行任何測試,但子測試會被視為跳過。
subtest 'skippy' => sub {
plan skip_all => 'cuz I said so';
pass('this test will never be run');
};
如果子測試通過,則傳回 true,否則傳回 false。
由於子測試的工作方式,如果您願意,可以省略計畫。這會在子測試的結尾新增一個隱含的 done_testing()
。以下兩個子測試是等效的
subtest 'subtest with implicit done_testing()', sub {
ok 1, 'subtests with an implicit done testing should work';
ok 1, '... and support more than one test';
ok 1, '... no matter how many tests are run';
};
subtest 'subtest with explicit done_testing()', sub {
ok 1, 'subtests with an explicit done testing should work';
ok 1, '... and support more than one test';
ok 1, '... no matter how many tests are run';
done_testing();
};
傳遞給 subtest
的額外引數會傳遞給回呼。例如
sub my_subtest {
my $range = shift;
...
}
for my $range (1, 10, 100, 1000) {
subtest "testing range $range", \&my_subtest, $range;
}
pass($test_name);
fail($test_name);
有時您只想表示測試已通過。通常情況是您有一些複雜的條件,難以塞進 ok()
中。在這種情況下,您可以簡單地使用 pass()
(宣告測試正常)或 fail(不正常)。它們是 ok(1)
和 ok(0)
的同義詞。
非常、非常、非常謹慎地使用這些。
有時您想測試模組或模組清單是否可以成功載入。例如,您通常會想要一個第一個測試,只載入發行版中的所有模組,以確保它們在進行更複雜的測試之前能正常工作。
對於這樣的目的,我們有 use_ok
和 require_ok
。
require_ok($module);
require_ok($file);
嘗試require
給定的 $module 或 $file。如果載入成功,測試將會通過。否則,測試將會失敗並顯示載入錯誤。
require_ok
會猜測輸入是模組名稱或檔案名稱。
如果載入失敗,不會擲出例外。
# require Some::Module
require_ok "Some::Module";
# require "Some/File.pl";
require_ok "Some/File.pl";
# stop testing if any of your modules will not load
for my $module (@module) {
require_ok $module or BAIL_OUT "Can't load $module";
}
BEGIN { use_ok($module); }
BEGIN { use_ok($module, @imports); }
如同require_ok
,但它會use
有問題的 $module,而且只載入模組,不載入檔案。
如果你只想測試模組是否可以載入,請使用require_ok
。
如果你只想在測試中載入模組,我們建議直接使用use
。這會導致測試停止。
建議你在 BEGIN 區塊內執行use_ok()
,如此一來,其函式會在編譯時匯出,而且會正確地遵循原型。
如果給予 @imports,它們會傳遞到 use。因此,這
BEGIN { use_ok('Some::Module', qw(foo bar)) }
就像執行這段程式碼
use Some::Module qw(foo bar);
版本號碼可以這樣檢查
# Just like "use Some::Module 1.02"
BEGIN { use_ok('Some::Module', 1.02) }
不要嘗試執行這段程式碼
BEGIN {
use_ok('Some::Module');
...some code that depends on the use...
...happening at compile time...
}
因為「編譯時」的概念是相對的。相反地,你想要
BEGIN { use_ok('Some::Module') }
BEGIN { ...some code that depends on the use... }
如果你想要等同於use Foo ()
的程式碼,請使用模組但不要匯入任何東西,請使用require_ok
。
BEGIN { require_ok "Foo" }
並非所有東西都是簡單的 eq 檢查或正規表示式。有時你需要判斷兩個資料結構是否相等。對於這些情況,Test::More 提供了一些有用的函式。
注意我不太確定檔案句柄會發生什麼事。
is_deeply( $got, $expected, $test_name );
類似於is()
,但如果 $got 和 $expected 是參考,它會執行深度比較,遍歷每個資料結構以判斷它們是否相等。如果兩個結構不同,它會顯示它們開始不同的位置。
is_deeply()
會比較取消參考的參考值,參考本身(其類型除外)會被忽略。這表示祝福和連結等面向不會被視為「不同」。
is_deeply()
目前對於函式參考和 glob 的處理非常有限。它僅檢查它們是否具有相同的參照。這可能會在未來得到改善。
Test::Differences 和 Test::Deep 提供了更深入的這方面的功能。
注意 is_deeply() 在比較字串和參照時有其限制
my $path = path('.');
my $hash = {};
is_deeply( $path, "$path" ); # ok
is_deeply( $hash, "$hash" ); # fail
這是因為 is_deeply 會無條件地解除所有參數的重載。最好不要將 is_deeply 與重載一起使用。由於歷史原因,這不太可能被修復。如果您想要一個更好的工具,您應該看看 Test2::Suite 特別是 Test2::Tools::Compare 有個 is()
函式,其運作方式類似於 is_deeply
,但有許多改進。
如果您選擇正確的測試函式,通常可以在測試失敗時清楚了解問題出在哪裡。但有時並非如此。因此,我們提供了讓您撰寫自己的診斷訊息的方法,這些方法比僅使用 print STDERR
更安全。
diag(@diagnostic_message);
印出診斷訊息,保證不會干擾測試輸出。如同 print
,@diagnostic_message 僅僅會串接在一起。
傳回 false,以保留失敗。
對於這類事情非常方便
ok( grep(/foo/, @users), "There's a foo user" ) or
diag("Since there's no foo, check that /etc/bar is set up right");
將會產生
not ok 42 - There's a foo user
# Failed test 'There's a foo user'
# in foo.t at line 52.
# Since there's no foo, check that /etc/bar is set up right.
您可能會將 ok() or diag()
記成助記符號 open() or die()
。
注意 診斷輸出的確切格式仍在變更中,但保證您傳入的任何內容都不會干擾測試。
note(@diagnostic_message);
如同 diag()
,但當測試在測試架構中執行時,訊息將不會顯示。它只會在詳細 TAP 串流中可見。
對於放置在註解中、可能有助於除錯但不會指出問題的訊息非常方便。
note("Tempfile is $tempfile");
my @dump = explain @diagnostic_message;
會以人類可讀的格式傾印任何參照的內容。通常您會想要將此傳入 note
或 diag
。
對於類似以下事項非常方便...
is_deeply($have, $want) || diag explain $have;
或
note explain \%args;
Some::Class->method(%args);
有時在特定條件下執行測試會導致測試腳本中斷。某些函式或方法未實作(例如 MacOS 上的 fork()
)、某些資源不可用(例如網路連線)或某些模組不可用。在這些情況下,有必要略過測試,或宣告它們應該失敗,但未來會運作(待辦事項測試)。
有關跳過和待辦測試的機制之詳細資訊,請參閱 Test::Harness。
Test::More 處理此問題的方式是使用命名區塊。基本上,區塊中的測試可以跳過或設為待辦。以下是我展示給您的最佳方式...
SKIP: {
skip $why, $how_many if $condition;
...normal testing code goes here...
}
這宣告一個可能會跳過的測試區塊,$how_many 測試、$why 以及在什麼 $condition 下跳過它們。舉例說明是最簡單的方法
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" );
}
如果使用者未安裝 HTML::Lint,整個程式碼區塊根本不會執行。Test::More 會輸出 Test::Harness 視為跳過但通過的特殊 ok。
$how_many 精確反映 SKIP 區塊中的測試數目非常重要,因此執行測試的數量會與您的計畫相符。如果您的計畫是 no_plan
,則 $how_many 是選用的,且預設為 1。
嵌套 SKIP 區塊完全安全。每個 SKIP 區塊都必須有標籤 SKIP
,否則 Test::More 無法發揮其神奇作用。
您不會跳過因程式中有錯誤或尚未撰寫程式碼而失敗的測試。您會使用 TODO。請繼續閱讀。
TODO: {
local $TODO = $why if $condition;
...normal testing code goes here...
}
宣告一個您預期會失敗的測試區塊和 $why。可能是因為您尚未修復錯誤或尚未完成新功能
TODO: {
local $TODO = "URI::Geller not finished";
my $card = "Eight of clubs";
is( URI::Geller->your_card, $card, 'Is THIS your card?' );
my $spoon;
URI::Geller->bend_spoon;
is( $spoon, 'bent', "Spoon bending, that's original" );
}
對於待辦區塊,預期裡面的測試會失敗。Test::More 會正常執行測試,但會列印出特殊標記,表示它們是「待辦」。Test::Harness 會將失敗解釋為正常。如果任何事情成功,它會將其報告為意外的成功。然後您會知道您待辦的事項已完成,並可以移除 TODO 標記。
與僅註解掉一個測試區塊相比,待辦測試的優點在於它就像有一個程式化的待辦清單。您知道還有多少工作要做,您知道有哪些錯誤,而且您會在它們修復時立即知道。
一旦待辦測試開始成功,只需將其移到區塊外即可。當區塊為空時,請將其刪除。
請注意,如果您讓 $TODO 未設定或未定義,Test::More 會像平常一樣報告失敗。這對於將測試標記為僅在特定條件下預期失敗很有用,例如
TODO: {
local $TODO = "$^O doesn't work yet. :(" if !_os_is_supported($^O);
...
}
TODO: {
todo_skip $why, $how_many if $condition;
...normal testing code...
}
對於待辦測試,最好實際執行測試。這樣您就會知道它們何時開始通過。有時這是不可行的。通常,失敗的測試會導致整個程式死掉或當機,即使在使用 alarm
的 eval BLOCK
內部也是如此。在這些極端情況下,您別無選擇,只能完全跳過損壞的測試。
語法和行為類似於 SKIP: BLOCK
,但測試會標示為失敗但待辦。 Test::Harness 會將它們解釋為通過。
如果使用者可能無法執行某些操作,請使用 SKIP。這包括未安裝的選用模組、在沒有某些功能(例如 fork()
或符號連結)的作業系統下執行,或者可能需要網路連線但無法使用。
如果程式設計師尚未執行某些操作,請使用 TODO。這是針對尚未撰寫的任何程式碼,或尚未修正的錯誤,但希望將測試放入測試指令碼(這始終是個好主意)。
BAIL_OUT($reason);
指示測試架構所有測試都應該終止,因為情況非常糟糕。這包括執行任何其他測試指令碼。
這通常用於測試無法繼續進行的情況,例如關鍵模組無法編譯或必要的外部公用程式無法使用,例如資料庫連線失敗。
測試將以 255 退出。
若要獲得更好的控制,請查看 Test::Most。
不建議使用下列函式,因為它們實際上不是測試函式,而且不會產生任何診斷訊息來協助找出問題所在。它們是在 is_deeply()
存在之前編寫的,因為我無法找出如何顯示兩個任意資料結構的實用差異。
這些函式通常用於 ok()
內部。
ok( eq_array(\@got, \@expected) );
is_deeply()
可以做得更好,而且有診斷訊息。
is_deeply( \@got, \@expected );
它們可能會在未來版本中被棄用。
my $is_eq = eq_array(\@got, \@expected);
檢查兩個陣列是否相等。這是一個深度檢查,因此可以正確處理多層級結構。
my $is_eq = eq_hash(\%got, \%expected);
判斷兩個雜湊是否包含相同的鍵和值。這是一個深度檢查。
my $is_eq = eq_set(\@got, \@expected);
類似於 eq_array()
,但元素順序不重要。這是一個深度檢查,但順序無關僅適用於頂層。
ok( eq_set(\@got, \@expected) );
寫得更好
is_deeply( [sort @got], [sort @expected] );
注意 歷史上意外地,這不是真正的集合比較。雖然元素順序不重要,但重複元素很重要。
注意 eq_set()
不知道如何處理頂層的參考。以下是一個可能無法運作的比較範例
eq_set([\1, \2], [\2, \1]);
Test::Deep 包含更好的集合比較函式。
有時 Test::More 介面不夠用。幸運的是,Test::More 建構在 Test::Builder 之上,它提供單一統一的後端供任何測試函式庫使用。這表示兩個都使用 Test::Builder 的測試函式庫可以在同一個程式中一起使用。
如果你只是想稍微調整測試行為,你可以存取底層的 Test::Builder 物件,如下所示
my $test_builder = Test::More->builder;
傳回 Test::More 底層的 Test::Builder 物件,供你使用。
如果你的所有測試都通過,Test::Builder 會以零退出(這是正常的)。如果任何測試失敗,它會以失敗的數量退出。如果你執行的測試少於(或多於)你計畫的,遺失的(或額外的)測試會被視為失敗。如果從未執行任何測試,Test::Builder 會擲回警告並以 255 退出。如果測試中斷,即使在成功完成所有測試後,它仍會被視為失敗,並會以 255 退出。
因此,退出代碼是...
0 all tests successful
255 test died or all passed but wrong # of tests run
any other number how many failed (including missing or extras)
如果你失敗超過 254 個測試,它會回報為 254。
注意 此行為可能會在未來的版本中消失。
Test::More 可與 5.8.1 等舊版的 Perl 搭配使用。
在 5.10.1 之前,執行緒支援不是很可靠,但那是因為在 5.10.1 之前執行緒不是很可靠。
儘管 Test::More 自 Perl 5.6.2 以來的版本中一直是核心模組,但 Test::More 自此之後已演進,你習慣的所有功能並不會出現在 Test::More 的出貨版本中。如果你正在撰寫模組,請記得在你的套件中繼資料中指出你需要的 Test::More 最低版本。例如,如果你想使用 done_testing()
但希望你的測試腳本在 Perl 5.10.0 上執行,你需要明確要求 Test::More > 0.88。
主要功能里程碑包括
子測試在 Test::More 0.94 中釋出,隨 Perl 5.12.0 附帶。子測試在 0.96 之前不會隱式呼叫 done_testing()
;第一個有此修正的 Perl 是搭配 0.98 的 Perl 5.14.0。
done_testing()
這在 Test::More 0.88 中釋出,並在 Perl 5.10.1 中作為 Test::More 0.92 的一部分首次附帶發布。
cmp_ok()
儘管 cmp_ok()
在 0.40 中引入,但 0.86 修復了一個重要的錯誤,使其對超載物件安全;此修復在 Perl 5.10.1 中作為 Test::More 0.92 的一部分首次附帶發布。
new_ok()
note()
和 explain()
這些在 Test::More 0.82 中釋出,並在 Perl 5.10.1 中作為 Test::More 0.92 的一部分首次附帶發布。
在 Changes 檔案中有完整的版本記錄,而包含在核心中的 Test::More 版本可以使用 Module::CoreList 找到。
$ corelist -a Test::More
如果您在 Test::More 中使用 utf8 或其他非 ASCII 字元,您可能會收到「列印中的寬字元」警告。使用 binmode STDOUT, ":utf8"
無法修復此問題。 Test::Builder(為 Test::More 提供支援)複製 STDOUT 和 STDERR。因此,對它們的任何變更,包括變更其輸出規則,Test::More 都看不到。
一種解決方法是在 Test::More(或任何其他 Test 模組)載入之前,盡早將編碼套用到 STDOUT 和 STDERR。
use open ':std', ':encoding(utf8)';
use Test::More;
更直接的解決方法是變更 Test::Builder 使用的文件處理常式。
my $builder = Test::More->builder;
binmode $builder->output, ":encoding(utf8)";
binmode $builder->failure_output, ":encoding(utf8)";
binmode $builder->todo_output, ":encoding(utf8)";
字串超載物件會以字串形式進行比較(或在 cmp_ok()
的情況下,以適於比較運算式的字串或數字形式進行比較)。這可防止 Test::More 穿透物件介面,從而允許更好的黑盒測試。因此,如果函式開始傳回超載物件而非純粹的字串,您的測試不會注意到差異。這是好的。
然而,這確實表示無法使用像 is_deeply()
之類的函式來測試字串超載物件的內部。在這種情況下,我建議使用 Test::Deep,其中包含更多用於複雜資料結構的彈性測試函式。
只有在載入 Test::More 之前執行 use threads
,Test::More 才會知道執行緒。這沒問題
use threads;
use Test::More;
這可能會造成問題
use Test::More
use threads;
支援 5.8.1 以上版本。低於此版本有太多錯誤。
這是與 Joshua Pritikin 的 Test 模組會聚演化的案例。在我第一次撰寫自己的 ok()
常式時,我幾乎不知道它的存在。這個模組存在是因為我不知道如何輕鬆地將測試名稱塞進 Test 的介面(以及其他一些問題)。
此處的目標是要有一個測試工具程式,它易於學習、快速使用且不容易出錯,同時提供比現有的 Test.pm 更多的彈性。因此,最常見常式的名稱保持簡短,特殊情況和神奇的副作用保持在最低限度。所見即所得。
Test2::Suite 是最新、最現代的測試工具組。
Test::Simple 如果所有這些讓你感到困惑,而你只想撰寫一些測試。你可以稍後升級到 Test::More(它向前相容)。
Test::Legacy 使用 Test.pm(原始測試模組)撰寫的測試與其他測試函式庫不搭配。Test::Legacy 模擬 Test.pm 介面,並與其他介面搭配良好。
Test::Differences 提供更多測試複雜資料結構的方法。而且它與 Test::More 搭配良好。
Test::Class 類似於 xUnit,但更 Perl 風格。
Test::Deep 提供更強大的複雜資料結構測試。
Test::Inline 顯示嵌入式測試的概念。
Mock::Quick 終極模擬函式庫。輕鬆產生動態定義的物件。也可以根據需要覆寫、封鎖或重新實作套件。
Test::FixtureBuilder 快速定義單元測試的固定資料。
Test::Harness 是 Perl 的測試執行器和輸出詮釋器。它是推動 make test
的工具,也是 prove
工具程式來源。
Test::Most 最常需要的測試函式和功能。
Michael G Schwern <schwern@pobox.com> 受到 Joshua Pritikin 的 Test 模組的許多啟發,以及 Barrie Slaymaker、Tony Bowden、blackstar.co.uk、chromatic、Fergal Daly 和 perl-qa 團隊的許多幫助。
請參閱 https://github.com/Test-More/test-more/issues 以報告和檢視錯誤。
Test::More 的原始碼存放庫位於 http://github.com/Test-More/test-more/。
版權所有 2001-2008 Michael G Schwern <schwern@pobox.com>。
此程式為免費軟體;您可以在與 Perl 相同的條款下重新散布或修改它。
請參閱 http://www.perl.com/perl/misc/Artistic.html