2010-05-20 22 views
28

Tôi sắp xếp mới cho Perl và tôi tự hỏi liệu có một khung kiểm thử đơn vị được ưa thích không?Khung kiểm tra đơn vị ưu tiên cho Perl là gì?

Google đang hiển thị cho tôi một số kết quả tốt đẹp, nhưng vì tôi mới làm quen với điều này, tôi không biết liệu có sở thích rõ ràng trong cộng đồng hay không.

Trả lời

35

Perl có bộ công cụ kiểm tra tuyệt vời đi kèm với nó! Lõi Perl có hàng chục nghìn kiểm tra tự động cho nó, và phần lớn tất cả chúng đều sử dụng các khung công tác Perl tiêu chuẩn này. Chúng được gắn kết với nhau bằng TAP - Test Anything Protocol.

Cách chuẩn để tạo thử nghiệm TAP trong Perl là sử dụng gói gia đình Test::More, bao gồm để bắt đầu. Dưới đây là một ví dụ nhanh:

use 5.012; 
use warnings; 

use Test::More tests => 3; 

my $foo = 5; 
my $bar = 6; 

ok $foo == 5, 'Foo was assigned 5.'; 
ok $bar == 6, 'Bar was assigned 6.'; 
ok $foo + $bar == 11, 'Addition works correctly.'; 

Và kết quả sẽ là:

ok 1 - Foo was assigned 5. 
ok 2 - Bar was assigned 6. 
ok 3 - Addition works correctly. 

Về cơ bản, để bắt đầu, tất cả các bạn cần phải làm là đặt thông qua một giá trị boolean và một chuỗi giải thích những gì sẽ xảy ra!

Khi bạn vượt qua bước đó, Kiểm tra :: Thêm một số lượng lớn các chức năng khác để kiểm tra những thứ khác dễ dàng hơn (chuỗi, so sánh regex, cấu trúc sâu so sánh) và có kết thúc sau Test::Harness cho phép bạn kiểm tra lớn nhóm các kịch bản thử nghiệm riêng lẻ với nhau.

Ngày đầu đó, như Schwern chỉ ra, hầu như tất cả các mô-đun hiện đại Test:: hoạt động cùng nhau. Điều đó có nghĩa là bạn có thể sử dụng Test::Class (như được chỉ ra bởi Markus) với tất cả các mô-đun tuyệt vời được liệt kê trong answer của rjh. Trên thực tế, vì Test::Builder - công cụ Test::More và các công cụ khác được xây dựng trên (và hiện được Schwern duy trì ... nhờ Schwern!) - nếu cần, bạn có thể xây dựng các chương trình con thử nghiệm OWN của bạn từ đầu mà sẽ làm việc với tất cả các khuôn khổ thử nghiệm khác. Điều đó làm cho hệ thống TAP của Perl trở thành một trong những điều tuyệt vời nhất trong quan điểm của tôi: mọi thứ hoạt động cùng nhau, mọi người đều sử dụng cùng một công cụ và bạn có thể thêm vào khung công tác cho phù hợp với nhu cầu của bạn.

+0

chỉ cần tự hỏi, 'tests => 3' là gì. tôi có cần phải mã hóa số lượng các trường hợp không? – Mike

+6

Bạn không cần phải làm như vậy. Nhưng nếu kịch bản thử nghiệm của bạn chết sau khi xuất kết quả cho chỉ 1 hoặc 2 thử nghiệm, Kiểm tra :: Biết thêm rằng thử nghiệm của bạn đã thất bại (ngay cả khi nó thoát với một mã lỗi của số không). Bạn cũng có thể thực hiện 'use Test :: More 'no_plan'' hoặc gọi' done_testing() 'ở cuối script. – rjh

+0

Tôi không thể tìm được cách thích hợp để sử dụng không có kế hoạch. Nếu tôi không chỉ định một đối số số cho 'done_testing', tôi nhận được' Bạn đã cố chạy thử nghiệm mà không có kế hoạch! Phải có một kế hoạch ' – Mike

13

thử nghiệm phổ biến nhất Perl của 'khuôn khổ' là một định dạng kết quả xét nghiệm được gọi là TAP (Test Bất cứ điều gì Protocol) mà là một tập hợp các chuỗi mà hình như:

ok 1 - Imported correctly 
ok 2 - foo() takes two arguments 
not ok 3 - foo() throws an error if passed no arguments 

Bất kỳ kịch bản mà có thể tạo ra những chuỗi đếm như một bài kiểm tra Perl. Bạn có thể sử dụng Test::More để tạo TAP cho các điều kiện khác nhau - kiểm tra xem một biến có bằng một giá trị hay không, kiểm tra xem một mô-đun đã được nhập chính xác hay hai cấu trúc (mảng/băm) giống nhau. Nhưng trong tinh thần Perl thực sự, có nhiều cách để làm điều đó, và có những cách tiếp cận khác (ví dụ: Test::Class, trông giống như JUnit!)

Ví dụ đơn giản của một kịch bản thử nghiệm (thường kết thúc bằng .t, ví dụ foo.t)

use strict; 
use warnings; 
use Test::More tests => 3; # Tell Test::More you intend to do 3 tests 

my $foo = 3; 
ok(defined $foo, 'foo is defined'); 
is($foo, 3, 'foo is 3'); 
$foo++; 
is($foo, 4, 'incremented foo'); 

Bạn có thể sử dụng Test::Harness (thường được gọi là prove từ vỏ) để chạy một loạt các bài kiểm tra theo thứ tự, và nhận được một bản tóm tắt của những người thân mà đạt hoặc không đạt.

Kiểm tra :: Thêm cũng có thể thực hiện một số nội dung phức tạp hơn, như kiểm tra đánh dấu là TODO (không mong đợi họ vượt qua, nhưng chạy chúng chỉ trong trường hợp) hoặc SKIP (các thử nghiệm này bị hỏng/tùy chọn, không chạy chúng). Bạn có thể khai báo số lượng các bài kiểm tra mà bạn mong đợi để chạy, vì vậy nếu kịch bản thử nghiệm của bạn chết một nửa chiều, điều này có thể được phát hiện.

Một khi bạn bắt đầu làm thử nghiệm phức tạp hơn, bạn có thể tìm thấy một số module CPAN hữu ích khác - đây là một vài ecamples, nhưng có rất nhiều (nhiều) hơn:

Test::Exception - kiểm tra rằng mã của bạn ném lỗi/không ném bất kỳ lỗi nào
Test::Warn - kiểm tra xem mã của bạn có tạo/không tạo cảnh báo
Test::Deep - so sánh sâu đối tượng. Chúng không nhất thiết phải giống nhau - bạn có thể bỏ qua thứ tự mảng, sử dụng regexes, bỏ qua các lớp đối tượng, v.v.
Test::Pod - đảm bảo tập lệnh của bạn có POD (tài liệu) và có giá trị
Test::Pod::Coverage - đảm bảo rằng văn bản POD của bạn tất cả các phương pháp/chức năng trong module của bạn
Test::DBUnit - tương tác cơ sở dữ liệu thử nghiệm
Test::MockObject - làm cho đối tượng giả vờ để kiểm soát môi trường của các bài kiểm tra của bạn

5

Nếu bạn thực hành TDD, bạn sẽ nhận thấy rằng thiết lập của bạn kiểm tra đơn vị đang thay đổi rất nhiều. Test::Class theo mẫu xUnit (http://en.wikipedia.org/wiki/XUnit).

Đối với tôi, lợi ích chính với xUnit là đóng gói của từng thử nghiệm trong phương pháp. Khung công tác đặt tên cho mỗi xác nhận bằng tên của phương pháp thử nghiệm và thêm khả năng chạy các phương thức thiết lập và rách trước và sau mỗi lần thử nghiệm.

Tôi đã thử cách "perl-ish" để kiểm tra đơn vị cũng (chỉ sử dụng Test :: More), nhưng tôi thấy nó kiểu cũ và cồng kềnh.

+1

Tôi thực sự thích Test :: Class quá. Điều gọn gàng về Test :: Class là nó chỉ đơn giản là một cách khác để xây dựng các thử nghiệm dựa trên TAP - một khung công tác khác, chuyển đổi nó từ "Procedural" thành "Object oriented". Nó tách ra "cách báo cáo của nó" từ "Cách chạy của nó", cho phép bạn sử dụng bất kỳ Thử nghiệm nào khác :: Các bước kiểm tra kiểu/chức năng thử nghiệm khác trong đối tượng Test :: Class của bạn. NHƯNG nó không phải là để thử nghiệm dựa trên TAP hoặc - nó chỉ xảy ra là rất tốt ở đó. Bạn có thể mở rộng Test :: Class và ghi đè lên nhiều hành vi mặc định và chỉ cần sử dụng khung công tác. –

2

Một số chống khuyến nghị có thể theo thứ tự:

Anti-giới thiệu:

ĐỪNG sử dụng gia đình Test::Unit các gói thử nghiệm cho Perl như Test::Unit::AssertTest::Unit::TestCases.

Lý do: Test::Unit dường như bị bỏ qua.

Test :: Unit, Test :: Unit :: TestCases, Test :: Unit :: Assert work, khá tốt (khi tôi sử dụng chúng 2015-2016). Test :: Unit được cho là không được tích hợp với Perl's Test Anything Protocol (TAP), mặc dù tôi thấy dễ sửa lỗi.

Nhưng thử nghiệm :: Đơn vị là bực bội vì rất nhiều gói thử nghiệm Perl khác, chủ yếu được xây dựng bằng cách sử dụng Test :: Builder, như Test :: More, Test :: Most, Test :: Exception, Test :: Differences, Test :: Deep, Test :: Warn, vv, KHÔNG tương tác tốt với phương pháp thử nghiệm hướng đối tượng của Test :: Unit.

Bạn có thể kết hợp kiểm tra :: Kiểm tra đơn vị và kiểm tra :: Trình kiểm tra trình xây dựng khi bạn đã điều chỉnh thử nghiệm :: Đơn vị để làm việc với thử nghiệm :: Thêm và TAP; nhưng các tính năng tốt của các gói khác này không có sẵn cho phần mở rộng OO. Đó là nhiều lý do để sử dụng một bài kiểm tra kiểu xUnit anyway.

Giả sử CPAN Test::Class cho phép "Dễ dàng tạo các lớp thử nghiệm theo kiểu xUnit/JUnit" - nhưng tôi không chắc chắn rằng tôi có thể đề xuất điều này. Nó chắc chắn không giống như xUnit với tôi - không phải OO, tên riêng biệt như is(VAL1,VAL2,TESTNAME) thay vì tên kiểu xUnit như $test_object->assert_equals(VAL1,VAL2,TEST_ERR_MSG). Bài kiểm tra :: Lớp học có tính năng thú vị của tự động phát hiện tất cả các bài kiểm tra được chú thích: Kiểm tra, so sánh với phương pháp xUnit và TEST :: Unit :: TestCase bằng cách sử dụng nội suy để chạy tất cả các hàm có tên test_ *.

Tuy nhiên, gói cơ bản Test::Builder là hướng đối tượng và do đó nhiều kiểu xUnit hơn. Đừng sợ hãi bởi tên - nó không phải là một nhà máy, nó chủ yếu là một bộ với phương pháp xác nhận thử nghiệm. Mặc dù hầu hết mọi người thừa kế từ nó, bạn có thể gọi trực tiếp nếu bạn muốn, ví dụ: $test_object->is(VAL1,VAL2,TESTNAME) và thường bạn có thể sử dụng các cuộc gọi Test :: Builder để làm việc xung quanh các giới hạn của các gói thủ tục như Test :: More được xây dựng trên đầu trang của Test :: Builder - như sửa chữa mức callstack mà tại đó một lỗi được báo cáo.

Kiểm tra :: Trình tạo thường được sử dụng kiểu đơn, nhưng bạn có thể tạo nhiều đối tượng. Tôi không chắc chắn liệu những hành vi này có phải là điều mong đợi từ một thử nghiệm gia đình xUnit hay không.

Cho đến nay, không có cách nào dễ dàng để giải quyết các giới hạn như kiểm tra TAP Perl sử dụng TEST_NAMES, mỗi xác nhận, không có phân cấp và không phân biệt TEST_NAMES với TEST_ERROR_MESSAGES. (Mức báo cáo Err giúp với sự thiếu đó.)

Có thể tạo một bộ điều hợp làm cho Test :: Builder và kiểm tra kiểu TAP hướng đối tượng hơn, để bạn có thể rebase trên một thứ khác ngoài TAP (ghi lại nhiều hơn thông tin hữu ích hơn TAP - được cho là giao thức XML của ANT). Tôi nghĩ rằng để thích ứng với các tên và/hoặc các khái niệm còn thiếu sẽ liên quan đến việc đi vào Test :: Builder, hoặc introspection.

+0

Cảm ơn, Peter. Sạch hơn nhiều. Tôi bắt đầu giải trí khi tôi đã lãng phí thời gian bằng cách sử dụng phần mềm cũ. –