TDD'siz birim test anlayışı


28

TDD kullanarak geliştirmeyi planladığımız yeni (oldukça büyük) bir projemiz var.

TDD fikri başarısız oldu (pek çok iş ve iş dışı nedenlerle), ancak şu anda bir sohbetimiz var - yine de birim testleri yazmalı mı ya da olmasın. Arkadaşım TDD'siz birim testleri yazarken hiçbir şeyin (ya da sıfıra yakın) bir anlamı olmadığını söylüyor, sadece entegrasyon testlerine odaklanmalıyız. Bunun tersine, sadece kodu daha geleceğe dönüştürmek için düz birim testleri yazarken hala bir anlam olduğuna inanıyorum. Ne düşünüyorsun?

Eklendi: Bunun >> bu sorunun bir kopyası olmadığını düşünüyorum << - UT ve TDD arasındaki farkı anlıyorum. Benim sorum farklılıklar hakkında değil , TDD'siz Birim Testleri yazma duygusuyla ilgili .


22
Arkadaşınızın bu kadar saçma bir duruş için nedeninin ne olduğunu merak ediyorum ...
Telastyn

11
Bazı ünite testleri ile projelerin büyük çoğunluğu olduğu bahis olur değil TDD kullanarak.
Casey,

2
Entegrasyon seviyeleriniz ne olacak? Birimleriniz ne olacak? Her test seviyesinin altında ne sıklıkta refaktör olacaksınız? Entegrasyon testleriniz ne kadar hızlı çalışacak? Yazmaları ne kadar kolay olacak? Kodunuzun farklı bölümleri kaç tane kombinasyon halinde vaka oluşturur? vb ... Bunların cevaplarını bilmiyorsanız, o zaman kesin kararlar almak için çok erken olabilir. Bazen TDD harikadır. Bazen faydalar daha az açıktır. Bazen Birim testleri zorunludur. Bazen iyi bir entegrasyon testi seti sizi neredeyse kadar satın alır ve çok daha esnektir ... Seçeneklerinizi açık tutun.
topo Reinstate Monica

2
Tecrübeden bazı pratik tavsiyeler olarak, TDD yapmıyorsanız her şeyi test etmeyin . Ne tür testlerin değerli olduğu konusunda karar verin. Saf girdi / çıktı yöntemlerine ilişkin birim testlerinin olağanüstü derecede değerli olduğunu, bununla birlikte uygulamanın çok yüksek düzeyde entegrasyon testlerinin de (örneğin, bir web uygulamasında web istekleri gönderme) de olağanüstü değerli olduğunu buldum. Orta seviye entegrasyon testlerine ve çok fazla alay oluşturma gerektiren ünite testlerine dikkat edin. Ayrıca bu videoyu izleyin: youtube.com/watch?v=R9FOchgTtLM .
jpmc26

Güncellemeniz, sorduğunuz soruya ilişkin olarak bir anlam ifade etmiyor. TDD ve Ünite Testleri arasındaki farkı anlarsanız, sizi ünite testlerinden yazmaktan alıkoyan şeydir. Sorunuzu kapalı bırakmak için oy kullanmak, yinelemek yerine "ne istediğinizi belirlemediğiniz" şeklinde kapanmak için bir tartışma görebildiğim halde.

Yanıtlar:


52

TDD, esas olarak (1) kapsam sağlamak, (2) ve sürdürülebilir, anlaşılabilir, test edilebilir tasarımları sürmek için kullanılır. TDD kullanmıyorsanız, kod kapsamı garanti edilmez. Ancak bu, hiçbir şekilde bu hedefi terk etmeniz ve% 0 kapsama alanıyla birlikte yaşamanız gerektiği anlamına gelmez.

Regresyon testleri bir nedenden dolayı icat edildi. Bunun nedeni, uzun vadede, önleme hataları konusunda size yazmak için harcadıkları çabalardan daha fazla zaman kazandırdıklarıdır. Bu tekrar tekrar kanıtlanmıştır. Bu nedenle, ciddi organizasyon regresyon test tavsiye tüm gurulara daha yazılım mühendisliği çok daha iyi, çok olduğuna ikna edilmedikçe (ya da çok yakında bu yüzden oradaki aşağı oluyor düşünüyorsanız olduğunu hiçbir uzun çalıştırmak sizin için) evet, sen kesinlikle dünyadaki tüm diğer organizasyonlar için geçerli olan sebeplerden dolayı kesinlikle birim testlerine sahip olmalıdır: çünkü entegrasyon testlerinden daha erken hatalar yakalarlar ve bu size para kazandırır. Onları yazmamak, sokakta dolaşıp para almak gibi bir şey.


12
"TDD kullanmıyorsanız, kod kapsamı garanti edilmez.": Öyle sanmıyorum. İki gün boyunca gelişebilir ve sonraki iki gün boyunca testleri yazabilirsiniz. Önemli olan, istenen kod kapsamını alana kadar bitmiş bir özelliğin dikkate alınmamasıdır.
Giorgio

5
@DougM - Belki ideal bir dünyada ...
Telastyn

7
Ne yazık ki TDD alay ile el ele gidiyor ve insanlar kanıtladığı kadarını yapmayı bırakıncaya kadar testinizin daha hızlı çalıştığını gösteriyor . TDD öldü. Yaşasın test
MickyD

17
TDD kod kapsamını garanti etmiyor. Bu tehlikeli bir varsayım. Testlere karşı kod yazabilir, bu testleri geçebilir, ancak yine de son durumlara sahip olabilirsiniz.
Robert Harvey,

4
@MickyDuncan Tamamen endişenizi anladığımdan emin değilim. Alay etme, bir bileşeni diğerlerinden izole etmek için kullanılan ve bu bileşenin davranışının testlerinin bağımsız olarak yapılabilmesi için kullanılan mükemmel bir tekniktir. Evet, aşırı uçlara alındığında aşırı tasarlanmış bir yazılıma yol açabilir, ancak uygun şekilde kullanıldığında herhangi bir geliştirme tekniği olabilir. Ayrıca, DHH'den bahsettiğiniz makalede de belirtildiği gibi, sadece hiç tam sistem testlerini kullanma fikri, daha kötüsü olmasa da aynı derecede kötüdür. Herhangi bir özelliği test etmenin en iyi yolunun ne olduğuna karar vermek için yargıyı kullanmak önemlidir .
Jules

21

Ben oluyor birşeyden alakalı bir anekdot var elimizde benim için. TDD kullanmayan bir projeyim. Bizim QA milletlerimiz bizi bu yöne doğru hareket ettiriyorlar, ancak biz küçük bir kıyafetimiz ve çok uzun bir süreç oldu.

Neyse , son zamanlarda belirli bir görevi yapmak için üçüncü taraf bir kütüphane kullanıyordum. Bu kütüphanenin kullanımı ile ilgili bir sorun vardı, bu yüzden de aynı kütüphanenin bir versiyonunu kendi başıma yazmam istendi. Toplamda, yaklaşık 5.000 satır çalıştırılabilir kod ve zamanımın yaklaşık 2 ayı oldu. Kod satırlarının zayıf bir metrik olduğunu biliyorum, ancak bu yanıt için bunun büyüklüğün iyi bir göstergesi olduğunu düşünüyorum.

İsteğe bağlı sayıda bit izlememe izin verecek belirli bir veri yapısı vardı. Proje Java'da olduğu için, Java'ları seçtim BitSetve biraz değiştirdim (liderleri de takip edebilme yeteneğine ihtiyacım vardı, 0Java'nın BitSet'i nedense yapmazdı .....). ~% 93 kapsama alanına ulaştıktan sonra, yazdığım sistemi gerçekten vurgulayacak bazı testler yazmaya başladım. Son gereksinimlerime yetecek kadar hızlı olmalarını sağlamak için işlevselliğin bazı yönlerini kıyaslamam gerekiyordu. Şaşırtıcı olmayan bir şekilde, BitSetarabirimden geçersiz kıldığım işlevlerden biri, büyük bit kümeleriyle (bu durumda yüz milyonlarca bit) uğraşırken absürd. Diğer geçersiz kılılmış fonksiyonlar bu fonksiyona dayanıyordu, bu yüzden kocaman bir şişe boynuydu.

Yaptığım çizim kuruluna gidiyor ve alt yapısını manipüle etmek için bir yol bulmaktan bitti ne BitSetbir olduğunu long[]. Algoritmayı tasarladım, meslektaşlarına girdilerini sordum ve ardından kodu yazmaya başladım. Sonra birim testlerini yaptım. Bazıları kırıldı ve beni düzeltenler için algoritmamda nereye bakmam gerektiğini tam olarak işaret etti. Tüm hataları birim testlerinden düzelttikten sonra, işlevin gerektiği gibi çalıştığını söyleyebildim. En azından, bu yeni algoritmanın önceki algoritmanın yanı sıra çalıştığından emin olabilirim.

Tabii ki, bu kurşun geçirmez değil. Kodumda ünite testlerinin kontrol etmediği bir hata varsa, o zaman bilemem. Ama elbette, aynı kesin hata benim daha yavaş algoritmamda da olabilirdi. Ancak , bu özel işlevden kaynaklanan yanlış çıktı hakkında endişelenmeme gerekmediğine büyük bir güven ile söyleyebilirim. Önceden var olan ünite testleri, yeni algoritmayı doğru test etmek için sınamak için saatler, belki de günler boyunca tasarruf etti.

Bu , TDD'den bağımsız olarak birim testlerinin yapılması noktasıdır - yani birim testleri, kodu yeniden düzenlemeye / sürdürmeye başladığınızda, TDD'de ve TDD dışında sizin için aynısını yapar. Tabii ki, bu düzenli regresyon testi, duman testi, bulanık test, vs, ama eşleştirilmiş olmalıdır birim adı devletler olarak, size hataları yukarı attı var nerede yön veren olası en küçük, atom düzeyinde, şeyler testleri, test.

Benim durumumda, mevcut birim testleri olmadan, bir şekilde algoritmanın her zaman çalışmasını sağlayacak bir yöntem bulmalıydım. Hangisi, sonunda ... birim testi gibi görünüyor , değil mi?


7

Kodu kabaca 4 kategoriye ayırabilirsiniz:

  1. Basit ve nadiren değişir.
  2. Basit ve sık sık değişir.
  3. Karmaşık ve nadiren değişir.
  4. Karmaşık ve sık sık değişir.

Birim testleri gittiğiniz listenin aşağısında daha değerli hale gelir (önemli böcekleri yakalama olasılığı vardır). Kişisel projelerimde neredeyse her zaman kategori 4'te TDD yapıyorum. Kategori 3'te, manuel testler daha basit ve hızlı olmadığı sürece genellikle TDD yapıyorum. Örneğin, antialiasing kodunun yazılması karmaşık olabilir, ancak görsel olarak doğrulanması bir birim testi yazmaktan çok daha kolay olur, bu nedenle birim testi yalnızca bu kod sık sık değiştiyse benim için değecektir. Kodumun geri kalanı sadece bu fonksiyonda bir hata bulduktan sonra ünite testine girdim.

Belirli bir kod bloğunun hangi kategoriye girdiğini önceden bilmek zor olabilir. TDD'nin değeri, yanlışlıkla karmaşık birim testlerinin hiçbirini kaçırmamanızdır. TDD'nin maliyeti, basit birim testlerini yazmak için harcadığınız zamandır. Ancak, genellikle bir projeyle deneyimli insanlar, farklı kod bölümlerinin hangi kategoriye girdiğini makul derecede kesin olarak bilir. TDD yapmıyorsanız, en azından en değerli testleri yazmaya çalışmalısınız.


1
Antialiasing örneğinizde önerdiğiniz gibi kod üzerinde çalışırken, kodu deneysel olarak geliştirmek için en iyi şeyin, algoritmayı daha sonra yanlışlıkla kırmamamı sağlamak için bazı karakterizasyon testleri eklemektir . Karakterizasyon testleri çok hızlı ve kolaydır, bu nedenle bunu yapmanın yükü çok düşüktür.
Jules

1

Birim, bileşen, entegrasyon veya kabul testleri olsun, önemli kısmı otomatikleştirilmesi gerektiğidir. Otomatik testlere sahip olmamak, basit CRUD'lardan en karmaşık hesaplamalara kadar her türlü yazılım için ölümcül bir hatadır. Sebep, otomatik testlerin yazılmasının, yapmadığınız zamanlarda tüm testlerin manuel olarak yapılması gerekliliğinden çok daha düşük maliyetli olacaktır. Onları yazdıktan sonra, geçip geçmediklerini görmek için bir düğmeye basmanız yeterlidir. Manuel testlerin yürütülmesi her zaman uzun zaman alacaktır ve testlerin başarılı veya başarısız olduğunu kontrol edebilmek için insanlara (sıkılan canlı yaratıklara, dikkat eksikliği vb.) Bağlıdır. Kısacası, her zaman otomatik testler yaz.

Şimdi, iş arkadaşınızın TDD'siz her türlü birim testine karşı çıkmasının nedeni hakkında: Muhtemelen, üretim kodundan sonra yazılan testlere güvenmek daha zor. Ve otomatikleştirilmiş testlerinize güvenemezseniz, hiçbir şey yapmazlar . TDD döngüsünü takiben, önce test kodunu (doğru sebepten dolayı) geçmesi için üretim kodunu yazmasına izin verilmesi (ve daha fazla değil) yapmanız gerekir. Bu işlem aslında testlerinizi test ediyor, bu nedenle onlara güvenebilirsiniz. Gerçek koddan önce test yazmanın sizi birimlerinizi ve bileşenlerinizi daha kolay test edilebilir şekilde tasarlamaya zorlamasından bahsetmiyorum bile (yüksek seviyede dekuplaj, SRP uygulamalı, vb ...). Tabii ki TDD yapmak disiplini alıyor .

Bunun yerine, önce tüm üretim kodunu yazarsanız, bunun için testleri yazdığınızda, ilk çalıştırmada geçmelerini beklersiniz. Bu çok problemlidir, çünkü doğru davranışı iddia etmeden üretim kodunuzun% 100'ünü kapsayan bir test oluşturmuş olabilirsiniz (herhangi bir iddia bile yapamazsınız! Bunu gördüm. ) ilk önce doğru nedenden dolayı başarısız olup olmadığını kontrol etmek. Böylece, yanlış pozitifler olabilir. Yanlış pozitifler eninde sonunda test paketinize olan güveni kıracak, temelde insanları tekrar manuel testlere zorlayacak, bu nedenle her iki işlemin de maliyetini (yazma testleri + manuel testler) alacaksınız.

Bu , TDD'nin yaptığı gibi testlerinizi test etmenin başka bir yolunu bulmanız gerektiği anlamına gelir . Bu nedenle, testlere güvenebilmeniz için hata ayıklamaya, üretim kodunun bölümlerini vb. Yorumlamaya başvuruyorsunuz. Sorun şu ki, "testlerinizi sınama" sürecinin bu şekilde daha yavaş olması. Bu zamanı, geçici testleri çalıştırmak için harcayacağınız zamana ekleme (üretim kodunu kodlarken otomatik sınamalarınız olmadığından), benim deneyimime göre, uygulamadan çok daha yavaş genel bir işlemle sonuçlanır TDD "kitap tarafından" (Kent Beck - Örnek tarafından TDD). Ayrıca, burada bahis yapmaya ve gerçekten "testlerinizi test ettikten sonra test etmenin" TDD'den çok daha fazla disiplin aldığını söylemeye istekliyim .

Bu yüzden belki de ekibiniz TDD'yi yapmadığı için "işle ilgili ve olmayan nedenleri" yeniden değerlendirebilir. Tecrübelerime göre, insanlar TDD'nin kod bittikten sonra yazılan testlere göre daha yavaş olduğunu düşünüyorlar. Bu varsayım yukarıda okuduğunuz gibi hatalı.


0

Genellikle, testlerin kalitesi, kanıtlarına bağlıdır. Düzenli olarak 'gerçek' TDD yapmadığım için suçluyum - kullanmak istediğim stratejinin gerçekten işe yaradığını ispatlamak için bazı kodlar yazıyorum, daha sonra kodun testlerle desteklemesi gereken her durumu kapsar. Genellikle kod birimi bir sınıftır, size test kapsamı olmadan ne kadar çalışacağım hakkında genel bir fikir vermek için - yani, büyük miktarda değil. Bunun anlamı, testlerin semantik anlamının 'bitmiş' durumunda test edilen sistemle iyi bir şekilde uyuşmasıdır - çünkü SUT'un hangi davaları yerine getirdiğini ve nasıl yerine getirdiğini bilerek yazdım.

Bunun aksine, TDD agresif yeniden yapılandırma politikasıyla, testleri değiştirilen sistemin genel arayüzü olarak yazabildiğiniz en kısa sürede eski testleri kullanma eğilimindedir. Ben şahsen her iki uygulamanın işlevsel birimlerini tasarlama zihinsel iş yükünü bulmak ve benim konsantrasyon ve sık sık kayıyor testi bakım korumak için çok yüksek olması senkronize örtün testlerin semantiğini tutarak. Kod temeli, etrafta takılan testlerle sona erer ve değerli hiçbir şeyi test etmez veya sadece düz bir şey olur. Eğer siz titizlikle istediğiniz gibi disiplin ve elbette, bugüne kadar test takımı yetişmek için zihinsel kapasitesini, uygulama TDD var. Bilmiyorum, bu yüzden daha az başarılı buldum.


0

Aslında Bob Amca, Temiz Kodlayıcı videolarından birinde çok ilginç bir noktaya değindi. Red-Green-Refactor döngüsünün 2 şekilde uygulanabileceğini söyledi.

1, geleneksel TDD yolu. Başarısız olan bir test yazın, sonra testten geçirin ve son olarak refaktör yapın.

İkinci yol, çok küçük bir üretim kodu kodu yazıp derhal bunu birim testinden sonra refaktör takip etmektir.

Fikir çok küçük adımlarla gitmektir . Tabii ki, testinizin kırmızıdan yeşile geçtiği üretim kodundaki doğrulamayı kaybedersiniz, ancak bazı durumlarda TDD'yi anlamaya çalışmayı bile reddeden genç geliştiricilerle çalıştığım bazı durumlarda bunun etkili olduğunu kanıtladı.

Yine yineliyorum (ve bu Bob Amca tarafından vurgulandı), fikir çok küçük adımlarla ilerlemek ve yeni eklenmiş olan üretim kodunu hemen test etmek.


“... fikir çok küçük adımlarla ilerlemek ve yeni eklenen üretim kodunu hemen test etmek.”: Kabul etmiyorum. Ne yapmak istediğinizi net bir fikre sahipseniz ve detaylar üzerinde çalışmak istediğinizde iyiyseniz neyi tarif edersiniz, ancak önce büyük resmi elde etmeniz gerekir. Aksi takdirde, çok küçük adımlarla (test, geliştir, test et, geliştir) giderek ayrıntılarda kaybolabilirsiniz. “Nereye gittiğinizi bilmiyorsanız oraya ulaşamayabilirsiniz.”
Giorgio,
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.