Birim testinde yeni, harika testler nasıl yazılır? [kapalı]


267

Birim testi dünyasında oldukça yeniyim ve bu hafta mevcut uygulamam için test kapsamı eklemeye karar verdim.

Bu büyük bir görevdir, çoğunlukla test edilecek sınıfların sayısı nedeniyle, aynı zamanda yazma testleri benim için yeni olduğu için.

Zaten bir grup sınıf için testler yazdım, ama şimdi bunu doğru yapıp yapmadığımı merak ediyorum.

Bir yöntem için testler yazarken, yöntemin kendisinde yazdıklarımı ikinci kez yeniden yazma hissim var.
Testlerim sadece yönteme o kadar sıkı bağlı görünüyor (tüm kodyolunu test etmek, bazı içsel yöntemlerin birkaç kez çağrılmasını beklemek, belirli argümanlarla), eğer yöntemi hiç değiştirmezsem, testler başarısız olsa bile yöntemin nihai davranışı değişmedi.

Bu sadece bir duygu ve daha önce de söylediğim gibi, test etme deneyimim yok. Orada daha deneyimli bazı testçiler bana mevcut bir uygulama için nasıl harika testler yazma konusunda tavsiyelerde bulunabilirse, bu çok takdir edilecektir.

Düzenleme: Stack Overflow teşekkür etmek istiyorum, ben az önce online okuma saat daha cevap 15 dakika içinde büyük girdiler vardı.


1
Birim testi için en iyi kitap: manning.com/osherove Birim testi için en iyi uygulamaları, yapılacakları ve yapılmayacakları açıklar.
Ervi B

Tüm bu cevapların bıraktığı bir şey, birim testlerin dokümantasyon gibi olmasıdır. Ergo, bir işlev yazarsanız, giriş ve çıkışlarını (ve muhtemelen yan etkilerini) tanımlayarak amacını belgelersiniz. Bir birim testi bunu doğrulamak içindir. Ve siz (veya bir başkası) daha sonra kodda değişiklik yaparsa dokümanlar hangi değişikliklerin yapılabileceğini açıklamalı ve birim testleri sınırların korunmasını sağlamalıdır.
Thomas Tempelmann

Yanıtlar:


187

Testlerim sadece yönteme o kadar sıkı bağlı görünüyor (tüm kodyolunu test etmek, bazı içsel yöntemlerin birkaç kez çağrılmasını beklemek, belirli argümanlarla), eğer yöntemi hiç değiştirmezsem, testler başarısız olsa bile yöntemin nihai davranışı değişmedi.

Bence yanlış yapıyorsun.

Birim testi:

  • bir yöntemi test et
  • bu yönteme bazı spesifik argümanlar sağlayın
  • sonucun beklendiği gibi olduğunu test edin

Ne yaptığını görmek için yöntemin içine bakmamalı, bu yüzden iç kısımları değiştirmek testin başarısız olmasına neden olmamalıdır. Özel yöntemlerin çağrıldığını doğrudan test etmemelisiniz. Özel kodunuzun test edilip edilmediğini öğrenmek istiyorsanız bir kod kapsama aracı kullanın. Ancak buna takıntılı olmayın:% 100 kapsama alanı bir gereklilik değildir.

Metodunuz diğer sınıflardaki genel yöntemleri çağırıyorsa ve bu çağrılar arayüzünüz tarafından garanti ediliyorsa, bu çağrıların alaycı bir çerçeve kullanarak yapıldığını test edebilirsiniz.

Beklenen sonucu dinamik olarak oluşturmak için yöntemin kendisini (veya kullandığı iç kodlardan herhangi birini) kullanmamalısınız. Beklenen sonuç, uygulama değiştiğinde değişmemesi için test durumunuza sabit olarak kodlanmalıdır. Birim testinin ne yapması gerektiğine dair basitleştirilmiş bir örnek:

testAdd()
{
    int x = 5;
    int y = -2;
    int expectedResult = 3;
    Calculator calculator = new Calculator();
    int actualResult = calculator.Add(x, y);
    Assert.AreEqual(expectedResult, actualResult);
}

Sonucun nasıl hesaplandığının kontrol edilmediğine dikkat edin - yalnızca sonucun doğru olduğundan emin olun. Mümkün olduğu kadar çok senaryo ele geçirene kadar yukarıdaki gibi daha basit test senaryoları eklemeye devam edin. İlginç yolları kaçırıp kaçırmadığınızı görmek için kod kapsamı aracınızı kullanın.


13
Çok teşekkürler, cevabınız daha eksiksizdi. Artık sahte nesnelerin gerçekten ne için olduğunu daha iyi anlıyorum: Her çağrıyı diğer yöntemlere, sadece ilgili olanlara iddia etmek zorunda değilim. Ayrıca, işlerin NASIL yapıldığını bilmeme gerek yok, ama doğru bir şekilde yaptıklarını.
pixelastic

2
Ben saygıyla düşünüyorum sen yanlış yapıyorsun. Birim testleri kod yürütme akışıyla ilgilidir (beyaz kutu testi). Kara kutu testi (önerdiğiniz şey) genellikle fonksiyonel testlerde (sistem ve entegrasyon testi) kullanılan tekniktir.
Wes

1
"Birim testi bir yöntemi test etmeli" Aslında katılmıyorum. Birim testi bir mantıksal kavramı test etmelidir. Sık sık her zaman böyle değildir bir yöntemi olarak temsil edilir iken
robertmain

35

Birim testi için, hem Test Driven (önce testler, ikinci kod) hem de önce kod, ikinci testin son derece yararlı olduğunu gördüm.

Kod yazmak yerine test yazmak. Kodu yazın ve kodun ne yapması gerektiğini DÜŞÜNÜN. Amaçlanan tüm kullanımlarını düşünün ve her biri için bir test yazın. Yazma testlerinin kodlamanın kendisinden daha hızlı ama daha ilgili olduğunu düşünüyorum. Testler amacı test etmelidir. Ayrıca, test yazma aşamasında köşe vakaları bulmak için tasarladığınız niyetleri de düşünün. Ve tabii ki testler yazarken birkaç kullanımdan birini bir hataya neden olabilir (sık sık bulduğum bir şey ve bu hatanın verileri bozmadığı ve kontrol edilmediği için çok memnunum).

Yine de test neredeyse iki kez kodlamaya benzer. Aslında uygulama kodundan daha fazla test kodu (miktar) olduğu uygulamalar vardı. Bir örnek çok karmaşık bir durum makinesiydi. Daha fazla mantık ekledikten sonra, her şeyin önceki tüm kullanım durumlarında her zaman çalıştığından emin olmalıydım. Ve bu vakaları koda bakarak takip etmek oldukça zor olduğundan, bu makine için o kadar iyi bir test paketine sahip olduğumu düşündüm ki, değişiklik yaptıktan sonra bile kırılmayacağından emindim ve testler birkaç kez kıçımı kurtardı . Kullanıcılar veya test kullanıcıları, akış veya köşe vakalarının hesaba katılmadığı hataları bulurken, tahmin edin, testlere eklendi ve bir daha asla olmadı. Bu, her şeyi süper kararlı hale getirmenin yanı sıra kullanıcılara işimde gerçekten güven verdi. Performans nedenleriyle yeniden yazılması gerektiğinde, tahmin edin ne,

Gibi tüm basit örnekler function square(number) harika ve hepsi ve muhtemelen çok fazla zaman test etmek için kötü aday. Önemli iş mantığı yapan, testin önemli olduğu nokta. Gereksinimleri test edin. Sadece su tesisatını test etmeyin. Gereksinimler değişirse, tahmin edin, testler de yapılmalıdır.

Test, kelimenin tam anlamıyla işlev çağırma işlev çubuğunu 3 kez test etmemelidir. Bu yanlış. İç mekaniğin değil, sonucun ve yan etkilerin doğru olup olmadığını kontrol edin.


2
Güzel cevap, koddan sonra test yazmanın hala faydalı ve mümkün olabileceğine dair güven verdi.
pixelastic

2
Yakın zamanda mükemmel bir örnek. Çok basit bir fonksiyonum vardı. Doğru, bir şey yapar, yanlış başka bir şey yapar. ÇOK BASİT. Fonksiyonun yapmak istediği şeyi yaptığından emin olmak için kontrol gibi 4 test vardı. Davranışı biraz değiştiriyorum. Testleri çalıştırın, POW bir sorun. Komik şey, uygulamayı kullanırken problem ortaya çıkmaz, sadece karmaşık bir durumda. Test vakası buldu ve kendime saatlerce baş ağrısını kurtardım.
Dmitriy Likhten

"Testler niyeti test etmeli." Bu bence özetliyor, kodun amaçlanan kullanımları geçmesi ve kod onları barındırabilir sağlamak gerekir. Ayrıca, testin gerçekten neyi test etmesi gerektiğini ve bir kod değişikliği yaptığınızda, o değişikliğin kodun öngörülen tüm kullanımlarını nasıl etkilediğini düşünemeyebilirsiniz - test amaçlanan tüm kullanım durumlarını karşılamayan bir değişikliğe karşı koruma sağlar.
Greenstick

18

Mevcut koda retro-fitting ünite testlerinin , ilk etapta testlerle bu kodun oluşturulmasını sağlamaktan çok daha zor olduğunu belirtmek gerekir. Bu, eski uygulamalarla ilgili en büyük sorulardan biri ... nasıl test yapılır? Bu daha önce birçok kez sorulmuştur (bu nedenle bir dupe sorusu olarak kapatılmış olabilirsiniz ) ve insanlar genellikle buraya gelir:

Mevcut kodu Test Amaçlı Geliştirmeyi Test Etmek için Taşıma

Kabul edilen cevabın kitap önerisini ikinci olarak belirttim, ancak bunun ötesinde, oradaki cevaplarda daha fazla bilgi var.


3
Testleri birinci veya ikinci olarak yazarsanız, her ikisi de iyidir, ancak testler yazarken kodların test edilebilir olduğundan emin olursunuz, böylece testler yazabilirsiniz. Kendi başınıza daha iyi kod yazılmasına neden olan "bunu nasıl test edebilirim" diye düşünürsünüz. Güçlendirme test vakaları her zaman büyük bir hayır. Çok zor. Bu bir zaman sorunu değil, bir miktar ve test edilebilirlik meselesidir. Şu anda patronuma gelemiyorum ve binlerce masamız ve kullanımımız için test senaryoları yazmak istediğimi söyleyemem, şimdi çok fazla, bir yıl beni alacaktı ve bazı mantık / kararlar unutuldu. Çok uzun süre ertelemeyin: P
Dmitriy Likhten

2
Muhtemelen kabul edilen cevap değişti. Linx'in tavsiye ettiği bir cevap var Roy Osherove tarafından yapılan birim test sanatı, manning.com/osherove
thelem

15

Kodunuzun tamamını kapsamak için testler yazmayın. Gereksinimlerinizi garanti eden testler yazın. Gereksiz kod yollarını keşfedebilirsiniz. Tersine, eğer gerekliyse, bir çeşit şartı yerine getirmek için oradalar; ne olduğunu bulun ve gereksinimi test edin (yolu değil).

Testlerinizi küçük tutun: şart başına bir test.

Daha sonra, bir değişiklik yapmanız (veya yeni kod yazmanız) gerektiğinde, önce bir test yazmayı deneyin. Sadece bir tane. O zaman test odaklı geliştirmede ilk adımı attınız.


Teşekkürler, küçük gereksinimler için birer birer küçük testler yapmak mantıklıdır. Ders öğrenildi.
pixelastic

13

Birim testi, bir işlev / yöntem / uygulamadan elde ettiğiniz çıktıyla ilgilidir. Sonucun nasıl üretildiği hiç önemli değil, sadece doğru olduğu önemli. Bu nedenle, iç yöntemleri ve bu gibi çağrıları sayma yaklaşımınız yanlıştır. Ne yapmak eğiliminde oturup belirli bir giriş değerleri veya belirli bir ortam verilen bir yöntemin dönmesi gerektiğini yazmak ve daha sonra ben geldi ne ile döndürülen gerçek değeri karşılaştıran bir test yazın.


Teşekkürler ! Yanlış yaptığımı hissettim, ama birisinin bana söylemesini sağlamak daha iyi.
pixelastic

8

Test edeceği yöntemi yazmadan önce Birim Testi yazmayı deneyin.

Bu kesinlikle işlerin nasıl yapıldığı hakkında biraz farklı düşünmeye zorlar. Yöntemin nasıl çalışacağına dair hiçbir fikriniz olmayacak, sadece ne yapılması gerekiyor.

Yöntemin bu sonuçları nasıl aldığını değil, her zaman yöntemin sonuçlarını test etmelisiniz.


Evet, yöntemlerin önceden yazılmış olması dışında bunu yapabilmek isterim. Sadece onları test etmek istiyorum. Gelecekte yöntemlerden önce testler yazacağım, tho.
pixelastic

2
@ pixelastic yöntemlerin yazıldığı gibi mi davranıyor?
committedandroider

4

testlerin sürdürülebilirliği arttırması beklenmektedir. Eğer bir yöntem ve bir test sonlarını değiştirirseniz olabilir iyi bir şey olabilir. Öte yandan, yönteminize kara bir kutu olarak bakarsanız, yöntemin içinde ne olduğu önemli değildir. Gerçek şu ki, bazı testler için bir şeyler alay etmelisiniz ve bu durumlarda yöntemi gerçekten bir kara kutu olarak ele alamazsınız. Yapabileceğiniz tek şey bir entegrasyon testi yazmaktır - test edilen hizmetin tamamen somutlaştırılmış bir örneğini yüklersiniz ve uygulamanızda çalıştığı gibi yapmasını istersiniz. Sonra bir kara kutu gibi davranabilirsiniz.

When I'm writing tests for a method, I have the feeling of rewriting a second time what I          
already wrote in the method itself.
My tests just seems so tightly bound to the method (testing all codepath, expecting some    
inner methods to be called a number of times, with certain arguments), that it seems that
if I ever refactor the method, the tests will fail even if the final behavior of the   
method did not change.

Bunun nedeni, kodunuzu yazdıktan sonra testlerinizi yazmanızdır. Eğer başka bir şekilde yaptıysanız (önce testleri yazdı) bu şekilde hissetmezdim.


Kara kutu örneği için teşekkürler, böyle düşünmemiştim. Keşke daha önce birim testi keşfetmiş olsaydım, ama maalesef durum böyle değil ve test eklemek için eski bir uygulama ile sıkışıp kaldım. Mevcut bir projeye kırık hissetmeden test eklemenin bir yolu yok mu?
pixelastic

1
Daha sonra test yazmak, daha önce test yazmaktan farklıdır, bu yüzden onunla sıkışıp kalırsınız. ancak, ilk önce başarısız olacak şekilde testleri yapıp sonra sınıfınızı sınava sokarak geçmelerini sağlayın .... böyle bir şey yapın, sınama başarısız olduktan sonra örneğinizi sınava sokun. Alaylarla aynı şey - başlangıçta alayın hiçbir beklentisi yoktur ve başarısız olacaktır, çünkü test edilen yöntem alayla bir şeyler yapacak, daha sonra testi geçecektir. Bu şekilde çok fazla hata bulursanız şaşırmam.
hvgotcodes

ayrıca, beklentilerinize gerçekten özel olun. Sadece testin bir nesne döndürdüğünü iddia etmeyin, nesnenin üzerinde çeşitli değerler olduğunu test edin. Bir değerin boş olması gerekiyorsa, öyle olduğunu test edin. Ayrıca, bazı testler ekledikten sonra yapmak istediğiniz yeniden düzenleme yaparak biraz parçalayabilirsiniz.
hvgotcodes
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.