Test yapmak için gerçek koddan daha fazla değil, zaman harcamak normal midir?


211

Testleri yazdıkları kodlardan daha zor ve yazmak daha zor buluyorum. Testi yazmak için, test ettiği koddan daha fazla zaman harcamak olağandışı değil.

Bu normal mi yoksa yanlış bir şey mi yapıyorum?

Ünite testi veya test odaklı geliştirme faydalı mı? ”,“ İşlevsel testi uygulamak için sistemin kendisini uygulamaktan daha fazla zaman harcıyoruz, bu normal mi? ”Ve cevapları, testin buna değip değmediği hakkında daha fazladır (" Testleri tamamen atlamalı mıyız? "Gibi). Testler önemli olduğuna ikna olmuşken, testlere gerçek koddan daha fazla zaman harcamamın normal mi yoksa sadece ben mi olduğunu merak ediyorum.

Sorumu kabul ettiğim görüş, cevap ve vekalet sayısı dikkate alındığında, bunun sadece web sitesinde başka bir soruda ele alınmayan meşru bir kaygı olduğunu varsayabilirim.


20
Anekdot, ancak TDD yazarken kod yazmak kadar testler yazmak için zaman harcıyorum. Testler üzerinde koddan daha fazla zaman harcadığım gerçeğinden sonra test edip yazdığım zamandır.
RubberDuck

10
Ayrıca kodunuzu yazmaktan daha çok zaman harcıyorsunuz.
Thorbjørn Ravn Andersen

27
Ayrıca testler şunlardır gerçek kod. Sadece bu kısmı müşterilere göndermiyorsunuz.
Thorbjørn Ravn Andersen

5
İdeal olarak, kodunuzu yazmaktan daha fazla zaman harcayacaksınız. (Aksi takdirde, işi sadece elinizle yaparsınız.)
Joshua Taylor

5
@RubberDuck: Burada deneyim karşısında. Bazen kodları ve tasarımları oldukça düzenli olduktan sonra testler yazdığımda kodları ve testleri çok fazla tekrar yazmak zorunda kalmayacağım. Bu yüzden testleri yazmak daha az zaman alır. Bu bir kural değil, ama oldukça sık başıma geliyor.
Giorgio

Yanıtlar:


205

Bir yazılım mühendisliği kursundan, geliştirme süresinin ~% 10'unun yeni kod yazmak için harcadığını ve diğer% 90'ının hata ayıklama, test etme ve dokümantasyon olduğunu hatırlıyorum.

Birim testleri hata ayıklamayı yakaladığından ve çabayı (potansiyel olarak otomatikleştirebilen) kodla test ettiğinden, bunlara daha fazla çaba harcanması mantıklı olacaktır; Gerçek zaman, test yazmadan yapılan hata ayıklama ve testlerden daha fazla olmamalıdır.

Son olarak, testler de dokümantasyon olarak iki katına çıkmalıdır! Ünite testleri, kodun kullanılması amaçlanan şekilde yazılmalıdır; yani testler (ve kullanım) basit olmalı, karmaşık işleri uygulamaya koyunuz.

Eğer testleriniz yazmak zorsa, test ettikleri kodun kullanılması çok zordur!


4
Kodun test edilmesinin neden bu kadar zor olduğunu anlamak için iyi bir zaman olabilir :) Toplu olarak yerleştirilmiş ikili / üçlü operatörler gibi, kesinlikle gerekli olmayan karmaşık çok işlevli satırları "açmayı" dene ... Gerçekten gereksiz ikili dosyalardan nefret ediyorum yollardan biri olarak ikili / üçlü operatöre sahip / üçlü operatör ...
Nelson

53
Son bölüme katılmamak için yalvarıyorum. Çok yüksek ünite testi kapsamı hedefliyorsanız, nadir bulunan ve bazen kodunuzun kullanım amacına karşı düpedüz kullanım durumlarını kapsamalısınız. Bu köşe davaları için test yazmak, tüm işin en çok zaman alan kısmı olabilir.
otto

Bunu başka bir yerde söyledim, ancak birim testi çok daha uzun sürüyor, çünkü çoğu kod bir tür "Pareto İlkesi" kalıbı izlemeye meyilli: mantığınızın yaklaşık% 80'ini kapladığı kodun yaklaşık% 20'sini Mantığınızın% 100'ünü kaplayın (yani tüm kenar kasalarını kaplamak, ünite test kodunun yaklaşık beş katı sürer). Tabii ki, çerçeveye bağlı olarak, ortamın çoklu testler için başlatılması, gerekli genel kodun azaltılması, ancak ek planlama yapılması bile mümkündür. % 100 güvene yaklaşmak, ana yolları test etmekten çok daha fazla zaman gerektirir.
phyrfox 14:15

2
@phyrfox Bu çok temkinli olduğunu düşünüyorum, daha fazla "kodun diğer% 99 kenar davaları" gibi. Bu, testlerin diğer% 99'unun bu son durumlar için olduğu anlamına geliyor.
Mż '14

@Nelson İç içe geçmiş üçlü operatörlerin okunmasının zor olduğunu kabul ediyorum, ancak testleri özellikle zorlaştırdıklarını sanmıyorum (olası bir kombinasyondan birini kaçırdıysanız iyi bir kapsam aracı size söyleyecektir). IMO, yazılımın çok sıkı bir şekilde bağlandığında test edilmesi zor veya sabit kablolu verilere veya bir parametre olarak geçirilmeyen verilere bağlı (örneğin bir koşulun mevcut saate bağlı olduğu ve bu bir parametre olarak geçirilmediği). Bu, kodun "okunabilir" olmasıyla doğrudan ilgili değildir, elbette, tüm diğer şeylerin eşit olmasına rağmen, okunabilir kodun daha iyi olması!
Andres F.

96

Bu.

Sadece birim sınaması yapsanız bile, sınamalarda gerçekte sınanan koddan daha fazla kod olması olağan değildir. Bunda yanlış bir şey yok.

Basit bir kod düşünün:

public void SayHello(string personName)
{
    if (personName == null) throw new NullArgumentException("personName");

    Console.WriteLine("Hello, {0}!", personName);
}

Testler ne olurdu? Burada test edilecek en az dört basit vaka vardır:

  1. Kişi adı null. İstisna gerçekten atılmış mı? Yazılacak en az üç satır test kodu.

  2. Kişi adı "Jeff". "Hello, Jeff!"Cevap veriyor muyuz ? Bu dört satır test kodu.

  3. Kişi adı boş bir dizedir. Hangi çıktıyı bekliyoruz? Asıl çıktı nedir? Yan soru: işlevsel gereksinimlere uygun mu? Bu, ünite testi için dört kod satırı daha ifade eder.

  4. Kişi adı bir dize için yeterince kısa, ancak "Hello, "ünlem işareti ile birlikte kullanılamayacak kadar uzun . Ne oldu?

Bu, çok fazla test kodu gerektirir. Ayrıca, en temel kod parçaları genellikle test altındaki kod için gerekli olan nesneleri başlatan kurulum kodunu gerektirir, bu da çoğu zaman saplamalar ve alaylar, vb.

Oran çok büyükse, bu durumda birkaç şeyi kontrol edebilirsiniz:

  • Testler arasında kod çoğaltması var mı? Test kodunun olması, kodun benzer testler arasında kopyalanması (kopyala yapıştırılması) gerektiği anlamına gelmez: bu tür bir çoğaltma bu testlerin bakımını zorlaştıracaktır.

  • Gereksiz testler var mı? Genel kural olarak, bir birim testini kaldırırsanız, dal kapsamı düşmelidir. Olmazsa, yollar zaten diğer testlerle kaplandığından teste gerek olmadığını gösterebilir.

  • Sadece test etmeniz gereken kodu mu test ediyorsunuz? Üçüncü taraf kütüphanelerinin temel çerçevesini test etmeniz beklenmez , yalnızca projenin kodunu yazmanız gerekir.

Duman testleri, sistem ve entegrasyon testleri, fonksiyonel ve kabul testleri ve stres ve yük testleri ile daha da fazla test kodu eklersiniz, bu nedenle gerçek kodun her bir LOC'si için dört veya beş LOC testine sahip olmak endişelenmeniz gereken bir şey değildir.

TDD hakkında bir not

Kodunuzu sınamak için geçen süre konusunda endişeleriniz varsa, yanlış yaptığınız olabilir, ilk önce kod, daha sonra testler. Bu durumda, TDD sizi 15-45 saniyelik tekrarlarla çalışmaya, kod ve testler arasında geçiş yapmaya teşvik ederek yardımcı olabilir. TDD'nin savunucularına göre, yapmanız gereken sınama sayısını ve daha da önemlisi, yazmanız gereken iş kodunu ve özellikle sınama için yeniden yazmayı azaltarak geliştirme sürecini hızlandırır .


Let ¹ n olmak bir dize maksimum uzunluğu . İşe SayHelloyarayarak n - 1 uzunluğunda çalışması gereken bir dizi uzunluğu arayabiliriz . Şimdi, Console.WriteLineadımda, biçimlendirmenin bir istisna ile sonuçlanacak olan n + 8 uzunluğunda bir dizeyle bitmesi gerekir . Muhtemelen, bellek limitleri nedeniyle, n / 2 karakter içeren bir dize bile bir istisnaya yol açacaktır. Sorulması gereken soru, bu dördüncü testin bir birim testi olup olmadığı (biri gibi gözüküyor, ancak kaynaklar açısından ortalama birim testlere göre çok daha yüksek bir etkiye sahip olabilir) ve gerçek kodu veya temel çerçeveyi test ediyor mu?


5
Unutma, bir kişinin adı boş olabilir. stackoverflow.com/questions/4456438/…
psatek

1
@JacobRaihle @MainMa'nın a'ya personNamesığacak değer anlamına geldiğini string, ancak personNameartı değerin birleştirilmiş değerlerin taşma olduğunu kabul ediyorum string.
saat

@ JacobRaihle: Bu noktayı açıklamak için cevabımı düzenledim. Dipnotlara bakınız.
Arseni Mourzenko 14:15

4
As a rule of thumb, if you remove a unit test, the branch coverage should decrease.Yukarıda bahsettiğim dört sınavın tamamını yazıp 3. testi kaldırırsam kapsam azalır mı?
Vivek

3
"yeterince uzun" → "çok uzun" (4. maddede)?
Paŭlo Ebermann

59

İki tür test stratejisi arasında ayrım yapmanın önemli olduğunu düşünüyorum: birim testi ve entegrasyon / kabul testi.

Bazı durumlarda ünite testi gerekli olsa da, genellikle umutsuzca fazla yapılır. Bu, "% 100 kapsama alanı" gibi geliştiricilere zorlanan anlamsız ölçümlerle daha da kötüleşir. http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf bunun için zorlayıcı bir argüman sunar. Agresif birim testi ile aşağıdaki hususları göz önünde bulundurun:

  • Bir işletme değerini belgeleyen, ancak% 100 kapama oranına yaklaşmak için var olan anlamsız testlerin bolluğu. Çalıştığım yerde, yeni sınıf örnekleri oluşturmaktan başka bir şey yapmayan fabrikalar için birim testleri yazmak zorundayız . Bu değer katmaz. Veya Eclipse tarafından oluşturulan bu uzun .equals () yöntemleri - bunları test etmeye gerek yoktur.
  • Testleri kolaylaştırmak için geliştiriciler karmaşık algoritmaları daha küçük test edilebilir birimlere bölerler. Kazanmak gibi geliyor değil mi? Ortak bir kod yolunu takip etmek için 12 sınıf açmanız gerekirse. Bu gibi durumlarda, birim testi kod okunabilirliğini gerçekten azaltabilir. Bununla ilgili başka bir sorun, kodunuzu çok küçük parçalara bölerseniz, başka bir kodun alt kümesi olmanın ötesinde hiçbir gerekçe göstermeyen bir sürü sınıfla (ya da kod parçalarıyla) bitiyor olmanızdır.
  • Ayrıca bu çalışma bağlı birim testlerin bereket korumak gerekir gibi son derece coveraged kod üstlenmeden, zor olabilir sadece bu yüzden . Bu, testinizin bir bölümünün bir sınıfın ortak çalışanlarının etkileşimini de doğruladığı (genellikle alay edilen) davranışsal birim testleri tarafından daha da şiddetlenir.

Öte yandan, entegrasyon / kabul testi, yazılım kalitesinin oldukça önemli bir parçasıdır ve deneyimlerime göre, onları doğru yapmak için önemli miktarda zaman harcamanız gerekir.

Birçok dükkan TDD kool yardımcısını içti, ancak yukarıdaki bağlantıda görüldüğü gibi, bir dizi çalışma yararının yetersiz olduğunu gösteriyor.


10
Refactoring'deki puan için +1. On yıldan uzun süredir yamalı ve kırılmış eski bir ürün üzerinde çalışıyordum. Sadece belirli bir yönteme olan bağımlılıkları belirlemeye çalışmak bir günün daha iyi bir parçası olabilir ve daha sonra onları nasıl daha fazla alıkoyabileceğini anlamaya çalışmak. Beş satırlık bir değişimin 200 satırdan fazla test kodu gerektirmesi ve bir haftanın daha iyi bir parçası olması olağandışı değildi.
TMN

3
Bu. MainMa'nın cevap testinde 4 yapılmamalı (akademik bağlamın dışında), çünkü pratikte bunun nasıl olacağını düşünün ... eğer bir kişinin ismi bir dizgenin maksimum boyutuna yakınsa bir şeyler ters gitti. Test etmeyin, çoğu durumda algılayacak kod yolu yoktur. Uygun cevap, çerçevenin temel hafızanın istisnasını atmasına izin vermektir, çünkü gerçek sorun budur.
Mż '14

3
" .equals()Eclipse tarafından oluşturulan bu uzun yöntemleri test etmeye gerek yok" tarihine kadar sizi neşelendiriyorum . equals()Ve compareTo() github.com/GlenKPeterson/TestUtils için bir test cihazı yazdım. Hemen hemen her testimde uygulama yoktu. Nasıl olursa koleksiyonları kullanıyorsunuz equals()ve hashCode()doğru ve verimli bir şekilde birlikte çalışmak değil mi? Cevabın geri kalanı için tekrar tezahürat yapıyorum ve buna oy verdim. Bunu bile hibe bazı otomatik oluşturulan eşittir () yöntemleri olabilir test gerekmez, ama beni geriyor fakir uygulamaları ile pek çok böcek yaşadım.
GlenPeterson

1
@GlenPeterson Kabul ediyorum. Bir meslektaşım bu amaç için Equals Valeri yazdı. Bakınız github.com/jqno/equalsverifier
Tohnmeister

@ Ӎσᶎ hayır, hala kabul edilemez girdileri sınamak zorundasınız, bu şekilde insanlar güvenlik açıklarını bulur.
gbjbaanb

11

Genelleştirilemez.

Fiziksel temelli renderlemeden bir formül veya algoritma uygulamam gerekiyorsa, en ufak bir hata veya belirsizliğin teşhis edilmesi neredeyse imkansız olan hatalara yol açabileceğini bildiğim için 10 saatimi paranoyak birim testlerine harcayabilirim. .

Sadece bazı kod satırlarını mantıksal olarak gruplandırmak ve sadece dosya kapsamında kullanılan bir isim vermek istersem, hiç sınamayacağım (her tek işlev için test yazarken ısrar ederseniz, istisnasız) geri dönebilir mümkün olduğu kadar az işlev yazmak için).


Bu gerçekten değerli bir bakış açısı. Sorunun tam olarak cevaplanması için daha fazla içeriğe ihtiyacı var.
CLF

3

Evet, TDDing hakkında konuşuyorsanız normaldir. Otomatik testler yaptığınızda, kodunuzun istenen davranışını korursunuz. Önce testlerinizi yazdığınızda, mevcut kodun zaten istediğiniz davranışa sahip olup olmadığını belirlersiniz.

Bu şu demek:

  • Başarısız olan bir test yazarsanız, kodu en basit olanla düzeltmek, testi yazmaktan daha kısadır.
  • Başarılı bir test yazarsanız, yazmak için fazladan bir kodunuz olmaz, test yapmak için koddan daha fazla zaman harcarsınız.

(Bu, müteakip kodu yazmaya daha az zaman harcamayı amaçlayan kod yeniden düzenlemesini hesaba katmaz. Bundan sonraki testleri yazmaya daha az zaman harcamayı hedefleyen test yeniden düzenlemesi ile dengelenir.)

Evet, hatta testten sonra yazmaktan bahsediyorsanız, daha fazla zaman harcayacaksınız:

  • İstenilen davranışın belirlenmesi
  • İstenilen davranışı test etme yollarını belirleme.
  • Testleri yazabilmek için kod bağımlılıklarını yerine getirme.
  • Başarısız olan testler için kod düzeltme.

Daha çok kod yazarak harcayacaksınız.

Yani evet, beklenen bir önlem.


3

En önemli kısım olarak buluyorum.

Birim testi her zaman "doğru çalışıp çalışmadığını görmek" ile ilgili değildir, öğrenme ile ilgilidir. Bir şeyi yeterince test ettiğinizde beyninize "kodlanmış" hale gelir ve sonunda birim test sürenizi kısaltırsınız ve bitinceye kadar hiçbir şey test etmeden kendinizi tüm sınıfları ve yöntemleri yazarken bulabilirsiniz.

Bu nedenle bu sayfadaki diğer cevaplardan birinin% 90 test yaptıklarını, çünkü herkesin hedeflerinin uyarılarını öğrenmesi gerektiğini belirtti.

Ünite testi, becerilerinizi tam anlamıyla arttırdığı için yalnızca zamanınızın çok değerli bir kullanımı değil, kendi kodunuzu tekrar gözden geçirmek ve yol boyunca mantıklı bir hata bulmak için iyi bir yoldur.


2

Birçok insan için olabilir, ama buna bağlı.

Öncelikle testler yazıyorsanız (TDD), testi yazmak için harcanan süre içinde bir miktar çakışma yaşıyor olabilirsiniz, testi yazmak gerçekten de yardımcı olur. Düşünmek:

  • Sonuçların ve girişlerin belirlenmesi (parametreler)
  • Adlandırma Kuralları
  • Yapı - nereye bir şeyler koymak için.
  • Sade eski düşünce

Kodu yazdıktan sonra testler yazarken, kodunuzun kolay test edilemez olduğunu keşfedebilirsiniz, bu nedenle yazma testleri daha zor / daha uzun sürer.

Programcıların çoğu, testlerden çok daha uzun süre kod yazıyor, bu yüzden çoğunun akıcı olmamasını beklerdim. Ayrıca, test çerçevenizi anlamak ve kullanmak için gereken süreyi de eklersiniz.

Sanırım kodlamanın ne kadar sürdüğü ve birim testinin ne kadar yer aldığına ilişkin fikrimizi değiştirmemiz gerekiyor. Asla kısa vadede bakmayın ve hiçbir zaman sadece belirli bir özellik sunmak için toplam süreyi karşılaştırın, çünkü yalnızca daha iyi / daha az buggy kodu yazarken değil, aynı zamanda değiştirmesi ve yine de daha kolay hale getirmesi kolay bir kod da yazmanız gerektiğini düşünmeniz gerekir. daha iyi / daha az adamcağız.

Bir noktada, hepimiz sadece çok iyi kod yazabiliyoruz, bu yüzden bazı araç ve teknikler sadece becerilerimizi geliştirmek için çok fazla şey sunabilir. Sadece lazer kılavuzlu bir testerem olsaydı, bir ev inşa edebilirdim.


2

Test yapmak için gerçek koddan daha fazla değil, zaman harcamak normal midir?

Evet öyle. Bazı uyarılarla.

Her şeyden önce, çoğu büyük dükkanın bu şekilde çalışması anlamında "normal", bu şekilde tamamen yanlış yönlendirilmiş ve dilsiz olsa bile, yine de, çoğu büyük dükkanın bu şekilde çalışması gerçeği onu "normal" yapıyor.

Bununla, test etmenin yanlış olduğu anlamına gelmez. Test yapılmayan ortamlarda ve obsesif-kompulsif test yapılan ortamlarda çalıştım ve yine de obsesif-kompulsif testlerin testten daha iyi olduğunu söyleyebilirim.

Ve henüz TDD yapmam, (kim bilir, gelecekte de yapabilirim) ama düzenleme-çalıştır-hata ayıklama döngülerimin büyük çoğunluğunu testleri uygulayarak gerçekleştiriyorum, asıl uygulamayı değil, çok doğal olarak, çok çalışıyorum. Testlerimde, gerçek uygulamayı çalıştırmak zorunda kalmamak için mümkün olduğunca kaçın.

Bununla birlikte, aşırı testlerde ve özellikle de testlerin sürdürülmesi için harcanan zaman miktarında tehlikeler olduğunu unutmayın . (Özellikle bunu belirtmek için öncelikle bu cevabı yazıyorum.)

Roy Osherove'un Ünite Testi Sanatının ( Önsöz , 2009) önsözünde , yazar, kötü bir şekilde tasarlanan ünite testlerinin getirdiği muazzam gelişme yükü nedeniyle büyük ölçüde başarısız olan bir projeye katıldığını itiraf ediyor. geliştirme çabasının süresi. Yani, kendinizi testlerinizi sürdürmekten başka hiçbir şey yapmadan çok fazla zaman harcamakta bulursanız, bu mutlaka doğru yolda olduğunuz anlamına gelmez, çünkü "normal". Geliştirme çabanız, projeyi kurtarmak için test metodolojinizin radikal bir şekilde yeniden düşünülmesinin gerekli olabileceği sağlıksız bir moda girmiş olabilir.


0

Test yapmak için gerçek koddan daha fazla değil, zaman harcamak normal midir?

  • Evet yazmak için birim testleri kod ise (tek başına bir modül test) yüksek birleştiğinde (eski, yeterli kaygılar ayrılması eksik, bağımlılık enjeksiyon , değil geliştirilen TDD )
  • Evet , test edilecek mantığa yalnızca gui kodu ile ulaşılabilir olması durumunda entegrasyon / kabul testleri yazmak için
  • Gui kodu ve iş mantığı birbirinden ayrıldığı sürece entegrasyon / kabul testleri yazmak için hayır (Testin gui ile etkileşime girmesi gerekmez)
  • Ayrı ayrı bir kaygı varsa ünite testi yazmak için hayır , bağımlılık enjeksiyonu, kod geliştirildi , test geliştirildi (tdd)
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.