El ile birim testleri yazmak Örnekle Kanıt mı?


9

JUnit testleri yazmanın, kodunuz aracılığıyla belirli bir yolu gösterdiğini biliyoruz .

Ortaklarımdan biri yorum yaptı:

Ünite testlerini manuel olarak yazmak Örnek ile Kanıttır .

Quickcheck gibi araçlara ve türlerle program davranışı hakkında akıl yürütme yeteneğine sahip Haskell'in arka planından geliyordu .

Onun anlamı, kodunuzun test edilmediği bu yöntemle denenmemiş çok sayıda başka giriş kombinasyonu olmasıydı.

Sorum şu: El ile birim testleri yazmak Örnekle Kanıt mı?


3
Hayır, test yazma / kullanma . Ünite testlerinizin programda yanlış bir şey olmadığının kanıtı olduğunu iddia etmek Örnek ile Kanıttır (uygunsuz bir genelleme). Testler, kod doğruluğunu matematiksel olarak kanıtlamakla ilgili değildir - testler, doğası gereği deneysel kontrollerdir. Kod hakkında bir şeyler söyleyerek güven oluşturmanıza yardımcı olan bir güvenlik ağıdır. Ancak kodu incelemek için iyi bir strateji seçmek zorundasınız ve bu verilerin ne anlama geldiğini yorumlamak zorundasınız.
Filip Milovanović

Yanıtlar:


10

Test için girişleri rastgele seçiyorsanız, Örnek ile Kanıtlama örneğini mantıksal bir yanlışlık kullanmanın mümkün olabileceğini düşünüyorum.

Ancak iyi birim testleri bunu asla yapmaz. Bunun yerine, aralıklar ve uç davalarla ilgilenirler .

Örneğin, girdi olarak bir tamsayıyı kabul eden mutlak değer işlevi için birim testleri yazacak olsaydınız, kodun çalıştığını kanıtlamak için olası her giriş değerini test etmeniz gerekmez. Kapsamlı bir test elde etmek için yalnızca beş değere ihtiyacınız vardır: -1, 0, 1 ve giriş tamsayı için maksimum ve min değerleri.

Bu beş değer, işlevin olası her aralığını ve kenar durumunu test eder. İşlevin tüm giriş değerleri için çalıştığına dair yüksek bir güven düzeyi elde etmek için diğer tüm olası giriş değerlerini (yani tamsayı türünün temsil edebileceği her sayı) test etmeniz gerekmez.


11
Kod test cihazı bir bara girer ve bir bira sipariş eder. 5 bira. -1 bira, MAX_VALUE bira, bir tavuk. boş.
Neil

2
"5 değer" tamamen saçmalıktır. Gibi önemsiz bir işlevi düşünün int foo(int x) { return 1234/(x - 100); }. Ayrıca, (test ettiğiniz şeye bağlı olarak) geçersiz ("aralık dışı") girişin doğru sonuçlar verdiğinden emin olmanız gerekebileceğini unutmayın (örn. Eğer bir şey bulunamazsa).
Brendan

3
@Brendan: Beş değer olması konusunda önemli bir şey yok; benim örneğimde sadece beş değer var. Farklı bir işlevi test ettiğiniz için örneğinizde farklı sayıda test var. Her fonksiyonun tam olarak beş test gerektirdiğini söylemiyorum; cevabımı okuyarak bunu çıkardın.
Robert Harvey

1
Üretkenlik testi kitaplıkları, en son vakaları test etmede genellikle sizden daha iyidir. Örneğin, bunun yerine tamsayılar şamandıralar kullanılmadan edildi ederse, kütüphane de kontrol ediyorum -Inf, Inf, NaN, 1e-100, -1e-100, -0, 2e200... Daha doğrusu bütün elle bu yapmak istemem.
Hovercouch

@Hovercouch: İyi bir tanesini biliyorsanız, bunu duymak isterim. Gördüğüm en iyisi Pex; yine de inanılmaz derecede dengesizdi. Unutmayın, burada nispeten basit işlevlerden bahsediyoruz. Gerçek hayattaki iş mantığı gibi şeylerle uğraşırken işler daha da zorlaşır.
Robert Harvey

8

Herhangi bir yazılım testi, sadece JUnit gibi bir araç kullanılarak yapılan birim testleri değil, "Örnekle Kanıtla" gibidir. Ve bu yeni bir bilgelik değil , 1960'dan Dijkstra'dan bir alıntı var , bu aslında aynı diyor:

"Test hataların varlığını değil varlığını gösterir"

(sadece "gösteriler" kelimelerini "ispatlar" ile değiştirin). Ancak bu, rastgele test verileri üreten araçlar için de geçerlidir. Gerçek dünya işlevi için olası girdi sayısı, büyüklük sıralarına göre, genellikle, bu vakaları oluşturma yönteminden bağımsız olarak, evren çağında beklenen bir sonucu üretebileceği ve doğrulayabileceği test vakalarının sayısından daha büyüktür, bu nedenle çok sayıda test verisi üretmek için bir jeneratör aracı kullansa bile, belirli bir hatayı tespit edebilecek tek test senaryosunu kaçırmamanın garantisi yoktur.

Rastgele testler bazen manuel olarak oluşturulan test senaryoları tarafından gözden kaçan bir hata ortaya çıkarabilir. Ancak genel olarak, testleri test edilecek işleve dikkatlice hazırlamak ve mümkün olduğunca az sayıda test vakasıyla tam kod ve şube kapsamı aldığından emin olmak daha etkilidir. Bazen manuel ve rastgele oluşturulan testleri birleştirmek uygun bir stratejidir. Ayrıca, rastgele testler kullanılırken, sonuçların tekrarlanabilir bir şekilde elde edilmesine özen gösterilmelidir.

Bu nedenle, manuel olarak oluşturulan testler hiçbir şekilde rastgele üretilen testlerden daha kötü değildir, çoğu zaman bunun tam tersidir.


1
Rastgele kontrol kullanan herhangi bir pratik test paketinde de birim testleri olacaktır. (Teknik olarak, birim testler sadece rastgele bir rastgele test örneğidir.) İfadeleriniz rastgele testlerin gerçekleştirilmesinin zor olduğunu veya rastgele test ile birim testlerini birleştirmenin zor olduğunu göstermektedir. Bu genellikle böyle değildir. Kanımca, randomize testin en büyük faydalarından biri, her zaman tutulması amaçlanan kodla ilgili özellikler olarak testlerin yazılmasını şiddetle teşvik etmesidir. Ben çok bu özellikleri açıkça bazı nokta testleri çıkarmak zorunda daha açıkça (ve kontrol!) Belirtti.
Derek Elkins SE

@DerekElkins: "zor" IMHO yanlış terim. Rastgele testler oldukça fazla çaba gerektirir ve bu, el işi testleri için mevcut zamanı azaltan bir çabadır (ve soruda belirtilen gibi sloganları takip eden insanlarınız varsa, muhtemelen hiç el işi yapmayacaklardır). Bir kod parçasına çok fazla rastgele test verisi atmak işin sadece yarısıdır, ayrıca bu test girişlerinin her biri için beklenen sonuçları üretmek zorundadır. Bazı senaryolar için bu otomatik olarak yapılabilir. Diğerleri için değil.
Doc Brown

İyi bir dağıtım seçmek için bazı düşüncelere ihtiyaç duyulan zamanlar kesinlikle olsa da, bu genellikle büyük bir askıya alma değildir. Yorumunuz bunu yanlış şekilde düşündüğünüzü gösteriyor. Rastgele kontrol için yazdığınız özellikler, model kontrolü veya resmi provalar için yazdığınız özelliklerin aynısıdır. Gerçekten de, tüm bu şeyler için aynı anda kullanılabilir ve kullanılabilir. Sizin de üretmeniz gereken herhangi bir "beklenen sonuç" yoktur. Bunun yerine, her zaman tutulması gereken bir özelliği belirtmeniz yeterlidir. Bazı örnekler: 1) bir yığının üstüne bir şey itmek ve ...
Derek Elkins SE

... sonra haşhaş hiçbir şey yapmamakla aynı olmalı; 2) 10.000 $ 'dan fazla bakiyesi olan herhangi bir müşteri, yüksek bakiye faiz oranını almalı ve ancak o zaman; 3) hareketli grafiğin konumu her zaman ekranın sınırlayıcı kutusundadır. Bazı özellikler nokta testlerine iyi karşılık gelebilir, örneğin "denge $ 0 olduğunda sıfır denge uyarısı verir". Özellikler, toplam spesifikasyon elde etme idealiyle kısmi spesifikasyonlardır. Bu özellikleri düşünmekte güçlük çekmek, şartnamenin ne olduğu konusunda belirsiz olduğunuz anlamına gelir ve genellikle iyi birim testleri düşünmekte zorlanacağınız anlamına gelir.
Derek Elkins SE

0

Testleri manuel olarak yazmak "örnek olarak kanıt" tır. Ancak QuickCheck ve sınırlı ölçüde tip sistemler de öyle. Düzgün resmi doğrulama olmayan herhangi bir şey, kodunuz hakkında söylediklerinde sınırlı olacaktır. Bunun yerine, yaklaşımların göreli değeri açısından düşünmek zorundasınız.

QuickCheck gibi üretken testler, geniş bir girdi alanını süpürmek için gerçekten iyidir. Ayrıca, son durumlarla başa çıkmak için manuel testlerden çok daha iyidir: üretken test kütüphaneleri bu konuda sizden daha deneyimli olacaktır. Öte yandan, size belirli çıktılar değil, yalnızca değişmezler hakkında bilgi verirler. Bu nedenle, programınızın doğru sonuçları aldığını doğrulamak için, aslında bunu doğrulamak için bazı manuel testlere ihtiyacınız vardır foo(bar) = baz.

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.