Depo yöntemlerini test etmek için neden birim testlere ihtiyacım var?


19

Bu soru üzerine biraz şeytan savunucusu oynamam gerekiyor çünkü deneyim eksikliği yüzünden iyi savunamıyorum. İşte anlaşma, kavramsal olarak birim test ve entegrasyon testi arasındaki farkları alıyorum . Özellikle kalıcılık yöntemlerine ve depoya odaklanırken, birim testi, aranan bir siparişin beklendiği gibi iade edildiğini iddia etmek için muhtemelen Moq gibi bir çerçeve aracılığıyla bir sahte kullanır.

Aşağıdaki birim testini yaptığımı varsayalım:

[TestMethod]
public void GetOrderByIDTest()
{
   //Uses Moq for dependency for getting order to make sure 
   //ID I set up in 'Arrange' is same one returned to test in 'Assertion'
}

Bu yüzden ben OrderIdExpected = 5kurarsam ve sahte nesnem 5kimlik olarak geri dönerse testim geçer. Anladım. Ben birim test emin Ya benim kod preform döner beklenen nesne ve kimliği ve başka değil bir şey yapmak için kodu.

Ben alacağım argüman şudur:

"Neden sadece birim testleri atlamak ve entegrasyon testleri yapmak? Bu veritabanı saklı yordamı ve kodunuzu birlikte test önemli. Bu sonuçta veritabanı çağırır bilmek bilmek istiyorum, birim testleri ve entegrasyon testleri için çok fazladan fazla iş gibi görünüyor Testlerin daha uzun sürdüğünü biliyorum, ama ne olursa olsun çalıştırılmalı ve test edilmelidir, bu yüzden her ikisine de sahip olmak bana anlamsız geliyor.

Bunu bir ders kitabı tanımı ile savunabilirim: "Eh, bu bir entegrasyon testi ve kodu bir birim test olarak ayrı ayrı test etmemiz gerekiyor, yada, yada, yada ..." Bu, uygulamaların saf bir açıklamasının olduğu bir durum vs gerçeklik kaybediyor. Bazen bununla karşılaşıyorum ve sonuçta dış bağımlılıklara dayanan birim test kodunun ardındaki mantığı savunamıyorsam, bunun için bir dava açamıyorum.

Bu sorudaki herhangi bir yardım büyük beğeni topluyor, teşekkürler!


2
Ben doğrudan kullanıcı test göndermek göndermek ... onlar nasıl olsa gereksinimleri değiştirmek olacak ...
nathan hayfield

Zaman zaman ışık tutmak için alay için +1
atconway

2
Basit yanıt, her yöntemin x sayıda kenar vakası olabileceğidir (diyelim ki pozitif kimlikleri, 0 kimliğini ve negatif kimlikleri test etmek istiyorsunuz). Kendisinin 3 kenar vakası olan bu yöntemi kullanan bazı işlevleri test etmek isterseniz, her kenar vakası kombinasyonunu test etmek için 9 test vakası yazmanız gerekir. Onları izole ederek, sadece 6 yazmanız gerekir. Buna ek olarak, testler size bir şeyin neden kırıldığı hakkında daha spesifik bir fikir verir. Belki de deponuz hata durumunda null döndürür ve null istisnası koddan birkaç yüz satır aşağı atılır.
Rob

Bir "birim" testi tanımınız konusunda çok katı olduğunuzu düşünüyorum. Havuz sınıfı için "iş birimi" nedir?
Caleb

Ve bunu göz önünde bulundurduğunuzdan emin olun: birim testiniz test etmeye çalıştığınız her şeyi atarsa, gerçekten neyi test ediyorsunuz?
Caleb

Yanıtlar:


20

Birim testleri ve entegrasyon testlerinin farklı amaçları vardır.

Birim testleri , kodunuzun işlevselliğini doğrular ... çağırdığınızda yöntemden ne beklediğinizi alırsınız. Entegrasyon testleri, kodun bir sistem olarak bir araya getirildiğinde nasıl davrandığını test eder . Birim testlerinin sistem davranışını değerlendirmesini veya entegrasyon testlerinin belirli bir yöntemin belirli çıktılarını doğrulamasını beklemezsiniz.

Birim testleri, doğru yapıldığında entegrasyon testlerinden daha kolaydır. Yalnızca entegrasyon testlerine güveniyorsanız, testiniz:

  1. Genel olarak yazmak daha zor olmalı,
  2. Gerekli tüm bağımlılıklar nedeniyle daha kırılgan olun ve
  3. Daha az kod kapsamı sunun.

Alt satır: Nesneler arasındaki bağlantıların düzgün çalıştığını doğrulamak için entegrasyon testini kullanın, ancak işlevsel gereksinimleri doğrulamak için önce birim testine yaslanın.


Tüm bunlar, belirli depo yöntemleri için birim testine ihtiyacınız olmayabilir. Birim testleri önemsiz yöntemlerle yapılmamalıdır ; tüm yaptığınız bir nesne için ORM tarafından üretilen koda bir istek iletmek ve bir sonuç döndürmek, çoğu durumda, birim test etmek gerekmez; bir entegrasyon testi yeterlidir.


Evet, hızlı yanıt için teşekkür ederim. Yanıt hakkındaki tek eleştirim, son paragrafımın endişesine düşüyor. Muhalefetim hala soyut açıklamaları ve tanımları duyacak, daha derin bir akıl yürütmeyecek. Örneğin, saklı yordamı / DB'yi kodumla ilgili olarak sınama durumum için uyguladığım gerekçeler verebilir misiniz ve birim sınamaları bu özel kullanım durumuna göre neden hala değerlidir ?
Ocak'ta atconway

1
SP yalnızca veritabanından bir sonuç döndürüyorsa, bir tümleştirme testi yeterli olabilir. Önemsiz bir mantığı varsa, birim testleri belirtilir. Ayrıca bkz. Stackoverflow.com/questions/1126614/… ve msdn.microsoft.com/en-us/library/aa833169(v=vs.100).aspx (SQL Server'a özgü).
Robert Harvey

12

Ben pragmatistler tarafındayım. Kodunuzu iki kez test etmeyin.

Yalnızca depolarımız için entegrasyon testleri yazıyoruz. Bu sınamalar yalnızca bellek içi veritabanında çalıştırılan basit bir sınama kurulumuna bağlıdır. Bir birim testin yaptığı her şeyi ve daha fazlasını sağlıyorlar.

  1. TDD yaparken birim testleri yerine kullanılabilirler. Gerçek kodla başlamadan önce yazmak için biraz daha test kodlu kazan plakası olsa da, her şey yerinde olduğunda kırmızı / yeşil / refactor yaklaşımıyla çok iyi çalışır.
  2. Deponun gerçek kodunu test ederler - SQL dizelerinde veya ORM komutlarında bulunan kod. Sorgunun doğru olduğunu doğrulamak, bir StatementExecutor öğesine gerçekten bir dize gönderdiğinizi doğrulamaktan daha önemlidir.
  3. Regresyon testleri olarak mükemmeldirler. Başarısız olursa, her zaman hesaplanmamış şemadaki bir değişiklik gibi gerçek bir sorundan kaynaklanır.
  4. Veritabanı şemasını değiştirirken vazgeçilmezdirler. Şemayı, test geçtiği sürece uygulamanızı bozacak şekilde değiştirmediğinizden emin olabilirsiniz. (Bu durumda birim testi işe yaramaz, çünkü saklı yordam artık mevcut olmadığında, birim testi yine de geçer.)

Gerçekten çok pragmatik. Ben biraz farklı ORM nedeniyle, bellek içi veritabanı aslında (performans açısından değil) aslında gerçek veritabanımdan farklı davrandığını yaşadım. Entegrasyon testlerinizde buna dikkat edin.
Marcel

1
@Marcel, bununla karşılaştım. Bazen tüm testlerimi gerçek bir veritabanında çalıştırarak çözdüm.
Winston Ewert

4

Birim testleri, entegrasyon testlerinin (tasarım gereği) yapamayacağı bir modülerlik düzeyi sağlar. Bir sistem refactored veya recomposed, (ve bu zaman olacaktır gerçekleşmesi) entegrasyon testleri çoğunlukla yeniden yazılmış olmalı oysa birim testler genellikle, yeniden kullanılabilir. Birim testinde olması gereken bir şeyin işini yapmaya çalışan entegrasyon testleri genellikle çok fazla şey yapıyor ve bu da onların bakımını zorlaştırıyor.

Ayrıca, birim testini dahil etmenin aşağıdaki faydaları vardır:

  1. Birim testleri, başarısız bir entegrasyon testini (muhtemelen bir regresyon hatasından dolayı) hızla ayrıştırmanıza ve nedenini belirlemenize olanak tanır. Dahası, bu problemi diyagrama veya diğer belgelere göre daha hızlı bir şekilde tüm ekibe iletecektir.
  2. Birim testleri, kodunuzla birlikte örnekler ve belgeler ( gerçekten derlenen bir belge türü ) olarak kullanılabilir. Diğer belgelerin aksine, güncelliğini yitirdiğinde anında bileceksiniz.
  3. Birim testleri, daha büyük performans sorunlarını ayrıştırmaya çalışırken temel performans göstergeleri olarak kullanılabilirken, entegrasyon testleri sorunu bulmak için çok sayıda enstrümantasyon gerektirir.

Hem Birim hem de Entegrasyon testlerini kullanırken çalışmanızı bölmek (ve bir KURU yaklaşımını uygulamak) mümkündür. Küçük işlevsellik birimleri için birim testlerine güvenin ve bir entegrasyon testinde birim testinde olan herhangi bir mantığı tekrarlamayın. Bu genellikle daha az çalışmaya (ve dolayısıyla daha az yeniden çalışmaya) yol açar.


4

Testler kırıldıklarında faydalıdır: Proaktif veya Yeniden Aktif.

Birim Testleri proaktiftir ve Entegrasyon Testleri aşamalı / sahte verilerde reaktifken sürekli işlevsel bir doğrulama olabilir.

Söz konusu sistem hesaplama mantığından çok verilere yakınsa / veriye bağımlıysa, Entegrasyon Testleri daha fazla önem kazanmalıdır.

Örneğin, bir ETL sistemi inşa edersek, en alakalı testler verilerin etrafında olacaktır (aşamalı, sahte veya canlı). Aynı sistem bazı Birim Testlerine sahip olacak, ancak sadece doğrulama, filtreleme vb.

Havuz deseninde hesaplama veya iş mantığı olmamalıdır. Veritabanına çok yakın. Ancak depo, onu kullanan iş mantığına da yakındır. Yani bu bir DENGE'ye çarpma meselesidir.

Birim Testleri Deponun NASIL davranacağını test edebilir. Entegrasyon Testleri, depo çağrıldığında GERÇEKTEN NE OLDUĞUNU test edebilir.

Şimdi, "GERÇEKTEN NE OLDU?" Çok cazip gelebilir. Ancak bu, sürekli ve tekrarlı olarak çalışmak için çok pahalı olabilir. Kırılganlık testlerinin klasik tanımı burada geçerlidir.

Çoğu zaman, depoyu kullanan bir nesneye Birim testi yazmayı yeterince iyi buluyorum. Bu şekilde uygun havuz yönteminin çağrılıp çağrılmadığını ve uygun Mocked sonuçlarının döndürülüp döndürülmediğini test ederiz.


Şunu beğendim: "Şimdi," GERÇEKTEN NE OLDU? "Çok cazip gelebilir. Ama bu sürekli ve tekrarlı çalışmak için çok pahalı olabilir."
atconway

2

Test edilmesi gereken 3 ayrı şey vardır: saklı yordam, saklı yordamı çağıran kod (yani depo sınıfınız) ve tüketici. Deponun işi bir sorgu oluşturmak ve döndürülen veri kümesini bir etki alanı nesnesine dönüştürmektir. Sorgunun gerçek yürütülmesinden ve veri kümesinin oluşturulmasından ayrı olarak birim testini destekleyecek yeterli kod vardır.

Yani (bu çok basitleştirilmiş bir örnek):

interface IOrderRepository
{
    Order GetOrderByID(Guid id);
}

class OrderRepository : IOrderRepository
{
    private readonly ISqlExecutor sqlExecutor;
    public OrderRepository(ISqlExecutor sqlExecutor)
    {
        this.sqlExecutor = sqlExecutor;
    }

    public Order GetOrderByID(Guid id)
    {
        var sql = "SELECT blah, blah FROM Order WHERE OrderId = @p0";
        var dataset = this.sqlExecutor.Execute(sql, p0 = id);
        var result = this.orderFromDataset(dataset);
        return result;
    }
}

Daha sonra test ederken OrderRepository, alaycı bir şekilde geçin ISqlExecutorve test edilen nesnenin doğru SQL'de geçtiğini kontrol edin (bu onun işi) ve Orderbazı sonuç veri kümesi (ayrıca alaylı) verildiğinde uygun bir nesne döndürür . Beton SqlExecutorsınıfını test etmenin tek yolu , yeterince adil entegrasyon testleri ile olmakla birlikte, bu ince bir sargı sınıfıdır ve nadiren değişecek, çok büyük bir anlaşma.

Saklı yordamlarınızı da birim test etmeniz gerekir.


0

Bunu çok basit bir düşünce şekline indirgeyebilirim: Birim testlerini tercih edin çünkü hataları bulmaya yardımcı olur. Ve bunu tutarlı bir şekilde yapın çünkü tutarsızlıklar karışıklığa neden olur.

Diğer nedenler, testler için de geçerli oldukları için OO gelişimini yönlendiren aynı kurallardan kaynaklanmaktadır. Örneğin, tek sorumluluk ilkesi.

Bazı birim testleri yapmaya değmeyecek gibi görünüyorsa, belki de konunun gerçekten sahip olmaya değmediğinin bir işaretidir. Ya da belki de işlevselliği muadillerinden daha soyuttur ve bunun için testler (ve kodu) daha yüksek bir seviyeye çıkarılabilir.

Her şeyde olduğu gibi, istisnalar vardır. Ve programlama hala bir sanat biçimidir, bu yüzden birçok problem her birini en iyi yaklaşım için değerlendirmeyi gerektirecek kadar farklıdır.

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.