Build Perl, pengujian unit, cakupan kode: Contoh kerja lengkap

86

Sebagian besar jawaban Stackoverflow yang saya temukan berkenaan dengan proses pembuatan Perl dan pengujian unit dan cakupan kode cukup arahkan saya ke CPAN untuk dokumentasi di sana. Sama sekali tidak ada yang salah dengan menunjuk ke modul CPAN karena di sanalah dokumentasi lengkap seharusnya berada. Saya mengalami kesulitan menemukan contoh kode yang berfungsi lengkap dalam banyak kasus.

Saya telah mencari di seluruh Internet untuk contoh kode kerja aktual yang dapat saya unduh atau tempelkan ke IDE saya, seperti contoh kode sumber tutorial "Hello World", tetapi contoh yang mendemonstrasikan proses pembuatan dengan pengujian unit dan kode analisis cakupan. Adakah yang punya contoh kecil dari proyek kerja lengkap yang mendemonstrasikan teknologi dan proses ini?

(Saya memiliki contoh kecil yang berfungsi dan saya akan menjawab pertanyaan saya sendiri dengannya, tetapi mungkin ada pengguna SO lain yang memiliki contoh lebih baik daripada yang saya buat.)

Kurt W. Leucht
sumber

Jawaban:

105

Butuh beberapa saat dan saya juga mengambil cuplikan kecil dari sejumlah sumber yang berbeda dan meleburnya bersama-sama, tapi saya rasa saya memiliki contoh kerja kecil yang cukup menunjukkan kepada pemula Perl proses pembuatan Perl termasuk pengujian unit dan cakupan kode analisis & pelaporan. (Saya menggunakan ActiveState ActivePerl v5.10.0 pada PC Windows XP Pro, Module :: Build , Test :: More , Devel :: Cover )

Mulailah dengan direktori untuk proyek Perl Anda dan kemudian buat direktori "lib" dan direktori "t" di bawah direktori proyek Anda:

HelloPerlBuildWorld
        |
        |----------> lib
        |
        |----------> t

Di direktori "lib", buat file teks bernama "HelloPerlBuildWorld.pm". File ini adalah modul Perl Anda yang akan Anda buat dan uji. Tempel konten berikut ke dalam file ini:

use strict;
use warnings;
package HelloPerlBuildWorld;

$HelloPerlBuildWorld::VERSION = '0.1';

sub hello {
   return "Hello, Perl Build World!";
}

sub bye {
   return "Goodbye, cruel world!";
}

sub repeat {
   return 1;
}

sub argumentTest {
    my ($booleanArg) = @_;

    if (!defined($booleanArg)) {
        return "null";
    }
    elsif ($booleanArg eq "false") {
        return "false";
    }
    elsif ($booleanArg eq "true") {
        return "true";
    }
    else {
        return "unknown";
    }

   return "Unreachable code: cannot be covered";
}

1;

Di direktori "t", buat file teks bernama "HelloPerlBuildWorld.t". File ini adalah skrip pengujian unit Anda yang akan mencoba sepenuhnya menguji modul Perl Anda di atas. Tempel konten berikut ke dalam file ini:

use strict;
use warnings;
use Test::More qw(no_plan);

# Verify module can be included via "use" pragma
BEGIN { use_ok('HelloPerlBuildWorld') };

# Verify module can be included via "require" pragma
require_ok( 'HelloPerlBuildWorld' );

# Test hello() routine using a regular expression
my $helloCall = HelloPerlBuildWorld::hello();
like($helloCall, qr/Hello, .*World/, "hello() RE test");

# Test hello_message() routine using a got/expected routine
is($helloCall, "Hello, Perl Build World!", "hello() IS test");

# Do not test bye() routine

# Test repeat() routine using a got/expected routine
for (my $ctr=1; $ctr<=10; $ctr++) {
    my $repeatCall = HelloPerlBuildWorld::repeat();
    is($repeatCall, 1, "repeat() IS test");
}

# Test argumentTest() 
my $argumentTestCall1 = HelloPerlBuildWorld::argumentTest();
is($argumentTestCall1, "null", "argumentTest() IS null test");

# Test argumentTest("true") 
my $argumentTestCall2 = HelloPerlBuildWorld::argumentTest("true");
is($argumentTestCall2, "true", "argumentTest() IS true test");

# Test argumentTest("false") 
my $argumentTestCall3 = HelloPerlBuildWorld::argumentTest("false");
is($argumentTestCall3, "false", "argumentTest() IS false test");

# Test argumentTest(123) 
my $argumentTestCall4 = HelloPerlBuildWorld::argumentTest(123);
is($argumentTestCall4, "unknown", "argumentTest() IS unknown test");

Sekarang kembali ke direktori proyek tingkat atas Anda, buat file teks bernama "Build.PL". File ini akan membuat skrip build yang akan Anda gunakan nanti. Tempel konten berikut ke dalam file ini:

use strict;
use warnings;
use Module::Build;

my $builder = Module::Build->new(
    module_name         => 'HelloPerlBuildWorld',
    license             => 'perl',
    dist_abstract       => 'HelloPerlBuildWorld short description',
    dist_author         => 'Author Name <[email protected]>',
    build_requires => {
        'Test::More' => '0.10',
    },
);

$builder->create_build_script();

Itu saja file yang Anda butuhkan. Sekarang dari baris perintah di direktori proyek tingkat atas, ketik perintah berikut:

perl Build.PL

Anda akan melihat sesuatu yang mirip dengan berikut ini:

Checking prerequisites...
Looks good

Creating new 'Build' script for 'HelloPerlBuildWorld' version '0.1'

Sekarang Anda harus dapat menjalankan pengujian unit Anda dengan perintah berikut:

Build test

Dan lihat sesuatu yang mirip dengan ini:

Copying lib\HelloPerlBuildWorld.pm -> blib\lib\HelloPerlBuildWorld.pm
t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18,  0 wallclock secs ( 0.00 cusr +  0.00 csys =  0.00 CPU)

Untuk menjalankan pengujian unit Anda dengan analisis cakupan kode, coba ini:

Build testcover

Dan Anda akan melihat sesuatu dalam urutan ini:

t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18, 12 wallclock secs ( 0.00 cusr +  0.00 csys =  0.00 CPU)
cover
Reading database from D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db


----------------------------------- ------ ------ ------ ------ ------ ------
File                                  stmt   bran   cond    sub   time  total
----------------------------------- ------ ------ ------ ------ ------ ------
D:/Perl/lib/ActivePerl/Config.pm       0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/ActiveState/Path.pm        0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/AutoLoader.pm              0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/B.pm                      18.6   16.7   13.3   19.2   96.4   17.6
 ...
[SNIP]
 ...
D:/Perl/lib/re.pm                      0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/strict.pm                 84.6   50.0   50.0  100.0    0.0   73.1
D:/Perl/lib/vars.pm                   44.4   36.4    0.0  100.0    0.0   36.2
D:/Perl/lib/warnings.pm               15.3   12.1    0.0   11.1    0.0   12.0
D:/Perl/lib/warnings/register.pm       0.0    0.0    n/a    0.0    n/a    0.0
blib/lib/HelloPerlBuildWorld.pm       87.5  100.0    n/a   83.3    0.0   89.3
Total                                  9.9    4.6    2.8   11.3  100.0    7.6
----------------------------------- ------ ------ ------ ------ ------ ------


Writing HTML output to D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db/coverage.html ...
done.

(Seseorang tolong beri tahu saya cara mengkonfigurasi Cover untuk mengabaikan semua pustaka Perl kecuali dan laporkan kembali kepada saya pada file tunggal yang saya tulis. Saya tidak bisa mendapatkan Cover filtering untuk bekerja sesuai dengan dokumentasi CPAN!)

Sekarang jika Anda menyegarkan direktori tingkat atas, Anda dapat melihat subdirektori baru bernama "cover_db". Masuk ke direktori itu dan klik dua kali pada file "coverage.html" untuk membuka laporan cakupan kode di browser web favorit Anda. Ini memberi Anda laporan hypertext berkode warna yang bagus di mana Anda dapat mengklik nama file Anda dan melihat pernyataan rinci, cabang, kondisi, statistik cakupan subrutin untuk modul Perl Anda tepat di laporan di sebelah kode sumber sebenarnya. Anda dapat melihat di laporan ini bahwa kami tidak mencakup rutinitas "bye ()" sama sekali dan juga ada baris kode yang tidak dapat dijangkau yang tidak tercakup seperti yang kami harapkan.

snapshot dari laporan cakupan kode
(sumber: leucht.com )

Satu hal lagi yang dapat Anda lakukan untuk membantu mengotomatiskan proses ini di IDE Anda adalah membuat beberapa file jenis "Build.PL" yang secara eksplisit menjalankan beberapa target build yang kami lakukan di atas secara manual dari baris perintah. Misalnya, saya menggunakan file "BuildTest.PL" dengan konten berikut:

use strict;
use warnings;
use Module::Build;

my $build = Module::Build->resume (
  properties => {
    config_dir => '_build',
  },
);

$build->dispatch('build');
$build->dispatch('test');

Kemudian saya menyiapkan IDE saya untuk menjalankan file ini (melalui "perl BuiltTest.PL") dengan satu klik mouse dan secara otomatis menjalankan kode pengujian unit saya dari IDE alih-alih saya melakukannya secara manual dari baris perintah. Ganti "dispatch ('test')" dengan "dispatch ('testcover')" untuk eksekusi cakupan kode otomatis. Ketik "Bantuan build" untuk daftar lengkap target build yang tersedia dari Module :: Build.

Kurt W. Leucht
sumber
1
Ide Anda untuk menyiapkan BuiltTest.PL tidak terdengar bagus bagi saya. Mengapa Anda tidak bisa menulis skrip saja Build builddan kemudian Build test?
Leon Timmermans
2
Leon, apakah Anda menyarankan skrip perl yang membuat panggilan baris perintah? Jika demikian, saya lebih suka tidak membuat panggilan baris perintah jika ada cara OO untuk membuat panggilan secara terprogram seperti pada contoh file BuiltTest.PL.
Kurt W. Leucht
1
Itu tidak perlu, lihat jawaban saya sendiri
Leon Timmermans
2
Module :: Build bukan untuk CPAN. Anda masih bisa mendapatkan semua fitur dari berbagai alat CPAN meskipun tidak ada di CPAN. Anda masih dapat membangun, menguji, mendistribusikan, dan menginstalnya dengan proses yang sama meskipun itu adalah modul pribadi.
Brian d foy
4
Untuk memfilter hasil di Devel :: Cover saya menambahkan opsi ke $ENV{HARNESS_PERL_SWITCHES}. Misalnya: -MDevel::Cover=+ignore,.t$,+inc,/app/lib,-select,MyModule.pmwhere /app/libis application-private library dan MyModule.pmmodul yang sedang diuji.
Michael Carman
14

Menanggapi Kurt, saya akan mengusulkan alternatif ini ke skrip BuiltTest.PL-nya.

use strict;
use warnings;
use Module::Build;

my $build = Module::Build->resume (
  properties => {
    config_dir => '_build',
  },
);

$build->dispatch('build');
$build->dispatch('test');

Ini menggunakan kembali database yang dibangun oleh Build.PL (dan dengan demikian mengasumsikan bahwa sudah berjalan).

Leon Timmermans
sumber
Sempurna! Terima kasih, Leon. Saya tahu ada yang salah dengan contoh saya, tapi saya sendiri masih baru mengenal hal membangun perl ini! :-)
Kurt W. Leucht
12

Saya membahas ini di Perl Menengah serta Menguasai Perl . Kurt, bagaimanapun, telah memberikan ringkasan yang bagus.

Saya menggabungkan semua ini ke dalam skrip rilis menggunakan Module :: Release . Saya mengetik satu perintah dan semuanya terjadi.

brian d foy
sumber
12

The luar biasa membantu module-startermenghasilkan proyek kerangka yang mudah digunakan yang menangani instalasi modul, pembuatan dokumentasi dan tata letak yang baik untuk file modul untuk hidup, dan - saya pikir - dukungan cakupan kode. Ini IMO awal yang bagus untuk usaha yang berhubungan dengan modul Perl.

Juga: menggunakan alat yang berhubungan dengan CPAN seperti Module::Build- bahkan untuk modul yang kemungkinan tidak akan pernah dirilis secara publik - adalah ide yang sangat bagus .

Gaurav
sumber
7

(pengungkapan: Saya penulisnya)

Setelah Anda menyortir semuanya seperti yang dijelaskan di atas, Anda dapat mengambil langkah berikutnya dan menggunakan Devel :: CoverX :: Covered ke mis

  • Dengan adanya file sumber, buat daftar file pengujian yang menyediakan cakupan untuk file sumber tersebut. Ini dapat dilakukan pada file, sub rutin dan tingkat baris.
  • Dengan adanya file pengujian, buat daftar file sumber dan sub-sub yang dicakup oleh file pengujian tersebut.
  • Diberikan file sumber, laporkan secara efisien tentang detail cakupan per baris, atau sub.

Lihat sinopsis untuk contoh baris perintah konkret.

Di Devel :: PerlySense terdapat dukungan Emacs untuk menampilkan informasi cakupan di buffer kode sumber ( tangkapan layar ), dan untuk menavigasi ke / dari file pengujian yang mencakup.

jplindstrom.dll
sumber