Birim testi yerine kabul ve entegrasyon testlerini kullanmak yeterli mi?


62

Bu soruya kısa bir giriş. Şimdi TDD'yi ve son zamanlarda BDD'yi bir yıldan fazla bir süredir kullanıyorum. Testlerimi daha verimli yazmak için alay etme gibi teknikleri kullanıyorum. Son zamanlarda kendime küçük bir para yönetimi programı yazmak için kişisel bir projeye başladım. Eski kodum olmadığından TDD ile başlamak için mükemmel bir projeydi. Talihsiz TDD'nin sevincini o kadar fazla yaşamadım. Hatta projemden vazgeçtim ki eğlencemi o kadar mahvediyordum.

Problem neydi? Testlerin / gereksinimlerin programın tasarımını geliştirmesine izin vermek için TDD benzeri bir yaklaşım kullandım. Sorun yazma / refactor testleri için geliştirme süresinin yarısından fazlasının olmasıdır. Sonuçta daha fazla özellik uygulamak istemedim çünkü yeniden test edip birçok teste yazmak zorunda kalacağım.

İşte bir sürü eski kodum var. Burada daha fazla entegrasyon ve kabul testi ve daha az birim testi yazarım. Bu kötü bir yaklaşım gibi görünmüyor çünkü böcekler çoğunlukla kabul ve entegrasyon testleri tarafından tespit ediliyor.

Benim fikrim, sonuçta birim testlerden daha fazla entegrasyon ve kabul testi yazabilmemdi. Hataları tespit etmek için dediğim gibi, birim testleri entegrasyon / kabul testlerinden daha iyi değildir. Birim testi de tasarım için iyidir. Bunları çok yazdığımdan beri sınıflarım her zaman iyi bir test edilebilir olacak şekilde tasarlandı. Ek olarak, testlerin / gereksinimlerin tasarıma yol göstermesine izin verme yaklaşımı çoğu durumda daha iyi bir tasarıma götürür. Birim testlerinin son avantajı, daha hızlı olmalarıdır. Neredeyse ünite testleri kadar hızlı olabileceklerini bilmek için yeterince entegrasyon testi yazdım.

Ben öğrendim web üzerinden bakıyordu sonra söz konusu madende çok benzer fikirler olduğunu burada ve orada . Bu fikir hakkında ne düşünüyorsunuz?

Düzenle

Tasarımın iyi olduğu yerlere bir örnek sorulara cevap vermekle birlikte, bir sonraki gereksinim için çok büyük bir yeniden düzenlemeye ihtiyacım vardı:

İlk başta belirli komutları yerine getirmek için bazı gereksinimler vardı. Genişletilebilir bir komut ayrıştırıcı yazdım - bir tür komut isteminden komutları ayrıştırıp modelde doğru olanı çağırdım. Sonuç, bir görünüm modeli sınıfında temsil edildi: İlk tasarım

Burada yanlış bir şey yoktu. Tüm sınıflar birbirinden bağımsızdı ve kolayca yeni komutlar ekleyebilir, yeni veriler gösterebilirdim.

Bir sonraki şart, her komutun kendi görünüm temsiline sahip olması gerektiği idi - komutun sonucunun bir tür önizlemesi. Yeni gereksinime göre daha iyi bir tasarım elde etmek için programı yeniden tasarladım: İkinci tasarım

Bu da iyiydi, çünkü şimdi her komutun kendi görüş modeli ve dolayısıyla kendi ön izlemesi var.

Mesele şu ki, komut ayrıştırıcısının komutları belirteç tabanlı bir ayrıştırma kullanmak üzere değiştirildiği ve komutları yürütme yeteneğinden sıyrıldığı. Her komut kendi görünüm modeline sahipti ve veri görünüm modeli sadece mevcut olan komut görünüm modelini sadece gösterilmesi gereken verileri bildiğinden biliyor.

Bu noktada bilmek istediğim, yeni tasarımın mevcut herhangi bir şartı ihlal etmemesiydi. Kabul testimden HERHANGİ bir tane değiştirmek zorunda değildim. Çok büyük bir iş yığını olan neredeyse HER ünite testini yeniden düzenlemek ya da silmek zorunda kaldım.

Burada göstermek istediğim şey geliştirme sırasında sıkça görülen ortak bir durum. Eski ya da yeni tasarımlarla ilgili herhangi bir sorun yoktu, sadece doğal olarak gereksinimlerle değişti - nasıl anladım, bu TDD'nin tasarımın geliştiği bir avantajı.

Sonuç

Tüm cevaplar ve tartışmalar için teşekkürler. Bu tartışmanın özeti olarak bir sonraki projem ile test edeceğim bir yaklaşım düşündüm.

  • Öncelikle her zaman yaptığım gibi bir şey uygulamadan önce tüm testleri yazıyorum.
  • Gereksinimler için ilk önce tüm programı test eden bazı kabul testleri yazarım. Sonra gereksinimi uygulamam gereken bileşenler için bazı bütünleştirme testleri yazarım. Bu gerekliliği yerine getirmek için başka bir bileşenle birlikte çalışan bir bileşen varsa, her iki bileşenin birlikte test edildiği bazı entegrasyon testlerini de yazarım. Son fakat en az değil, eğer bir algoritma ya da yüksek permütasyona sahip başka bir sınıf yazmak zorunda kalırsam - örneğin bir seri hale getirici - bu belirli sınıflar için birim testleri yazarım. Diğer tüm sınıflar test edilmez, ünite testleri yapılır.
  • Hatalar için işlem basitleştirilebilir. Normalde bir hataya bir veya iki bileşen neden olur. Bu durumda, hatayı test eden bileşenler için bir entegrasyon testi yazardım. Bir algoritmayla ilgili olsaydı, sadece bir birim testi yazardım. Eğer hatanın oluştuğu bileşeni tespit etmek kolay değilse, hatayı bulmak için bir kabul testi yazardım - bu bir istisna olmalı.


Bu soruların neden test yazmanın nedenini daha fazla ele aldığı görülüyor. Birim testler yerine fonksiyonel testler yazmanın daha iyi bir yaklaşım olup olmadığını tartışmak istiyorum.
Yggdrasil

okuduğumda, çift sorudaki cevaplar öncelikle birim dışı testlerin daha mantıklı geldiği zamanlar hakkındadır
gnat

Bu ilk bağlantının kendisi bir kopyasıdır. Yani demek istediğin: programmers.stackexchange.com/questions/66480/…
Robbie Dee

Robbie Dee'nin bağlantısından gelen cevaplar, neden test edilmediği konusunda daha da fazla.
Yggdrasil

Yanıtlar:


37

Portakalları ve elmaları karşılaştırıyor.

Entegrasyon testleri, kabul testleri, birim testleri, davranış testleri - hepsi test ve hepsi kodunuzu geliştirmenize yardımcı olacak, ancak aynı zamanda oldukça farklı.

Bence farklı testlerin her birini inceleyeceğim ve umarım neden hepsinin bir karışımına ihtiyaç duyduğunuzu açıklayacağım:

Entegrasyon testleri:

Basitçe, sisteminizin farklı bileşen parçalarının doğru bir şekilde bütünleştiğini test edin - örneğin - bir web hizmeti isteğini simüle edip sonucun geri geldiğini kontrol edin. Sürekli olarak doğrulanabilmesi için genellikle gerçek (ish) statik verileri ve alaylı bağımlılıkları kullanırdım.

Kabul testleri:

Bir kabul testi doğrudan bir işletme kullanım durumu ile ilişkilendirilmelidir. Çok büyük ("işlemler doğru bir şekilde sunulur") veya küçük ("bir listeyi başarılı bir şekilde filtreler") olabilir - önemli değil; Önemli olan, açıkça belirli bir kullanıcı gereksinimine bağlı olması gerektiğidir. Test odaklı geliştirme için bunlara odaklanmayı seviyorum çünkü bu, dev ve qa'nın doğrulaması için kullanıcı öykülerinde yapılan testlerin iyi bir referans kılavuzuna sahip olduğumuz anlamına geliyor.

Birim testleri:

Bireysel bir kullanıcı hikayesini kendi başına yapan veya yapamayan küçük işlevsellik birimleri için - örneğin, belirli bir web sayfasına girdiğimizde tüm müşterileri aldığımızı söyleyen bir kullanıcı hikayesi bir kabul testi olabilir (interneti vurmak benzetimini yapabilir) sayfa ve yanıtı kontrol etme) aynı zamanda birkaç birim testi de içerebilir (güvenlik izinlerinin kontrol edildiğini doğrulayın, veritabanı bağlantısının doğru sorgulandığını doğrulayın, sonuçların sayısını sınırlayan herhangi bir kodun doğru şekilde yapıldığını doğrulayın) - hepsi "birim testleri" dir Bu tam bir kabul testi değil.

Davranış testleri:

Belirli bir giriş durumunda akışın bir uygulamada olması gerektiğini tanımlayın. Örneğin, "bağlantı kurulamadığında, sistemin bağlantıyı yeniden denediğini doğrulayın." Yine, bunun tam bir kabul testi olması muhtemel değildir, ancak yine de faydalı bir şeyi doğrulamanıza izin verir.

Bunların hepsi benim görüşüme göre yazma testleri konusunda çok tecrübeli; Ders kitabı yaklaşımlarına odaklanmayı sevmem - bunun yerine testlerinize değer veren şeylere odaklanın.


Tanımınızda, demek istediğim, birim testinden daha fazla davranış testi (?) Yazmak demek. Benim için birim testi tüm bağımlılıkları alay ile tek bir sınıfı test eden bir testtir. Birim testlerinin en yararlı olduğu durumlar vardır. Örneğin, karmaşık bir algoritma yazdığımda. O zaman algoritmanın beklenen çıktısı ile birçok örneğim var. Bunu birim seviyesinde test etmek istiyorum çünkü bu aslında davranış testinden daha hızlı. Testin değerini, sınıf boyunca sadece tam bir yolu olan ve bir davranış testi ile kolayca test edilebilen ünite düzeyinde bir sınıf görmüyorum.
Yggdrasil

14
Şahsen kabul testlerinin en önemli olduğunu düşünüyorum, iletişim, güvenilirlik ve hata durumları gibi şeyleri test ederken davranış testleri önemlidir ve küçük karmaşık özellikleri test ederken birim testleri önemlidir (algoritmalar buna iyi bir örnek olabilir)
Michael

Terminolojiniz konusunda o kadar da sağlam değilim. Bir programlama paketi programlıyoruz. Orada grafik editöründen ben sorumluyum. Testlerim düzenleyiciyi, paketin geri kalanından alay edilmiş hizmetler ve alay arayüzü kullanıcı arayüzü ile test ediyor. Bu ne tür bir test olur?
Yggdrasil

1
Ne test ettiğinize bağlı olarak değişir - işletme özelliklerini mi test ediyorsunuz (kabul testleri)? Entegrasyonu test ediyor musunuz (entegrasyon testleri)? Bir düğmeye tıkladığınızda ne olacağını test ediyor musunuz (davranış testleri)? Algoritmaları test ediyor musunuz (birim testleri)?
Michael

4
“Ders kitabı yaklaşımlarına odaklanmayı sevmiyorum - test sınavlarına değer veren şeye odaklanın” Oh, çok doğru! Her zaman sormanız gereken ilk soru "bunu yaparak ne problemi çözüyorum?". Ve farklı projelerin çözmek için farklı problemleri olabilir!
Laurent Bourgault-Roy

40

TL; DR: İhtiyaçlarınızı karşıladığı sürece, evet.

Uzun yıllardır Kabul Testine Dayalı Gelişim (ATDD) geliştirmesini yapıyorum. Çok başarılı olabilir. Dikkat edilmesi gereken birkaç şey var.

  • Birim testleri gerçekten, IOC'nin uygulanmasına yardımcı olmaktadır. Ünite testleri olmadan onus, iyi yazılmış kodun gerekliliklerini yerine getirdiklerinden emin olmak için geliştiricilere açıktır (ünite testleri iyi yazılmış kod kullandığı sürece)
  • Genellikle alay edilen kaynakları kullanıyorsanız, daha yavaş olabilirler ve yanlış hataları olabilirler.
  • Test, birim testlerinde olduğu gibi belirli bir sorunu tespit etmiyor. Test hatalarını düzeltmek için daha fazla araştırma yapmanız gerekir.

Şimdi faydaları

  • Çok daha iyi test kapsamı, entegrasyon noktalarını kapsar.
  • Sistemin bir bütün olarak yazılım geliştirmenin bütün noktası olan kabul kriterlerini karşılamasını sağlar.
  • Büyük refaktörleri çok daha kolay, daha hızlı ve daha ucuz hale getirir.

Her zaman olduğu gibi, analizi yapmak ve bu uygulamanın sizin durumunuza uygun olup olmadığını anlamak size bağlıdır. Birçok insanın aksine idealize edilmiş doğru bir cevap olduğunu sanmıyorum. İhtiyaçlarınıza ve gereksinimlerinize bağlı olacaktır.


8
Mükemmel nokta Test etme konusunda küçük bir yer tutucusu olmak ve uçan renklerle “geçtiğinde” sıcak bir memnuniyet ışıltısı almak için yüzlerce vaka yazmak çok kolaydır. Basitçe söylemek gerekirse: Yazılımınız KULLANICI bakış açısından yapması gerekeni yapmazsa, ilk ve en önemli testi geçemezsiniz.
Robbie Dee

Belirli bir sorunu tespit etmek için iyi bir nokta. Büyük bir gereksinim varsa, tüm sistemi test eden kabul testleri yazarım ve gereksinimi elde etmek için sistemin belirli bileşenlerinin alt görevlerini test eden testler yazarım. Bununla çoğu zaman kusurun bulunduğu bileşeni tespit edebilirim.
Yggdrasil

2
"Birim testleri IOC'yi uygulamada yardımcı olur"? IoC yerine DI demek istediğine eminim ama yine de neden birisi DI kullanımını zorlamak istesin ki ? Şahsen, pratikte DI'nin nesnelere (prosedür tarzı programlama) yol açtığını gördüm.
Rogério

Yalnızca entegrasyon testi yapmanın argümanına karşı BOTH entegrasyonu ve birim testi yapmanın (IMO en iyi) seçeneğine girişinizi verebilir misiniz? Buradaki cevabınız iyi, ama bu şeyleri karşılıklı olduklarını sanıyordum, ki öyle olduklarını sanmıyorum.
starmandeluxe

@starmandeluxe Gerçekten de birbirini dışlayan değiller. Aksine, testten elde etmek istediğiniz değerin bir sorusudur. Birim testlerini yazma değerinin geliştirme / destek maliyetini aştığı her yerde birim test ederdim. ex. Bileşik faiz fonksiyonunu kesinlikle mali bir uygulamada test ederim.
dietbuddha

18

Testlerin / gereksinimlerin programın tasarımını geliştirmesine izin vermek için TDD benzeri bir yaklaşım kullandım. Sorun şu ki, geliştirme süresinin yarısından fazlasına yazma / refactor testleri gelince

Birim testleri, kullanıldıkları bileşenlerin genel arayüzü çok sık değişmediğinde en iyi sonucu verir. Bu, bileşenler zaten iyi tasarlandığında (örneğin, SOLID ilkelerini izleyerek) anlamına gelir.

Dolayısıyla iyi bir tasarıma inanmak, bir bileşendeki birçok birim testini "atmaktan" sadece "evrimleştiğini" görmek yanlıştır. TDD iyi tasarım için bir "öğretmen" değildir, sadece tasarımın belirli yönlerinin iyi olduğunu doğrulamak için biraz yardımcı olabilir (özellikle test edilebilirlik).

Gereksinimleriniz değiştiğinde ve bir bileşenin içindekileri değiştirmeniz gerektiğinde ve bu birim testlerinizin% 90'ını kıracak, bu nedenle onları çok sık sık sıkmanız gerekecek, o zaman tasarım muhtemelen çok iyi değildi.

Bu yüzden benim tavsiyem: oluşturduğunuz bileşenlerin tasarımını ve açık / kapalı prensibini izleyerek bunları nasıl daha iyi hale getirebileceğinizi düşünün. İkincisi, bileşenlerin işlevselliğinin daha sonra değiştirilmeden genişletilebilmesini sağlamak (ve böylece birim testleriniz tarafından kullanılan bileşenin API'sini kırmamaktır). Bu tür bileşenler birim test testleri tarafından kapsanabilir (ve içermelidir) ve deneyim sizin tanımladığınız kadar acı verici olmamalıdır.

Hemen böyle bir tasarım bulamazsanız, kabul ve entegrasyon testleri gerçekten daha iyi bir başlangıç ​​olabilir.

EDIT: Bazen bileşenlerin tasarımı iyi olabilir, ancak birim testlerinin tasarımı sorunlara neden olabilir . Basit bir örnek: X sınıfının "MyMethod" yöntemini test etmek ve yazmak istiyorsunuz

    var x= new X();
    Assert.AreEqual("expected value 1" x.MyMethod("value 1"));
    Assert.AreEqual("expected value 2" x.MyMethod("value 2"));
    // ...
    Assert.AreEqual("expected value 500" x.MyMethod("value 500"));

(değerlerin bir tür anlamı olduğunu varsayalım).

Dahası, üretim kodunda sadece bir çağrı olduğunu varsayalım X.MyMethod. Şimdi, yeni bir gereksinim için "MyMethod" yöntemi context, ihmal edilemeyecek ek bir parametreye (örneğin, gibi bir şey ) ihtiyaç duyuyor . Birim testleri olmadan, bir arama kodunu tek bir yerde yeniden düzenlemek zorunda kalır. Birim testlerinde, 500 yere yeniden yerleştirmek zorundadır.

Fakat buradaki sebep ünite kendini test etmiyor, “X.MyMethod” ile aynı çağrının tekrar tekrar tekrarlanması, “Kendinizi Tekrar Etmeme (KURUYMA) prensibine kesinlikle uymamak değil. Burada test verilerini ve ilgili beklenen değerleri bir listeye koymak ve çağrıları bir döngü içinde "MyMethod" 'a (ya da test aracı "veri sürücü testleri" olarak adlandırdıysa, bu özelliği kullanmak için) çalıştırın. Birimde değiştirilecek yerlerin sayısı, yöntem imzası 1 olarak değiştiğinde (500'ün aksine) test eder.

Gerçek dünya durumunuzda, durum daha karmaşık olabilir, ancak umarım fikir edinirsiniz - ünite testleriniz değişime tabi olup olmayacağını bilmediğiniz bir bileşen API kullanıyorsa, sayıyı düşürdüğünüzden emin olun Bu API’ya minimum çağrı yapılması.


"Bu bileşenler zaten iyi tasarlanmış oluşmayacağı anlamına gelmektedir.": Sana katılıyorum ama kod yazmadan önce testler yazarsanız nasıl bileşenleri zaten dizayn edilebilir ve kod olan tasarım? En azından TDD'yi anladım.
Giorgio

2
@ Giorgio: aslında, testleri önce mi yoksa sonra mı yazmanızın bir önemi yoktur. Tasarım, bir bileşenin sorumluluğu, halka açık arabirim, bağımlılıklar (doğrudan veya enjekte edilen), çalışma zamanı veya derleme zamanı davranışı, değişkenlik, isimler, veri akışı, kontrol akışı, katmanlar vb. Hakkında karar vermek demektir. tasarım aynı zamanda bazı kararları mümkün olan en son noktaya ertelemek demektir. Birim testi, tasarımınızın iyi olup olmadığını dolaylı olarak gösterebilir: gereksinimler değiştikten sonra birçoğunu yeniden yansıtmak zorunda kalırsanız, muhtemelen değildi.
Doktor Brown

@Giorgio: bir örnek açıklığa kavuşturabilir: "MyMethod" yöntemi ve 2 parametresi olan bir X bileşenine sahip olduğunuzu söyleyin. TDD kullanarak X x= new X(); AssertTrue(x.MyMethod(12,"abc")), yöntemi gerçekten uygulamadan önce yazabilirsiniz . Ön tasarımı kullanarak, class X{ public bool MyMethod(int p, string q){/*...*/}}önce yazabilir, sonra da testleri yazabilirsiniz. Her iki durumda da aynı tasarım kararını verdiniz. Karar iyi ya da kötü ise, TDD size söylemeyecektir.
Doc Brown

1
Size katılıyorum: TDD'nin otomatik olarak iyi tasarım üreteceği varsayımıyla kör bir şekilde uygulandığını gördüğümde biraz şüpheliyim. Ayrıca, bazen tasarım henüz net değilse TDD yoluna girer: Yaptığım şeye genel bir bakış atmadan önce detayları test etmek zorundayım. Eğer doğru anlarsam, aynı fikirdeyiz. (1) birim testinin bir tasarımın doğrulanmasına yardımcı olduğunu, ancak tasarımın ayrı bir faaliyet olduğunu ve (2) TDD'nin her zaman en iyi çözüm olmadığını düşünüyorum çünkü testler yazmaya başlamadan önce fikirlerinizi düzenlemelisiniz ve TDD sizi yavaşlatabilir. bu.
Giorgio

1
Kısacası, birim testleri bir bileşenin iç tasarımındaki kusurları gösterebilir. Arabirim, öncesi ve sonrası koşullar önceden bilinmelidir, aksi halde birim testi oluşturamazsınız. Bu yüzden, bileşenin tasarımı, bileşenin yapması gereken, ünite testi yapılmadan önce gerçekleştirilmelidir. Bunu nasıl yapar - alt seviye tasarım, ayrıntılı tasarım veya iç tasarım veya ne demek istersen - birim testi yazıldıktan sonra gerçekleşebilir.
Maarten Bodewes,

9

Evet, tabi ki öyle.

Bunu düşün:

  • Birim testi, küçük bir kod parçasını uygulayan küçük, hedefli bir test parçasıdır. İyi bir kod kapsamı elde etmek için bunlardan birçoğunu yazarsınız, böylece tümü (veya garip bitlerin çoğunluğu) test edilir.
  • Bir entegrasyon testi, kodunuzun geniş bir yüzeyini uygulayan büyük, geniş bir test parçasıdır. İyi bir kod kapsamı elde etmek için bunlardan çok az yazarsınız, böylece tümü (veya garip bitlerin çoğunluğu) test edilir.

Genel farkı görün ....

Sorun, kod kapsamı ile ilgilidir, eğer tümleştirme / kabul testini kullanarak tüm kodunuzu tam olarak test edebiliyorsanız, o zaman bir sorun yoktur. Kodunuz test edildi. Hedef bu.

TDD tabanlı bir projenin bütün birimlerin gerçekten iyi bir şekilde çalışmasını sağlamak için bazı entegrasyon testlerine ihtiyaç duyacağı için bunları karıştırmanız gerekebileceğini düşünüyorum (% 100 başarılı bir ünite tarafından test edilen kod tabanının mutlaka çalışmamasını tecrübe ediyorum. hepsini bir araya getirince!)

Sorun gerçekten test etme, arızaları ayıklama ve düzeltmeyi kolaylaştırıyor. Bazı insanlar birim testlerinin bu konuda çok iyi olduğunu düşünüyorlar, küçük ve basitler ve arızaların görülmesi kolay, ancak dezavantajı, birim test araçlarına uyacak şekilde kodunuzu yeniden düzenlemek ve çoğunu yazmak zorunda olmanız. Bir entegrasyon testinin bir çok kodu kapsayacak şekilde yazması daha zordur ve muhtemelen herhangi bir hatayı ayıklamak için günlüğe kaydetme gibi teknikleri kullanmak zorunda kalacaksınız (yine de bunu yapmak zorundasınız diyebilirim, test hatalarını bir araya getiremezsiniz) ne zaman yerinde!).

Her halükarda, yine de test edilmiş bir kod alıyorsunuz, sadece hangi mekanizmanın size daha uygun olduğuna karar vermeniz gerekiyor. (Bir karışımla devam ederdim, karmaşık algoritmaları test eder ve kalanını test eder).


7
Tam olarak doğru değil ... Entegrasyon testlerinde, her ikisi de alıcı olan iki bileşene sahip olmak mümkündür, ancak entegrasyon testinde hataları iptal edilir. Son kullanıcı, bu bileşenlerden sadece birinin kullanıldığı şekilde kullanana kadar önemli değil ...
Michael Shaw

1
Kod kapsamı! = Test edildi - birbirlerini iptal eden hataların dışında, hiç düşünmediğiniz senaryolardan ne haber? Entegrasyon testi, mutlu yol testi için iyidir, ancak işler iyi gitmediğinde, yeterli entegrasyon testini nadiren görürüm.
Michael

4
@Ptolemy Birbirini iptal eden 2 buggy bileşeninin nadirliğinin, birbiriyle etkileşen 2 çalışan bileşenden çok daha düşük olduğunu düşünüyorum.
gbjbaanb

2
@Michael o zaman teste yeterince çaba göstermediniz, testlerin çok daha ayrıntılı olması gerektiğinden iyi entegrasyon testi yapmanın daha zor olduğunu söyledim. Bir ünite testinde olabildiğince kolay bir entegrasyon testinde hatalı veri sağlayabilirsiniz. Entegrasyon testi! = Mutlu yol Yapabildiğiniz kadar kod kullanmakla ilgili, bu yüzden size kodunuzun ne kadarının kullanıldığını gösteren kod kapsamı araçları var.
gbjbaanb

1
@Michael Cucumber veya SpecFlow gibi araçları doğru kullandığımda, istisnaları ve zor durumları da test eden entegrasyon testleri oluşturabilirim. Ancak bir sınıfın çok permütasyona sahip olup olmadığına katılıyorum, bu sınıf için birim sınavı yazmayı tercih ediyorum. Ancak bu, yalnızca avuç yollara sahip sınıflara sahip olmaktan daha az sıklıkta olacaktır.
Yggdrasil

2

Bence korkunç bir fikir.

Kabul testleri ve entegrasyon testi, belirli bir hedef test etmek için kod geniş kısımlarını dokunmak olduklarından, ihtiyacımız olacak daha , zamanla az üstlenmeden. Daha da kötüsü, kodun geniş bölümlerini kapsadığı için, arama yapmak için daha geniş bir alana sahip olduğunuzdan, kök nedenini izlemek için harcadığınız zamanı artırırlar.

Hayır, genellikle% 90 UI olan garip bir uygulamanız veya ünite testine garip olan başka bir şeyiniz yoksa genellikle daha fazla ünite testi yazmalısınız. Karşılaştığınız acı birim testlerinden değil, ilk gelişim testinde. Genellikle, zamanınızın sadece 1 / 3'ünü çoğu yazma sınavında geçirmelisiniz. Sonuçta, onlar size hizmet etmek için oradalar, tam tersi değil.


2
TDD'ye karşı duyduğum ana sığır eti doğal gelişim akışını bozuyor ve savunma programlamasını baştan başlatıyor. Bir programcı zaten zaman baskısı altındaysa, sadece kodu kesip daha sonra cilalamak isteyeceklerdir. Elbette, buggy koduyla keyfi bir son tarihle buluşmak yanlış ekonomidir.
Robbie Dee

2
Nitekim, özellikle "daha sonra cilala" olarak hiçbir zaman gerçekleşmemiş gibi görünüyor - bir geliştiricinin "dışarıya çıkması gerekiyor, daha sonra yapacağız" diye yaptığı her incelemede, hepimizin ne zaman olacağını bilmeden, bunun olmayacağını - teknik Borç = Bence iflas geliştiriciler.
Michael

3
Cevap bana mantıklı geliyor, neden bu kadar çok eksi olduğunu bilmiyorum. Mike Cohn'dan alıntı yapmak için: "Ünite testi sağlam bir test otomasyon stratejisinin temeli olmalı ve piramidin en büyük bölümünü temsil etmelidir . Otomatik ünite testleri harikadır çünkü bir programlayıcıya belirli veriler verirler - bir hata vardır ve satır 47 " mountaingoatsoftware.com/blog/…
guillaume31

4
@ guillaume31 Sırf bir adam bir zamanlar onların iyi olduklarını söylediği için, onların iyi olduğu anlamına gelmez. Tecrübelerime göre hatalar ünite testleri tarafından tespit edilmedi, çünkü öndeki yeni gereksinime değiştirildiler. Ayrıca çoğu hata entegrasyon hatalarıdır. Bunun için entegrasyon testlerimle çoğunu tespit ediyorum.
Yggdrasil

2
@ Yggdrasil Martin Fowler’a şunu da söyleyebilirim: "Yüksek seviye testinde bir başarısızlık yaşarsanız, sadece işlevsel kodunuzda bir hata yaşamanız değil, aynı zamanda eksik bir birim testiniz de vardır". martinfowler.com/bliki/TestPyramid.html Neyse, eğer tek başına entegrasyon testleri sizin için çalışıyorsa, o zaman para cezası. Tecrübelerime göre, ihtiyaç duyulduğunda, daha yavaştırlar, ünite testlerinden daha az kesin hata mesajı verir ve daha az manevra kabiliyeti (daha fazla kombinasyon) sunarlar. Ayrıca, entegrasyon testleri yazarken geleceği daha az kanıtlama eğilimindeyim - bir nesnenin doğruluğu yerine önceden (yanlış?) Tasarlanmış senaryoları düşünerek.
guillaume31

2

TDD ile "kazan", testlerin bir kez yazıldığı zaman otomatikleştirilebilmesidir. Kapak tarafı, geliştirme süresinin önemli bir bölümünü tüketebilmesidir. Bunun gerçekte tüm süreci yavaşlatıp yavaşlatmadığı tartışmalıdır. Ön testin geliştirme döngüsü sonunda düzeltilecek hata sayısını azalttığı argümanı.

BDD'nin davranışların birim testine dahil edilebildiği yer burasıdır, bu nedenle işlem tanım gereği daha az soyut ve daha somuttur.

Açıkça, eğer sınırsız bir süre mevcut olsaydı, mümkün olduğu kadar çok çeşitli çeşit testleri yapardınız. Bununla birlikte, zaman genellikle sınırlıdır ve sürekli test, yalnızca bir nokta için uygun maliyetlidir.

Tüm bunlar, en fazla değeri sağlayan testlerin işlemin önünde olması gerektiği sonucuna varmaktadır. Bu kendi başına bir testi diğerine göre otomatik olarak desteklemiyor - daha çok her durumun yararına olması gerekiyor.

Kişisel kullanım için bir komut satırı widget'ı yazıyorsanız, öncelikle birim testleriyle ilgilenirsiniz. Bununla birlikte, bir web servisi, önemli miktarda entegrasyon / davranış testi gerektirdiğini söylese de.

Çoğu test türü "yarış çizgisi" olarak adlandırılabilecek şeye odaklanırken, yani bugün işletme tarafından gerekli olanı test ederken, ünite testi, daha sonraki geliştirme aşamalarında yüzeye çıkacak ince böcekleri ayıklamakta mükemmeldir. Bu kolayca ölçülemeyen bir avantaj olduğundan, genellikle göz ardı edilir.


1
Testlerimi önceden yazıyorum ve hataların çoğunu kapsayacak kadar test yapıyorum. Sonradan ortaya çıkan böceklere gelince. Bu bana bir gereksinimin değiştiğini veya yeni bir gereksinimin ortaya çıktığını söylüyor. Entegrasyon / davranış testlerinden sonra değiştirilmesi gerekiyor. Eski bir gereksinimde bir hata gösteriliyorsa, bunun için yaptığım test bunu gösterecektir. Otomasyon gelince. bütün sınavlarım her zaman devam eder.
Yggdrasil

Son paragrafta düşündüğüm örnek, bir kütüphanenin yalnızca tek bir uygulama tarafından kullanıldığı, ancak bunun genel amaçlı bir kütüphane haline getirilmesi için bir iş gereksinimi olduğu. Bu durumda, kütüphaneye eklediğiniz her sistem için yeni entegrasyon / davranış testleri yazmak yerine, en azından bazı ünite testleri yaptırmanız daha iyi hizmet verebilir.
Robbie Dee

2
Otomatikleştirme testi ve ünite testi tamamen dikeydir. Kendine saygılı herhangi bir proje otomatik entegrasyon ve işlevsel testlere sahip olacaktır. Verilen, genellikle manuel birim testlerini görmüyorsunuz, ancak bunlar mevcut olabilir (temelde manuel birim testi, belirli bir işlevsellik için bir test aracıdır).
Jan Hudec

Gerçekten de. Bir süredir gelişme alanı dışında kalan otomatik 3. parti araçları için gelişen bir pazar var.
Robbie Dee

1

Birim testlerinin son avantajı, daha hızlı olmalarıdır. Neredeyse ünite testleri kadar hızlı olabileceklerini bilmek için yeterince entegrasyon testi yazdım.

Bu kilit nokta ve sadece "son avantaj" değil. Proje büyüdükçe, entegrasyon kabul testleriniz yavaşlıyor ve yavaşlıyor. Ve burada, o kadar yavaş demek istiyorum ki, onları çalıştırmayı bırakacaksınız.

Tabii ki, birim testleri de yavaşlıyor, ancak yine de daha hızlı büyüklük sırasından daha fazlası. Örneğin, önceki projemde (c ++, yaklaşık 600 kLOC, 4000 ünite testi ve 200 entegrasyon testi), entegrasyon testlerini yürütmek için 15 dakikadan daha uzun bir süre geçti. Değişen parçanın birim testlerini yapmak ve uygulamak, ortalama 30 saniyeden daha az zaman alacaktır. Çok hızlı bir şekilde yapabiliyorsanız, her zaman yapmak istersiniz.

Açıklığa kavuşturmak için: Entegrasyon ve kabul testleri eklememeyi söylemiyorum ama TDD / BDD'yi yanlış bir şekilde yaptınız.

Birim testi de tasarım için iyidir.

Evet, test edilebilirliği göz önünde bulundurarak tasarım yapmak tasarımı daha iyi hale getirecektir.

Sorun yazma / refactor testleri için geliştirme süresinin yarısından fazlasının olmasıdır. Sonuçta daha fazla özellik uygulamak istemedim çünkü yeniden test edip birçok teste yazmak zorunda kalacağım.

Gereksinimler değiştiğinde, kodu değiştirmeniz gerekir. Birim testleri yazmazsan işini bitirmediğini söylerdim. Ancak bu, ünite testleriyle% 100 kapsama almanız gerektiği anlamına gelmez - amaç bu değildir. Bazı şeylerin (GUI gibi, veya bir dosyaya erişen, ...) ünite testinden geçirilmediği bile.

Bunun sonucu daha iyi kod kalitesi ve başka bir test katmanıdır. Buna değer diyebilirim.


Ayrıca birkaç 1000 kabul testimiz vardı ve hepsini uygulamak bütün haftayı alacaktır.


1
Benim örneğime baktın mı? Bu her zaman oldu. Mesele şu ki, yeni bir özellik uyguladığımda ünite testini değiştiriyorum / ekliyorum, böylece yeni özelliği test edecekler - bu nedenle ünite testi yapılamayacak. Çoğu durumda, birim testlerinde tespit edilmeyen değişikliklerin yan etkileri var - çünkü çevre alay ediyor. Tecrübelerime göre, bu yüzden hiçbir ünite testi, mevcut bir özelliği bozmadığımı söyledi. Bana her zaman hatalarımı gösteren entegrasyon ve kabul testleri oldu.
Yggdrasil

Yürütme zamanı gelince. Büyüyen bir uygulama ile çoğunlukla artan sayıda izole edilmiş bileşene sahibim. Değilse yanlış bir şey yapmadım. Yeni bir özellik uyguladığımda, yalnızca sınırlı sayıda bileşende oluyor. Tüm başvuru kapsamında bir ya da daha fazla kabul testi yazıyorum - ki bu yavaş olabilir. Ek olarak aynı testleri bileşenlerin bakış açısından da yazıyorum - bu testler hızlı, çünkü bileşenler genellikle hızlı. Bileşen testlerini her zaman yapabilirim, çünkü yeterince hızlılar.
Yggdrasil

@ Yggdrasil Dediğim gibi, birim testlerinin hepsi güçlü değildir, ancak en hızlı oldukları için genellikle ilk test katmanıdır. Diğer testler de faydalıdır ve birleştirilmelidir.
BЈовић

1
Sadece daha hızlı olduklarından, bunun için kullanılması gerektiği veya bunları yazmanın yaygın olduğu anlamına gelmez. Dediğim gibi, birim testlerim bozulmuyor - bu yüzden benim için hiçbir değeri yok.
Yggdrasil

1
Asıl soru, kırılmadıkları zaman birim testinden ne gibi değerlere sahibim? Onları her zaman yeni gereksinimlere göre ayarlamam gerektiğinde neden yazmakta sorun mu yaşıyorsunuz? Onlardan gördüğüm tek değer algoritmalar ve yüksek permütasyonlu diğer sınıflar için. Ancak bunlar bileşen ve kabul testlerinden daha az.
Yggdrasil
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.