2011-02-09 16 views
5

Tamam, bu soru, normal soru seviyemden potansiyel olarak 'stupider' olur - ancak bu sorun son birkaç gündür beni sinirlendiriyordu, bu yüzden yine de soracağım. Sorunumun ne olduğuna dair sahte bir örnek vereceğim, böylece mevcut sorunuma genelleştirmeyi ümit edebilirim. Ben de yorumladı uncomment veya is ($price, '1.50', 'Great Success') kullanmak - Bu çalıştırılır ŞimdiPerl, dizeleri, yüzer, birim testi ve düzenli ifadeler!

#!/usr/bin/perl -w use strict; 

use Test::More 'no_plan'; 

my $fruit_string = 'Apples cost $1.50'; 
my ($fruit, $price) = $fruit_string =~ /(\w+)s cost \$(\d+\.\d+)/; 

# $price += 0; # Uncomment for Great Success 
is ($price, 1.50, 'Great Success'); 

Ben

# Failed test 'Great Success' 
#   got: '1.50' 
#  expected: '1.5' 

Test çalışması için mesaj alıyorum. Her iki seçenek de benim için çalışmıyor - Test :: Deep ve cmp_deeply kullanarak büyük miktarda iç içe geçmiş verileri test ediyorum. Benim sorum şu ki, bir regexp'den bir çifresini nasıl çıkartabiliyorsunuz, sonra bir çift olarak hemen kullanabiliyorsunuz - ya da daha iyi bir yol varsa, tamamen bana bildirin - ve bana bahçıvanlık ya da bir şey lol gibi şeyler söyleme konusunda çekinmeyin, Perl öğrenmek zor.

+0

Dizeyle sayıyı karşılaştırıyorsunuz, dolayısıyla dizelerle karşılaştırılıyorlar. Onunla bir şey yapabileceğini sanmıyorum. –

cevap

10

olarak yorumlanır Zaten bu yüzden sadece için num() kapsayıcı kullanabilir Test::Deep, kullanıyorsanız stringle karşılaştırma yerine bir sayısal gerçekleştirin (iki hatalı kayan nokta değerini karşılaştırmak için bile bir tolerans eklemenize izin verir):

Ayrı olarak yapılan normal karşılaştırmalar için cmp_ok çalışmaya devam edecek, ancak num() hala kullanılabilir: cmp_deeply($value, num(1.5), 'test name') hala çalışıyor.

+1

Tam olarak aradığım şey, çok teşekkürler. –

1

Kuvvet $price sayı olarak yorumlanmalıdır: Bu davranış için

is (0 + $price, 1.50, 'Great Success'); 
+2

@Platinum Azure: Hayır, gerçekten numarayı eklemeniz gerekiyor. Dene. – btilly

+0

Yup, emin olmak için tekrar perlop'a baktım ve haklısın. Belki Perl 6 ya da bir şey düşünüyorum. –

+1

Benim yazımda belirttiğim gibi, 0 + $ fiyatını kullanamıyorum, cmp_deeply kullanıyorum - 0 + $ fiyatını kullanıyorum, geçerli kodumdan geçip her değişkeni yapmak zorundayım. bir çift olmalı. –

0

nedeni, karşılaştırmalar yapmak eq kullanır bağımsız değişkenlerini stringification zorlar hangi. 1.50, '1.5' olarak adlandırır ve bu başarısız olur.

Seçimleriniz davranışla (zorlama dizgisi veya sayısal numaralandırma) birlikte yaşamak ya da her iki tarafın, karşılaştırma karşılaştırmasına geri dönmeden önce sayıları gibi görünmesi durumunda sayısal olarak karşılaştırılacak olan kendi alternatifinizi yazmaktır. Kişisel olarak ikinci yaklaşıma giderdim.

1

Neden denenmiş ve doğruyu kullanmıyorsunuz ok? Gerçekten test etmek istediğiniz şeyi test edeceksiniz ve is'un çok ince veya çok zekice bir şey yapıp yapmadığına dair endişelenmenize gerek kalmayacaktır.

ok($price == 1.5, 'Great Success'); 

is başarısızlık bazı ek teşhis sağlar, ancak bu da

ok($price == 1.5, 'Great Success') or diag("Expected \$price==1.5, got $price"); 
+1

', başarısız bir onaylama durumunda beklenen ve verilen değerleri sağlar. – Tim

1

is($x, $y, $name)cmp_ok($x, 'eq', $y, $name) eşdeğer olduğu için testler başarısız oluyor ok ile yapmak için yeterli kolaydır. eq, argümanlarının her birini dizgiler olarak değerlendirilmek üzere zorlar. Sayısal eşitliği istediğinizden, '==' kullanarak cmp_ok ile yazabilirsiniz. Yanlış hatlarında hataları rapor eder

sub is_num {cmp_ok $_[0], '==', $_[1], $_[2]} 

Ama bu sürümü ustaca bozuldu: Sen is kendi sayısal versiyonunu yazarak şeyler daha kolay yapabiliriz. Hata Raporlama doğru çizgiler gösterir emin olmak için: cmp_ok hata oldu yeri belirlemek için caller kullandığından goto &sub için

sub is_num {splice @_, 1, 0, '=='; goto &cmp_ok} 

nedenidir. goto &sub sözdizimi is_num için çağrı çerçevesi ayarını siler, böylece cmp_ok, is_num'un bulunduğu konumdan çağrıldığını düşünür.

Son olarak, Test::More için sözdizimsel şeker sağlar Modülümde Test::Magic bir fiş:

use Test::Magic 'no_plan'; 

... # setup code 

test 'fruit price', 
    is $price == 1.50; 

cmp_ok($price, '==', 1.50, 'fruit price')

+0

'goto' yerine, başarısız olan testin bildirildiği yeri değiştirmek için yerel $ Test :: Builder :: Level = $ Test :: Builder :: Level + 1; – Ether

+0

@Ether => Perl, şeffaf bir şekilde göndermek için genel bir amaç sağladığında neden API'ye özel bir çözüm kullanıyor? '$ Test :: Builder :: Level' ayarının gerekli olduğu birkaç durum vardır (bir arama sitesinden birden fazla test çalıştırılması veya post test eylemleri gerçekleştirilmesi), ancak bunlardan biri değildir. –