Perl derleme, birim testi, kod kapsamı: Tam bir çalışma örneği


86

Perl oluşturma süreci ve birim testi ve kod kapsamı ile ilgili bulduğum çoğu Stackoverflow yanıtı, oradaki belgeler için CPAN'a işaret ediyor. CPAN modüllerine işaret etmede kesinlikle yanlış bir şey yoktur çünkü tam dokümantasyonun burada bulunması gerekir. Yine de birçok durumda eksiksiz çalışan kod örnekleri bulmakta sorun yaşadım.

Tipik eğitici "Merhaba Dünya" örnek kaynak kodunuz gibi indirebileceğim veya IDE'ime yapıştırabileceğim, ancak birim testi ve kodla derleme sürecini gösteren bir örnek gibi, İnternet'in her yerinde gerçek çalışma kodu örneklerini araştırıyorum kapsama analizi. Bu teknolojileri ve süreçleri gösteren eksiksiz bir çalışma projesinin küçük bir örneği olan var mı?

(Küçük bir çalışma örneğim var ve bununla kendi sorumu cevaplayacağım, ancak muhtemelen benim bulduğum örneklerden daha iyi örnekleri olan başka SO kullanıcıları var.)

Yanıtlar:


105

Biraz zaman aldı ve aynı zamanda bir dizi farklı kaynaktan küçük parçacıkları alıp bunları bir araya getirmemi de aldı, ancak sanırım bir Perl acemisine birim testi ve kod kapsamı dahil olmak üzere Perl oluşturma sürecini yeterince gösteren küçük bir çalışma örneğim var. analiz ve raporlama. ( Windows XP Pro PC'de ActiveState ActivePerl v5.10.0 kullanıyorum , Module :: Build , Test :: More , Devel :: Cover )

Perl projeniz için bir dizinle başlayın ve ardından proje dizininizin altında bir "lib" dizini ve bir "t" dizini oluşturun:

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

"Lib" dizininde, "HelloPerlBuildWorld.pm" adlı bir metin dosyası oluşturun. Bu dosya, oluşturacağınız ve test edeceğiniz Perl modülünüzdür. Aşağıdaki içeriği bu dosyaya yapıştırın:

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;

"T" dizininde, "HelloPerlBuildWorld.t" adlı bir metin dosyası oluşturun. Bu dosya, yukarıdaki Perl modülünüzü tam olarak test etmeye çalışacak birim test komut dosyanızdır. Aşağıdaki içeriği bu dosyaya yapıştırın:

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");

Şimdi en üst düzey proje dizininize yedekleyin, "Build.PL" adlı bir metin dosyası oluşturun. Bu dosya, daha sonra kullanacağınız derleme komut dosyalarınızı oluşturacaktır. Aşağıdaki içeriği bu dosyaya yapıştırın:

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_addy@goes.here>',
    build_requires => {
        'Test::More' => '0.10',
    },
);

$builder->create_build_script();

İhtiyacınız olan tüm dosyalar bu. Şimdi en üst düzey proje dizinindeki komut satırından aşağıdaki komutu yazın:

perl Build.PL

Aşağıdakine benzer bir şey göreceksiniz:

Checking prerequisites...
Looks good

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

Artık birim testlerinizi aşağıdaki komutla çalıştırabilmelisiniz:

Build test

Ve buna benzer bir şey görün:

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)

Birim testlerinizi kod kapsamı analiziyle çalıştırmak için şunu deneyin:

Build testcover

Ve bunun sırasına göre bir şey göreceksiniz:

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.

(Biri lütfen bana Cover'ı nasıl yapılandıracağımı söyleyerek hariç tüm Perl kitaplıklarını yok sayacak ve yazdığım tek dosyam hakkında bana geri bildirimde bulunacak. CPAN belgelerine göre çalışmak için Kapak filtrelemesini alamadım!)

Şimdi en üst düzey dizininizi yenilerseniz, "cover_db" adlı yeni bir alt dizin görebilirsiniz. Bu dizine gidin ve kod kapsamı raporunu favori web tarayıcınızda açmak için "kapsam.html" dosyasına çift tıklayın. Dosya adınıza tıklayabileceğiniz ve Perl modülünüz için ayrıntılı açıklama, şube, koşul, alt rutin kapsama istatistiklerini tam orada gerçek kaynak kodunun yanındaki raporda görebileceğiniz güzel bir renk kodlu köprü metni raporu sunar. Bu raporda "bye ()" rutinini hiç ele almadığımızı ve ayrıca beklediğimiz gibi kapsanmayan ulaşılamayan bir kod satırı olduğunu görebilirsiniz.

kod kapsamı raporunun anlık görüntüsü
(kaynak: leucht.com )

IDE'nizde bu işlemi otomatikleştirmeye yardımcı olmak için yapabileceğiniz bir şey daha, yukarıda elle yaptığımız bazı yapı hedeflerini komut satırından açıkça gerçekleştiren bazı "Build.PL" türü dosyalar yapmaktır. Örneğin, aşağıdaki içeriğe sahip bir "BuildTest.PL" dosyası kullanıyorum:

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

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

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

Daha sonra IDE'mi bu dosyayı ("perl BuiltTest.PL" aracılığıyla) tek bir fare tıklamasıyla çalıştıracak şekilde ayarladım ve birim test kodumu komut satırından elle yapmak yerine IDE'den otomatik olarak çalıştırıyor. Otomatik kod kapsamı yürütme için "gönder ('test')" yerine "gönderi ('testcover')" yazın. Module :: Build'de bulunan derleme hedeflerinin tam listesi için "Build help" yazın.


1
Bir BuiltTest.PL kurma fikriniz bana pek iyi gelmiyor. Neden Build buildsonra bunu yapan bir senaryo yazamıyorsun Build test?
Leon Timmermans

2
Leon, komut satırı aramaları yapan bir perl betiği mi öneriyorsun? Öyleyse, örneğin BuiltTest.PL dosyasında olduğu gibi çağrıları programlı olarak yapmanın bir OO yolu varsa komut satırı çağrıları yapmamayı tercih ederim.
Kurt W. Leucht

1
Bu gerekli değil, kendi
cevabıma

2
Module :: Build sadece CPAN için değildir. CPAN'da olmasa bile çeşitli CPAN araçlarının tüm özelliklerini yine de alabilirsiniz. Özel bir modül olmasına rağmen yine de aynı işlemle oluşturabilir, test edebilir, dağıtabilir ve kurabilirsiniz.
brian d foy

4
Devel :: Cover'daki sonuçları filtrelemek için seçenekler ekledim $ENV{HARNESS_PERL_SWITCHES}. Örneğin: uygulamaya özel kitaplık -MDevel::Cover=+ignore,.t$,+inc,/app/lib,-select,MyModule.pmnerede /app/libve MyModule.pmtest edilen modüldür.
Michael Carman

14

Kurt'a yanıt olarak, bu alternatifi BuiltTest.PL betiğine öneririm.

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

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

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

Build.PL tarafından yapılan veritabanı derlemesini yeniden kullanır (ve böylece zaten çalıştığını varsayar).


Mükemmel! Teşekkürler Leon. Örneğimde bir sorun olduğunu biliyordum, ama bu perl build maddesinde kendim hala yeniyim! :-)
Kurt W. Leucht


12

Fevkalade yararlı module-starterolan, modül kurulumunu, dokümantasyonun oluşturulmasını ve modül dosyalarının içinde yaşaması için iyi bir yerleşim düzenini yöneten, kullanımı kolay bir iskelet projesi oluşturur ve - bence - kod kapsama desteğini . IMO, Perl modülü ile ilgili herhangi bir çaba için harika bir başlangıçtır.

Ayrıca: CPAN ile ilgili araçları kullanmak Module::Build- muhtemelen halka açıklanmayacak modüller için bile - çok iyi bir fikirdir .


7

(açıklama: ben yazarım)

Her şeyi yukarıda açıklandığı gibi sıraladıktan sonra, bir sonraki adıma geçebilir ve Devel :: CoverX :: Covered'i örneğin

  • Bir kaynak dosya verildiğinde, o kaynak dosyanın kapsamını sağlayan test dosyalarını listeleyin. Bu, bir dosya, alt yordam ve satır düzeyinde yapılabilir.
  • Bir test dosyası verildiğinde, o test dosyasının kapsadığı kaynak dosyaları ve alt dosyaları listeleyin.
  • Bir kaynak dosya verildiğinde, her satır veya alt.

Somut komut satırı örnekleri için özete bakın .

In Devel :: PerlySense kaynak kodu tamponunda (kapsama bilgilerini görüntülemek için Emacs desteği var ekran görüntüsü ) ve test dosyaları kapsayan üzerine / gitmek için.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.