TDD projelerinde yaşadığım sorunlar hakkında bu soruyu soruyorum. Birim testleri oluştururken aşağıdaki zorlukları fark ettim.
Büyük sahte verileri korumak zor ve gerçekçi değildir. Veritabanı yapısı değişikliklere uğradığında daha da zorlaşır.
MVVM ve GUI'yi test etme yeteneği ile bile, GUI senaryosunu yeniden oluşturmak çok fazla kod gerektirir.
Basit iş mantığına sınırlarsanız TDD'nin iyi çalıştığını deneyimliyorum. Bununla birlikte, karmaşık iş mantığını test etmek zordur çünkü test kombinasyonlarının sayısı (test alanı) çok fazladır.
Gerçekte, analiz ve tasarım kapsamındaki tüm gereklilikleri yakalamak zordur. Çoğu kez bir nota gereksinimi çelişkiye yol açar çünkü proje karmaşıktır. Çelişki uygulama aşamasında geç bulunur. TDD, gereksinimlerin% 100 doğru olmasını gerektirir. Bu gibi durumlarda, testlerin oluşturulması sırasında çelişen gereksinimlerin yakalanması beklenebilir. Ancak sorun şu ki, karmaşık senaryolarda durum böyle değil.
Bu soruyu okudum: TDD neden çalışıyor?
TDD gerçekten karmaşık kurumsal projeler için çalışıyor mu yoksa pratik olarak proje türüyle sınırlı mı?
Büyük sahte verileri korumak zor ve gerçekçi değildir. Veritabanı yapısı değişikliklere uğradığında daha da zorlaşır.
Yanlış.
Birim testi, "büyük" sahte veriler gerektirmez. Senaryoları test etmek için yeterli sahte veri ve daha fazlasını gerektirmez.
Ayrıca, gerçekten tembel programcılar, konu uzmanlarından çeşitli test durumlarının basit elektronik tablolarını oluşturmalarını ister. Sadece basit bir e-tablo.
Ardından tembel programcı, elektronik tablo satırlarını birim test senaryolarına dönüştürmek için basit bir komut dosyası yazar. Gerçekten çok basit.
Ürün geliştiğinde, test senaryolarının elektronik tabloları güncellenir ve yeni birim testleri oluşturulur. Her zaman yap. Gerçekten çalışıyor.
MVVM ve GUI'yi test etme yeteneği ile bile, GUI senaryosunu yeniden oluşturmak çok fazla kod gerektirir.
Ne? "Yeniden"?
TDD'nin amacı, Test Edilebilirlik için şeyler tasarlamaktır (Test Sürüşü Geliştirme). GUI bu kadar karmaşıksa, daha basit ve daha test edilebilir olacak şekilde yeniden tasarlanması gerekir. Daha basit, daha hızlı, daha bakımı daha kolay ve daha esnek demektir. Ancak çoğunlukla daha basit, daha test edilebilir anlamına gelir.
Basit iş mantığına sınırlarsanız TDD'nin iyi çalıştığını deneyimliyorum. Bununla birlikte, karmaşık iş mantığının test edilmesi zordur, çünkü test kombinasyon sayısı (test alanı) çok fazladır.
Bu doğru olabilir.
Ancak, konu uzmanlarından temel test senaryolarını basit bir formda (elektronik tablo gibi) sunmalarını istemek gerçekten yardımcı olur.
Elektronik tablolar oldukça büyük olabilir. Ancak, elektronik tabloları test senaryolarına dönüştürmek için basit bir Python komut dosyası kullandığım için sorun değil.
Ve. Elektronik tablolar eksik olduğu için bazı test senaryolarını manuel olarak yazmak zorunda kaldım.
Ancak. Kullanıcılar "hata" bildirdiklerinde, e-tablodaki hangi test durumunun yanlış olduğunu sordum.
O anda, konu uzmanları ya e-tabloyu düzeltirler ya da ne olması gerektiğini açıklamak için örnekler eklerlerdi. Hata raporları - çoğu durumda - açıkça bir test senaryosu problemi olarak tanımlanabilir. Gerçekten de, tecrübelerime dayanarak, hatayı kırık bir test örneği olarak tanımlamak tartışmayı çok daha basit hale getirir.
Uzmanları dinlemek, süper karmaşık bir iş sürecini açıklamaya çalışmak yerine, uzmanlar sürecin somut örneklerini üretmek zorundadır.
TDD, gereksinimlerin% 100 doğru olmasını gerektirir. Bu gibi durumlarda, testlerin oluşturulması sırasında çelişen gereksinimlerin yakalanması beklenebilir. Ancak sorun şu ki, karmaşık senaryoda durum böyle değil.
TDD'nin kullanılmaması kesinlikle gereksinimlerin% 100 doğru olmasını zorunlu kılar. Bazıları TDD'nin eksik ve değişen gereksinimleri tolere edebileceğini iddia etmektedir, burada TDD olmayan bir yaklaşım eksik gereksinimlerle çalışamaz.
TDD kullanmıyorsanız, çelişki uygulama aşamasında geç bulunur.
TDD kullanırsanız, kod bazı testleri geçtiğinde ve diğer testleri geçemediğinde çelişki daha önce bulunur. Gerçekten de, TDD size uygulamadan çok önce (ve kullanıcı kabul testi sırasında argümanlar) sürecin başlarında bir çelişki kanıt verir.
Bazı testleri geçen ve başarısız olan kodunuz var. Bu testlere sadece bakıyorsunuz ve çelişkiyi buluyorsunuz. Uygulamada gerçekten, gerçekten iyi çalışıyor çünkü şimdi kullanıcılar çelişki hakkında tartışmalı ve istenen davranışın tutarlı, somut örneklerini üretmelidir.
Evet
TDD ile ilk karşılaşmam Linux tabanlı bir cep telefonu için ara katman bileşenleri üzerinde çalışıyordu. Sonunda milyonlarca kaynak kodu satırı yaralandı ve bu da çeşitli açık kaynaklı bileşenler için yaklaşık 9 gigabayt kaynak kodu olarak adlandırıldı.
Tüm bileşen yazarlarının hem bir API hem de bir dizi birim test önermesi ve bir akran komitesi tarafından tasarım incelemesi yapılması bekleniyordu. Kimse testte mükemmellik beklemiyordu, ancak herkese açık tüm işlevlerin en az bir teste sahip olması gerekiyordu ve bir bileşen kaynak kontrolüne gönderildikten sonra, tüm birim testlerinin her zaman geçmesi gerekiyordu (bileşen yanlış bir şekilde bildirdiği için) tamam çalıştı).
Şüphesiz en azından kısmen TDD ve tüm birim testlerin her zaman geçtiği konusunda ısrar etti, 1.0 sürümü erken, bütçe altında ve şaşırtıcı bir istikrarla geldi.
1.0 sürümünden sonra, şirket müşteri talepleri nedeniyle kapsamı hızla değiştirmek istediğinden, bize TDD yapmayı bırakmamızı söylediler ve birim testlerin geçmesi gerekliliğini ortadan kaldırdılar. Kalitenin tuvalete ne kadar çabuk düştüğü şaşırtıcıydı ve daha sonra program takip etti.
Proje ne kadar karmaşıksa, TDD'den ne kadar çok fayda elde edeceğinizi savunuyorum. Başlıca faydaları, TDD'nin kodu çok daha küçük, çok daha bağımsız yığınlarda yazmaya nasıl zorlayacağının yan etkileridir. Temel faydaları:
a) Tasarımınızın çok daha erken doğrulanmasını elde edersiniz çünkü geri dönüş döngünüz başlangıçtaki testler nedeniyle çok daha sıkıdır.
b) Bitleri ve parçaları değiştirebilir ve sistemin nasıl tepki verdiğini görebilirsiniz, çünkü her zaman bir test kapsamı yorganı oluşturuyorsunuz.
c) Sonuç olarak bitmiş kod çok daha iyi olacaktır.
TDD gerçekten karmaşık projeler için çalışıyor mu?
Evet. Her proje değil, bu yüzden TDD ile iyi çalışıyor, ancak çoğu iş uygulaması gayet iyi ve saf bir TDD tarzında yazıldığında iyi çalışmayanların büyük sorunlar olmadan ATDD şeklinde yazılabileceğine bahse girerim.
Sahte veriler oluşturma ve koruma
Küçük tutun ve sadece ihtiyacınız olana sahip olun ve bu korkunç bir mesele değil. Beni yanlış anlamayın, bu bir acıdır. Ama buna değer.
Test GUI
MVVM'yi test edin ve görünüm olmadan test edilebildiğinden emin olun. Bunu, başka bir iş mantığını test etmekten daha zor bulmadım. Kod görünümünde test yapmıyorum, ancak test ettiğiniz tek şey bu noktada bağlayıcı bir mantık, hızlı bir manuel test yaptığınızda hızlı bir şekilde yakalanmayı umuyor.
İşletmeyi test etme
Sorun bulunamadı. Çok küçük testler. Yukarıda söylediğim gibi, bazı vakalar (Sudoku bulmaca çözücüleri popüler gibi görünüyor) TDD yapmak görünüşte zor.
TDD, gereksinimlerin% 100 doğru olmasını gerektirir
Hayır değil. Bu fikri nereden aldın? Tüm Çevik uygulamalar gereksinimlerin değiştiğini kabul eder. Bunu yapmadan önce ne yaptığınızı bilmeniz gerekir, ancak bu, gereksinimlerin% 100 olmasını gerektirmekle aynı şey değildir. TDD, Scrum'da, gereksinimlerin (Kullanıcı Öyküleri) tanım gereği% 100 tamamlanmadığı yaygın bir uygulamadır.
Öncelikle, sorunun genel olarak TDD'den ziyade birim testiyle ilgili olduğuna inanıyorum, çünkü söylediklerinizde gerçekten TDD'ye özgü (test-ilk + kırmızı-yeşil-refactor döngüsü) hiçbir şey göremiyorum.
Büyük sahte verileri korumak zor ve gerçekçi değildir.
Sahte verilerle ne demek istiyorsun? Bir sahte modelin neredeyse hiç veri içermediği varsayılır, yani testte bir veya iki alandan başka hiçbir alan ve test edilen sistem dışında herhangi bir bağımlılık yoktur. Sahte bir beklenti veya getiri değeri ayarlamak tek bir satırda yapılabilir, bu yüzden korkunç bir şey yoktur.
Veritabanı yapısı değişikliklere uğradığında daha da zorlaşır.
Veritabanının nesne modelinde uygun değişiklikler yapılmadan değişikliklere uğradığını kastediyorsanız, iyi bir birim testleri sizi uyarmak için tam buradadır. Aksi takdirde, modeldeki değişiklikler birim testlerine açıkça yansıtılmalıdır, ancak derleme göstergeleri ile yapılması kolay bir şeydir.
MVVM ve GUI'yi test etme yeteneği ile bile, GUI senaryosunu yeniden oluşturmak çok fazla kod gerektirir.
Haklısın, GUI'yi birim test etmek (Görünüm) kolay değil ve birçok insan onsuz iyi gidiyor (ayrıca GUI'yi test etmek TDD'nin bir parçası değil). Aksine, Controller/Presenter/ViewModel/ara katmanı tavsiye edilen birim testleri şiddetle tavsiye edilir, aslında MVC veya MVVM gibi desenlerin ana nedenlerinden biridir.
Basit iş mantığına sınırlarsanız TDD'nin iyi çalıştığını deneyimliyorum. Bununla birlikte, karmaşık iş mantığını test etmek zordur çünkü test kombinasyonlarının sayısı (test alanı) çok fazladır.
İş mantığınız karmaşıksa, birim testlerinizin tasarımı zordur. Bunları olabildiğince atomik hale getirmek size bağlıdır, her biri test edilen nesnenin yalnızca bir sorumluluğunu test eder. Birim testleri karmaşık bir ortamda daha çok gereklidir, çünkü kodda değişiklik yaparken iş kurallarını veya gereksinimlerini ihlal etmemenizi garanti eden bir güvenlik ağı sağlarlar.
TDD, gereksinimlerin% 100 doğru olmasını gerektirir.
Kesinlikle hayır. Başarılı yazılım, gereksinimlerin% 100 doğru olmasını gerektirir;) Birim testleri, şu anda gereksinimler hakkındaki görüşünüzü yansıtmaktadır; vizyon kusurlu ise, kodunuz ve yazılımınız da, birim testleri ya da değil olacaktır ... Ve birim testleri parlıyor: yeterince açık test başlıklarıyla, tasarım kararlarınız ve gereksinimler yorumunuz şeffaflaşır, bu da işaret etmeyi kolaylaştırır müşteriniz "bu iş kuralı tam istediğim gibi değil" dediğinde parmağınızı neyin değiştirmesi gerektiğine işaret edin.
Birisinin uygulamalarını test etmek için TDD'yi kullanamama nedeninin, uygulamalarının çok karmaşık olması nedeniyle şikayet ettiğini duyduğumda gülmem lazım. Alternatif nedir? Test maymunları dönüm klavyelerde vuruyor mu? Kullanıcılar test kullanıcıları olsun mu? Başka? Tabii ki zor ve karmaşık. Sizce Intel gönderilmeden fişlerini test etmiyor mu? Bu "kafa kafaya" nasıl?
> Does TDD really work for complex projects?
Deneyimlerime göre: nittests için Evet (modüllerin/özelliklerin ayrı ayrı test edilmesi) çünkü bunlar çoğunlukla bahsettiğiniz sorunlara sahip değildir: (Gui, Mvvm, Business-Modell). Hiç bir birim testi yerine getirmek için 3'den fazla alay/saplama yoktu (ama belki alanınız daha fazlasını gerektirir).
Ancak ben shure değil TDD bahsettiğiniz sorunları çözebilirse entegrasyon veya uçtan uca testlerde BDD tarzı testlerle.
Ama en azından bazı problemler azaltılabilir.
> However complex business logic is hard to test since the number > of combinations of tests (test space) is very large.
Entegrasyon testi veya uçtan uca test düzeyinde tam kapsam yapmak istiyorsanız bu doğrudur. Birim testi düzeyinde tam kapsama yapmak daha kolay olabilir.
Örnek: Karmaşık kullanıcı izinlerini kontrol etme
Bir entegrasyon testi düzeyinde
IsAllowedToEditCusterData() Fonksiyonunun test edilmesi için farklı nesnelerden kullanıcı, etki alanı, müşteri, çevre hakkında bilgi istenmesi gerekir .....
Bu parçaları taklit etmek oldukça zor.
IsAllowedToEditCusterData() bu farklı nesneleri bilmek zorundaysa bu özellikle doğrudur.
Unittest Seviyesinde, örneğin işlevin bilmesi gereken her şeyi içeren 20 parametre alan Function
IsAllowedToEditCusterData() fonksiyonuna sahip olursunuz.
IsAllowedToEditCusterData()'in bir
user, a
domain, a
customer, .... alanlarını bilmesine gerek olmadığı için, bunun test edilmesi kolaydır.
Ne zaman
IsAllowedToEditCusterData() uygulamak zorunda kaldı, ben iki aşırı yükleri vardı:
Bu 20 parametreyi almak ve daha sonra aşırı yükü karar veren 20 parametreyle çağırmaktan başka bir şey yapmayan bir aşırı yük.
(benim
IsAllowedToEditCusterData() sadece 5 parametreye sahipti ve tamamen test etmek için 32 farklı kombinasyona ihtiyacım vardı)
Misal
// method used by businesslogic // difficuilt to test because you have to construct // many dependant objects for the test public boolean IsAllowedToEditCusterData() { Employee employee = getCurrentEmployee(); Department employeeDepartment = employee.getDepartment(); Customer customer = getCustomer(); Shop shop = customer.getShop(); // many more objects where the permittions depend on return IsAllowedToEditCusterData( employee.getAge(), employeeDepartment.getName(), shop.getName(), ... ); } // method used by junittests // much more easy to test because only primitives // and no internal state is needed public static boolean IsAllowedToEditCusterData( int employeeAge, String employeeDepartmentName, String shopName, ... ) { boolean isAllowed; // logic goes here return isAllowed; }
TDD'nin (ve genel olarak birim testinin) ilgili bir nedenden dolayı neredeyse imkansız olduğunu gördüm: Karmaşık, yeni ve/veya bulanık algoritmalar. Yazdığım araştırma prototiplerinde en çok karşılaştığım sorun, kodumu çalıştırmaktan başka doğru cevabın ne olduğu hakkında hiçbir fikrim yok. Saçma derecede önemsiz durumlar dışında bir şey için makul bir şekilde elle bulmak çok karmaşık. Bu, özellikle algoritma buluşsal yöntemler, yaklaşımlar veya determinizm içermiyorsa geçerlidir. Yine de bu kodun bağlı olduğu alt düzey işlevselliği test etmeye çalışıyorum ve akıl sağlığı kontrolleri olarak ağır bir şekilde kullanıyor. Son çare test yöntemim, iki farklı kitaplık seti kullanarak ideal olarak iki farklı dilde iki farklı uygulama yazmak ve sonuçları karşılaştırmaktır.
Üzücü cevap, büyük karmaşık projeler için hiçbir şeyin gerçekten işe yaramadığıdır!
TDD başka bir şey kadar iyidir ve çoğundan daha iyidir, ancak TDD tek başına büyük bir projede başarıyı garanti etmez. Ancak başarı şansınızı artıracaktır. Özellikle diğer proje yönetimi disiplinleri ile birlikte kullanıldığında (gereksinimlerin doğrulanması, kullanım durumları, gereksinim izlenebilirlik matrisi, kod yönergeleri vb.).
TDD münhasıran kullanıldığında büyük bir karmaşık projenin tamamen başarısız olduğunu gördüm, yani en azından bir hata ayıklayıcı/IDE'ye kurmadan. Sahte veriler ve/veya testler yetersiz kaldı. Beta istemcilerin gerçek verileri hassastır ve kopyalanamaz veya kaydedilemez. Böylece, dev ekibi gerçek verilere işaret ettiğinde ortaya çıkan ölümcül hataları asla düzeltemedi ve tüm proje hurdaya çıkarıldı, herkes kovuldu, biraz.
Bu sorunu çözmenin yolu, istemci sitesinde bir hata ayıklayıcıda ateşlemek, gerçek verilere karşı yaşamak, kod boyunca adım atmak, kesme noktaları, değişkenleri izlemek, belleği izlemek vb. neredeyse bir yıllık bir süre boyunca kodlarının en iyi fildişi kuleleri süslemek için uygun olduğunu düşünen, bir kez uygulamalarını ateşlememişti. Bu aklımı havaya uçurdu.
Yani, her şey gibi, denge de anahtardır. TDD iyi olabilir, ancak buna güvenmeyin.
Birim testlerinin zorunlu teknik özellikler olduğunu unutmayın. Bu özellikle karmaşık projelerde değerlidir. Eski kod tabanınızın bunu destekleyecek herhangi bir testi yoksa, hiç kimse hiçbir şeyi değiştirmeye cesaret edemez, çünkü herhangi bir şeyi kırmaktan korkarlar.
"Wtf. Neden bu kod dalı var? Bilmiyor, belki birisinin ihtiyacı var, herkesi üzmekten daha iyi bırak ..." Zamanla karmaşık projeler çöp alanı haline gelir.
Testlerle, herkes güvenle "Büyük değişiklikler yaptım, ancak tüm testler hala geçiyor" diyebilir. Tanım olarak, hiçbir şeyi kırmadı. Bu, evrilebilecek daha çevik projelere yol açar. Belki de COBOL'u korumak için hala insanlara ihtiyacımızın nedenlerinden biri, testlerin o zamandan beri popüler olmamasıdır: P
Bütçe, gereklilikler ve takım becerilerinin kombinasyonu proje alanına 'buraya giren herkesi terk et' diyen kaderin içindeyse, tanım gereği büyük olasılıkla proje başarısız olacaktır.
Belki de gereksinimler karmaşık ve uçucu, altyapı kararsız, takım genç ve yüksek ciroya sahip ya da mimar bir aptal.
Bir TDD projesinde, bu yaklaşmakta olan başarısızlığın belirtisi, testlerin programa zamanında yazılamamasıdır; sadece 'bunun alacağı this uzun sürecek ve sadece that' olanı keşfetmeye çalışıyorsunuz.
Diğer yaklaşımlar başarısız olduklarında farklı belirtiler gösterecektir; en çok çalışmayan bir sistemin teslimi. Politika ve sözleşmeler bunun tercih edilip edilmeyeceğini belirleyecektir.
Bence, bkz. Test Odaklı Geliştirme gerçekten işe yarıyor
2008'de Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat ve Laurie Williams, “Test odaklı geliştirme yoluyla kalite iyileştirme gerçekleştirme: dört endüstriyel ekibin sonuçları ve deneyimleri“ (PDF link) ). Soyut:
Test güdümlü geliştirme (TDD), onlarca yıldır ara sıra kullanılan bir yazılım geliştirme uygulamasıdır. Bu uygulama ile bir yazılım mühendisi, başarısız birim testleri yazma ve bu testleri geçmek için uygulama kodu yazma arasında dakika dakika geçiş yapar. Test güdümlü geliştirme son zamanlarda çevik yazılım geliştirme metodolojilerinin kritik bir olanak sağlayan uygulaması olarak yeniden ortaya çıkmıştır. Bununla birlikte, çok az ampirik kanıt, bu uygulamanın endüstriyel bir bağlamda kullanılmasını desteklemektedir. Microsoft'ta üç geliştirme ekibi ve IBM'de TDD'yi benimsemiş bir geliştirme ekibi ile vaka çalışmaları yürütülmüştür. Vaka çalışmalarının sonuçları, dört ürünün serbest bırakma öncesi kusur yoğunluğunun, TDD uygulamasını kullanmayan benzer projelere göre% 40 ile% 90 arasında azaldığını göstermektedir. Sübjektif olarak, ekipler TDD'yi kabul ettikten sonra ilk geliştirme süresinde% 15-35 oranında bir artış yaşadı.
2012 yılında Ruby on Rails geliştirme uygulamaları TDD'yi varsayar. Ben şahsen test ve alay yazma rspec, nesne oluşturmak için factory_girl, tarayıcı için capybara) otomasyon, kod kapsamı için simplecov ve bu testleri otomatikleştirmek için koruma.
Bu metodolojiyi ve bu araçları kullanmanın bir sonucu olarak, Nagappan ve ark.