Bir birim test yazarken başka bir testin alt kümesi olan bir değer var mı?


15

Biraz anlaşılmış bir örnek vermek için, bir işlevin iki sayı döndürdüğünü ve ilkinin ikincisinden daha küçük olduğunu test etmek istediğimizi varsayalım:

def test_length():
    result = my_function()
    assert len(result) == 2

def test_order()
    a, b = my_function()
    assert a < b

Burada, test_lengthbaşarısız olursa, o zaman test_orderda başarısız olur. Yazmak test_lengthveya atlamak en iyi yöntem mi?

EDIT: Bu durumda, her iki testin çoğunlukla birbirinden bağımsız olduğunu, her birinin ayrı ayrı çalıştırılabileceğini veya ters sırada çalıştırılabileceğini unutmayın, bu önemli değil. Yani bu önceki soruların hiçbiri

yukarıdaki kodun bir kopyasıdır.



2
@ GlenH7 - bu farklı bir soru gibi görünüyor. Diğeri ise " Açağrıların Baynı sonucu döndürdüğü işlevleriniz varsa , her ikisini de test edersenizA ve B". Bu, test edilen fonksiyon (lar) dan ziyade testlerin örtüşmesidir. (Şu anda adlandırıldıkları gibi kafa karıştırıcı olsa da).
Telastyn


1
Açıkça söylemek gerekirse, bu testler gerçekten örtüşmüyor (başarı bağımlılığı yok). Bir işlevlambda: type('', (), {'__len__': lambda self: 2})() birincisini geçecek, ikincisini geçmeyecektir.
liori

1
@ GlenH7: FWIW, soruyu gerçekten değiştirmedim, sadece gnat-güvenli yapmaya çalıştım ;-) (@gnat: suç yok, sadece şaka!)
Doc Brown

Yanıtlar:


28

Değer olabilir, ama bu biraz koku. Testleriniz iyi yalıtılmış değil ( test_ordergerçekten iki şeyi test ettiğinden) veya testinizde çok dogmatik oluyorsunuz (iki testi aynı mantıklı şeyi test ediyor).

Örnekte, iki testi bir araya getireceğim. Evet, bu, birden fazla öneriniz olduğu anlamına gelir. Çok kötü. Hala tek bir şeyi test ediyorsunuz - işlevin sonucu. Bazen gerçek dünyada bu iki kontrol yapmak demektir.


Küçük bir noktayı kaçırsa da cevabınızı iptal ettim. Python'da ikinci test my_function, herhangi bir iddia olmaksızın tam olarak iki değer döndürmediğinde de başarısız olur - çünkü atama bir istisnaya neden olur. Dolayısıyla, aynı şeyi test etmek için birden fazla varsayım ve iki kontrol kullanmaya gerek yoktur.
Doc Brown

@DocBrown - Ben çok varsaydım, ama bilgilendirici nedenlerle rastgele istisna / hata yerine bir iddia hatası sahip olmanın değeri olup olmadığını bilmek Python hata mesajları aşina değilim.
Telastyn

Mevcut durumda hata mesajının muhtemelen yeterince bilgilendirici olacağını düşünüyorum. Ama genel olarak, durum böyle olmayabilir. Bu nedenle, böyle bir dava için genel yaklaşımın, iki ileriye yönelik bir "birleşme" düşünmek olduğunu kabul ediyorum. Testin, onaylayıcılardan birini dışarıda bırakarak daha da basitleştirilebileceği ortaya çıkarsa, para cezası.
Doc Brown

5
@DocBrown Bir iddia ile açıkça kontrol edilen diğer değer, testi inceleyen herkesin bunun testin kendisinin değil, test edilen kodun bir hatası olduğunu açıkça ortaya koymasıdır. Testlerim beklenmedik istisnalarla karşılaştığında, hangisinin gerçekten yanlış olduğunu anlamak için her zaman biraz zaman harcamak zorundayım.
Chris Hayes

@ChrisHayes: İçinde "gerek yok", "değer yok" diye yazdım.
Doc Brown

5

Testleriniz açık olmalıdır. Text_length başarısız olursa test_order başarısız olur.

Gönderdiğiniz Python'da nasıl gittiğinden emin değilim, ancak len(result)3 ise ilk başarısız olur, ancak ikincisi geçebilir (ve Python'da değilse, o zaman JavaScript gibi dillerde).

Dediğiniz gibi, fonksiyonun iki sayı döndürdüğünü ve sırayla olduğunu test etmek istersiniz. İki test var.


1
It's not completely inferred that if text_length fails test_order fails- Python'da, size bir istisna verecektir.
Doc Brown

Bence soru, başarısızlığın başarısızlık test_lengthanlamına geldiği durumla ilgilidir test_order. Javascript'te yazılmış benzer bir çift testin bu iki python testi ile aynı davranmayacağı gerçeği önemsizdir.
Dawood, Monica

2
@DavidWallace: Unutmayın, soru "test_length yazmak veya atlamak için en iyi uygulama" mıydı? Javascript'te, bir sorunu kaçırmadığınızdan emin olmak için her iki teste de ihtiyacınız vardır (iki testi biriyle birleştirmediğinizde). Python'da, ilkini (bu cevabın ilk cümlesinde reddedilir ve ikincisinde "Emin değilim" olarak ilan edilir) güvenle atlayabilirsiniz. Dürüst olmak gerekirse, iyi bir cevap farklı görünüyor. Ancak, iyi kısmı aslında JavaScript bahsettiği için bu cevabı küçümsemedim.
Doc Brown

4
@DavidWallace: Burada stackoverflow.com'da değil, bir programmers.com olduğumuzdan, IMHO birden fazla dile uygulanabilecek bir cevap vermek yalnızca belirli bir dilin cevabından daha iyidir. Ancak belirli bir dile atıfta bulunurken, cevap dil ​​hakkında doğru olmalı ve bazı özellikleri karıştırmamalıdır.
Doc Brown

1
Mesele şu ki, soru "başka bir testin alt kümesi olan bir test yazmaya değer mi?" Ve bu cevap "bazı dillerde, testlerinizin hiçbiri diğerinin bir alt kümesi değildir" der ve her iki testin de sonuçlandığı sonucuna varır. bu nedenle gerekli. Bana birisi "kodunuz C ++ 'da derlemiyor ve ayrıca C ++' da bir işlev yalnızca bir değer döndürebilir, bu yüzden iki tane döndürdüğünü test etmeniz gerekmez. ;-)
Steve Jessop

2

test_lengthBurada tek değer , eğer her şey geçerse, varlığının "uzunluğun" test edildiğini gösterir.

Bu yüzden her iki teste de gerek yok. Yalnızca saklayın, test_orderancak yeniden adlandırmayı düşünün test_length_and_order.

Bu arada, testbiraz sakar ile başlayan isimlerin kullanımını buluyorum . Ben gerçekten iddia ettiğiniz durumu açıklayan test isimlerinin güçlü bir savunucusuyum.


1
testSiğil Python'un testi çerçevesine anlamlıdır. Hangisi hayranı olup olmadığınızı değiştirmenize gerek yoktur, ancak birini kullanmayı durdurmak için gereken argümanın ağırlığını değiştirir ;-)
Steve Jessop

@SteveJessop Evet, gerekli olduğunu unutmaya devam ediyorum. Bir süre önce Python testleri yazarken, hepsini test_that_benzeri gibi başlatma alışkanlığına girdim test_that_return_values_are_in_order. Belki de test çerçevesinin gelecekteki bir versiyonu bu gereksinimi bir şekilde çözecektir.
Dawood, Monica

@DavidWallace: isterseniz öneki değiştirebilirsiniz .
Yalan Ryan

1

Eğer bu şekilde evrimleştiyseler bu testleri ayrı bırakırdım. Evet test_order, muhtemelen ne zaman başarısız olur test_length, ama kesinlikle nedenini biliyorsunuz.

Ayrıca, test_orderilk ortaya çıkan ve test edilebilir bir başarısızlık bulduysanız, sonucun muhtemelen iki değer olmadığı, bu kontrolü bir ekleyerek assertve testi yeniden adlandırmanın test_length_and_ordermantıklı olduğunu kabul edersiniz .

Ayrıca döndürülen değerlerin tamsayı türlerini de kontrol etmek zorunda olsaydınız, bu "omnibus" sonuç testine dahil ederim.

Ama şimdi sonuç için bir test piliniz olduğunu unutmayın my_function(). Bunu test etmek için birden fazla bağlam (veya daha fazla olasılıkla birden fazla parametre) varsa, artık tüm sonuçları test etmek için bir alt program olabilir.my_function() .

Ancak, birim testleri yazdığımda, normalde kenarı ve kötü durumları iyi giriş ve normal çıktıdan ayrı olarak test ediyorum (kısmen "birim" testlerimin çoğu genellikle mini entegrasyon testleri olduğu için) ve çoğu zaman sadece kırık olan çoklu onaylarla hata ayıklamadan daha fazla bilgi istiyorum bulduğum şekilde başarısız olursa ayrı testlere.

Ben muhtemelen ayrı testler ile başlar ve genişletecektir Yani test_lengthetmek test_length_and_typesve ayrılmak test_orderikincisi varsayarak, ayrı "normal işleme" olarak görülüyor.

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.