Depo desenli TDD


10

Yeni projemde TDD ile denemeye karar verdim. Ve başlangıçta bir sorunla karşılaştım. Uygulamamda yapmak istediğim ilk şey, veri kaynağından veri okuma yeteneği vermektir. Bu amaçla depo desenini kullanmak istiyorum. Ve şimdi:

  • Test, veri havuzu arayüzünün gerçek uygulaması içinse, veritabanına erişimi olan sınıfı test edeceğim ve bundan kaçınmam gerektiğini biliyorum.
  • Test, veri havuzu modelinin gerçek uygulaması için değilse, iyi test edeceğim ... sadece sahte. Bu birim testlerde test edilen herhangi bir üretim kodu olmayacaktır.

Bunu iki günden beri düşünüyorum ve hala makul bir çözüm bulamıyorum. Ne yapmalıyım?

Yanıtlar:


11

Bir havuzun yaptığı şey, alan adınızdan NHibernate veya Doctrine gibi DAL çerçevenize veya SQL yürütme sınıflarınıza dönüştürmektir. Bu, deponuzun görevlerini yerine getirmek için söz konusu çerçevedeki yöntemleri çağıracağı anlamına gelir: deponuz, verileri almak için gereken sorguları oluşturur. Bir ORM çerçevesi kullanmıyorsanız (umarım sizsiniz ...), depo ham SQL deyimlerinin oluşturulduğu yerdir.

Bu yöntemlerden en temel olanı kaydetmektir: çoğu durumda bu, nesneyi depodan iş birimine (veya oturuma) geçirir.

public void Save(Car car)
{
    session.Save(car);
}

Ancak başka bir örneğe bakalım, örneğin bir arabayı kimliğine göre getirme. Gibi görünebilir

public function GetCarWithId(String id)
{
    return Session.QueryOver<Car>()
                    .Where(x => x.Id == id)
                    .SingleOrDefault();
}

Hala çok karmaşık değil, ancak birden fazla koşulla hayal edebiliyorum (2010'dan sonra 'Volkswagen' grubundaki tüm markalar için yapılan tüm arabaları al) bu zorlaşıyor. Yani gerçek TDD tarzında bunu test etmeniz gerekiyor. Bunu yapmanın birkaç yolu vardır.

Seçenek 1: ORM çerçevesine yapılan çağrıları alay et

Elbette, Oturum nesnesini alay edebilir ve doğru çağrıların yapıldığını iddia edebilirsiniz. Bu, depoyu test ederken, gerçekte test odaklı değildir, çünkü sadece deponun dahili olarak istediğiniz şekilde göründüğünü test ediyorsunuz. Test temelde 'kod böyle görünmelidir' der. Yine de, geçerli bir yaklaşımdır, ancak bu tür testlerin değeri çok azdır.

Seçenek 2: (Yeniden) testlerden veritabanı oluşturmak

Bazı DAL çerçeveleri, etki alanını tablolarla eşleştirmek için oluşturduğunuz eşleme dosyalarına dayalı olarak veritabanının tüm yapısını oluşturma olanağı sağlar. Bu çerçeveler için depoları test etmenin yolu genellikle testin ilk adımında bir bellek içi veritabanıyla veritabanı oluşturmak ve DAL çerçevesini kullanarak bellek içi veritabanına nesne eklemektir. Bundan sonra, yöntemlerin işe yarayıp yaramadığını sınamak için bellek içi veritabanındaki havuzu kullanabilirsiniz. Bu testler daha yavaş, ancak çok geçerlidir ve testlerinizi yürütür. DAL çerçevenizden biraz işbirliği gerektiriyor.

3. Seçenek: Gerçek bir veritabanında test etme

Başka bir yaklaşım, gerçek bir veritabanını test etmek ve unittest'i izole etmektir. Bunu birkaç şekilde yapabilirsiniz: testlerinizi bir işlemle kuşatın, manuel olarak temizleyin (bakımı çok zor değildir), her adımdan sonra veritabanını tamamen yeniden oluşturun ... Uygulamaya bağlı olarak bu, inşa edebilir veya olabilir mümkün değil. Uygulamalarımda tamamen kaynak kontrolünden bir yerel geliştirme veritabanı oluşturabilirim ve depolardaki birim testlerim testleri birbirinden tamamen izole etmek için işlemleri kullanır (açık işlem, veri ekleme, test deposu, geri alma işlemi). Her derleme önce yerel geliştirme veritabanını kurar ve ardından bu yerel geliştirme veritabanındaki havuzlar için işlemden izole birim testleri gerçekleştirir. O'

DAL'ı test etme

NHibernate gibi bir DAL çerçevesi kullanıyorsanız, bu çerçeveyi test etme gereğinden kaçının. Her şeyin yolunda olduğundan emin olmak için bir etki alanı nesnesini kaydederek, alarak ve karşılaştırarak eşleme dosyalarınızı test edebilirsiniz (her türlü önbelleği devre dışı bıraktığınızdan emin olun), ancak yazmanız gereken diğer testlerin çoğu kadar gerekli değildir. Bunu çoğunlukla çocuklarla ilgili koşulları olan ebeveynler üzerindeki koleksiyonlar için yapmaya eğilimliyim.

Depolarınızın dönüşünü test ederken, etki alanı nesnenizdeki bazı tanımlayıcı özelliklerin eşleşip eşleşmediğini kontrol edebilirsiniz. Bu bir id olabilir, ancak testlerde insan tarafından okunabilir bir özelliği kontrol etmek genellikle daha yararlıdır. 'Bana 2010'dan sonra yapılan tüm arabaları getir ....' de bu sadece beş arabanın iade edildiğini ve plakaların 'buraya liste ekle' olduğunu kontrol edebilir. Ek yarar, sizi sıralama hakkında düşünmeye zorlaması ve testiniz otomatik olarak sıralamayı zorlamasıdır. Kaç uygulama birden çok kez sıralanır (veritabanından sıralanır, bir görüntüleme nesnesi oluşturmadan önce sıralanır ve ardından görünüm nesnesi, her ihtimale karşı aynı mülkte sıralanır ) veya depo türlerini dolaylı olarak varsayar ve yanlışlıkla kaldırırsınız. bu, kullanıcı arayüzünü kırarak yol boyunca ilerliyordu.

'Birim testi' sadece bir isim

Bence, birim testleri çoğunlukla veritabanına çarpmamalıdır. Bir kaynaktan veri gerektiren her kod parçasının bunu bir havuzla yapması ve bu havuzun bağımlılık olarak enjekte edilmesi için bir uygulama oluşturursunuz. Bu kolay alay ve istediğiniz tüm TDD iyiliğini sağlar. Ama sonunda depolarınızın görevlerini yerine getirdiğinden emin olmak istiyorsunuz ve bunu yapmanın en kolay yolu bir veritabanına çarparsa, öyle olsun. Uzun süredir 'birim testler veritabanına dokunmamalıdır' fikrini bıraktım ve bunu yapmak için çok gerçek nedenler olduğunu öğrendim. Ancak bunu otomatik ve tekrar tekrar yapabiliyorsanız. Ve böyle bir teste 'birim testi' veya 'entegrasyon testi' adını verdiğimiz hava tartışmalıdır.


3
Birim testleri ve entegrasyon testlerinin farklı amaçları vardır. Bu testlerin isimleri sadece dekoratif değildir; onlar da açıklayıcı.
Robert Harvey

9
  1. Önemsiz veya açık veri havuzu yöntemlerini test etmeyin.

    Yöntemler önemsiz CRUD işlemleri ise, gerçekten test ettiğiniz tek şey parametrelerin doğru eşlenip eşlenmediğidir. Entegrasyon testleriniz varsa, bu tür hatalar hemen görünür hale gelecektir.

    Bu, aşağıdaki gibi önemsiz özellikler için geçerli olan aynı prensiptir:

    public property SomeProperty
    {
        get { return _someProperty; }
        set { _someProperty = value; }
    }
    

    Test etmiyorsunuz, çünkü test edilecek hiçbir şey yok. Mülkte doğrulanması gereken doğrulama veya başka bir mantık yok.

  2. Hala bu yöntemleri test etmek istiyorsanız ...

    Alaylar bunu yapmanın yoludur. Unutmayın, bunlar Birim Testler. Veritabanını birim testleriyle test etmezsiniz; Entegrasyon Testleri bunun içindir.

Daha Fazla Bilgi
Full Stack, Bölüm 3: TDD kullanarak bir Havuz Oluşturma (yaklaşık 16 dakika içinde izlemeye başlayın).


3
Tabii, bunu anlıyorum. Yine de, bu TDD yaklaşımı varsa, ben önce bu kod için testler yoksa herhangi bir kod yazmamalısınız, değil mi?
Thaven

1
@Thaven - youtube'da "tdd ölü mü?" Başlıklı bir dizi video var. Onları izle. Bir çok ilginç noktaya değiniyorlar, bunlardan biri, uygulamanızın her düzeyinde TDD'nin uygulanmasının mutlaka en iyi fikir olmadığı fikri. "Başarısız testi olmayan kod" çok aşırı bir konum, sonuçlardan biridir.
Jules

2
@Jules: tl; dw nedir?
Robert Harvey

1
@RobertHarvey Özetlemek zordur, ancak en önemli nokta TDD'ye her zaman uyulması gereken bir din olarak davranmanın bir hata olmasıdır. Bunu kullanma seçimi bir değişimin bir parçasıdır ve (1) bazı problemler olmadan daha hızlı çalışabileceğinizi ve (2) sizi ihtiyacınız olandan daha karmaşık bir çözüme doğru itebileceğini, özellikle kendinizi çok fazla sahte kullanarak bulursanız.
Jules

1
1. nokta için +1. Testler yanlış olabilir, sadece genellikle önemsiz oldukları için. Doğruluğu testlerden daha belirgin olan bir işlevi test etmek anlamsızdır. % 100 kod kapsamı elde etmek, programın her olası çalışmasını test etmeye yakın bir yere götürmek gibi değildir, bu nedenle test çabalarını nerede harcadığınız konusunda akıllı olabilirsiniz.
Doval
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.