BDD ve dışarıdan yaklaşım, test ile nasıl başlanır

Herşey,

Tüm dış TDD ve BDD şeylerini anlamaya çalışıyorum ve bunu elde etmeme yardım etmenizi istiyor.

Aşağıdaki gibi çalışan Config Parameters işlevselliğini uygulamam gerektiğini varsayalım:

  • dosyada ve veritabanında parametreler var
  • her iki grup da bir parametreye ayarlanmış olmalıdır
  • Veritabanından gelen parametreler, dosyalardan gelenleri geçersiz kılar

Şimdi bunu dışarıdan yaklaşımla uygulamak istiyorum ve başlangıçta sıkıştım. Umarım gitmeme yardım edebilirsin. Benim sorularım:

Hangi testi ile başlamalıyım? Ben sadece aşağıdaki gibi sth var:

class ConfigurationAssemblerTest {

    @Test
    public void itShouldResultWithEmptyConfigurationWhenBothSourcesAreEmpty() {
        ConfigurationAssembler assembler = new ConfigurationAssembler();            
       //what to put here ?
        Configuration config = assembler.getConfiguration();            
        assertTrue(config.isEmpty());
    }

}

Bağımlılıkların ne ile biteceğimi henüz bilmiyorum. Henüz o şeyleri nasıl yazacağımı bilmiyorum. Bu testi geçerli hale getirmek için ne yapmalıyım? Bir şeyle dalga geçmeli miyim? Eğer öyleyse bu bağımlılıkları nasıl tanımlarsınız?

Bana bununla yolunu gösterebilirseniz, bir plan yazın, bazı testler iskeletler, ne yapmalı ve hangi sırada süper serin olabilir. Çok fazla yazı olduğunu biliyorum, belki beni herhangi bir kaynağa yönlendirebilirsin? Bulduğum dışarıdan yaklaşımla ilgili tüm kaynaklar bağımlılık vb. Olmayan basit vakalarla ilgiliydi.

Ve alaycılık yaklaşımına iki soru.

  • Eğer alay etkileşim ve doğrulama ile ilgili ise, bu tür testlerde devlet iddialarının olmaması gerektiği anlamına gelir (sadece sahte doğrulamalar)?
  • Henüz test için sahte olmayan bir şeyi değiştirirsek, daha sonra gerçek sürümle değiştirir miyiz?

Şimdiden teşekkürler.

1

1 cevap

Tamam, bu gerçekten çok fazla şey. Sondan başlayalım:

  • Mocking is not only about 'interactions and their verification', this would be only one half of the story. In fact, you're using it in two different ways:

    1. Checking, if a certain call was made, and eventually also checking the arguments of the call (this is the 'interactions and verification' part).

    2. Using mocks to replace dependencies of the class-under-test (CUT), eventually setting up return values on the mock objects as required. Here, you use mock objects to isolate the CUT from the rest of the system (so that you can handle the CUT as an isolated 'unit', which sort of runs in a sandbox).

İlk form dinamik veya 'etkileşim tabanlı' birim testini çağırırdım, Mocking framework çağrı doğrulama yöntemlerini kullanır. İkincisi, bir gerçeği öne süren daha geleneksel, 'statik' birim testidir.

  • 'Henüz var olmayan bir şeyin yerine geçme' gereksinimine sahip olmamalısınız (bunun mantıksal olarak görüldüğü gibi - tamamen imkansız olması dışında). Bunu yapmanız gerektiğini düşünüyorsanız, bu, ilk adımdan önce ikinci adımı yapmaya çalıştığınızın açık bir göstergesidir.

  • 'Dışarıdan yaklaşma' anlayışınız ile ilgili olarak: Dürüst olmak gerekirse, bunu daha önce hiç duymadım, bu yüzden çok belirgin bir kavram gibi görünmüyor - ve kesinlikle çok yararlı bir şey değil Çünkü, onları açıklığa kavuşturmaktan daha fazlasını karıştırıyor gibi görünüyor (en azından şimdilik).

Şimdi ilk sorunuzun üzerine: ( Hangi testle başlamalıyım? ):

  1. First things first - you need some mechanism to read the configuration values from file and database, and this functionality should be encapsulated in separate helper classes (you need, among other things, a clean Separation of concerns for effectively doing TDD - this usually is totally underemphasized when introducing TDD/BDD). I'd suggest an interface (e.g. IConfigurationReader) which has two implementations (one for the file stuff and one for the database, e.g. FileConfigurationReader and DatabaseConfigurationReader). In TDD (not necessarily with a BDD approach) you would also have corresponding test fixtures. These fixtures would cover test cases like 'What happens if the underlying data store contains no/invalid/valid/other special values?'. This is what I'd advice you to start with.

  2. Only then - with the reading mechanism in operation and your ConfigurationAssembler class having the necessary dependencies - you would start to write tests for/implement the ConfigurationAssembler class. Your test then could look like this (Because I'm a C#/.NET guy, I don't know the appropriate Java tools. So I'm using pseudo-code here):

    class ConfigurationAssemblerTest {

    @Test
    public void itShouldResultWithEmptyConfigurationWhenBothSourcesAreEmpty() {
    
        IConfigurationReader fileConfigMock = new [Mock of FileConfigurationReader];
        fileConfigMock.[WhenAskedForConfigValues].[ReturnEmpty];
    
        IConfigurationReader dbConfigMock = new [Mock of DatabaseConfigurationReader];
        dbConfigMock.[WhenAskedForConfigValues].[ReturnEmpty];
    
        ConfigurationAssembler assembler = new ConfigurationAssembler(fileConfigMock, dbConfigMock);            
    
        Configuration config = assembler.getConfiguration();            
    
        assertTrue(config.isEmpty());
    }
    

    }

Burada iki şey önemlidir:

  • İki okuyucu nesnesi ConfigurationAssembler öğesine yapıcısı aracılığıyla dışarıdan enjekte edilir - bu teknik Bağımlılık Enjeksiyonu . Genel olarak daha iyi ve daha temiz bir mimariye yol açan (ve özellikle sahte nesneleri kullanırken büyük ölçüde birim testine yardımcı olan) çok yararlı ve önemli mimari ilkedir.

  • Şimdi test, tam olarak ne ifade ettiğini belirtir: ConfigurationAssembler , parçalarındaki temel okuma mekanizmaları boş bir sonuç kümesini döndürdüğünde boş bir yapılandırmayı döndürür ('toplar'). Ve yapılandırma değerlerini sağlamak için sahte nesneler kullandığımız için, test tamamıyla çalışır. ConfigurationAssembler sınıfının (yani boş değerlerin işlenmesi) ve yalnızca başka bir işlevinin doğru çalışmasını test ettiğimizden emin olabiliriz.

Oh, ve belki de BDD yerine TDD ile başlamanız daha kolay çünkü BDD sadece bir TDD alt kümesidir ve TDD kavramlarının üzerine inşa edilir. Böylece, TDD'yi bildiğiniz zaman BDD'yi etkili bir şekilde yapabilirsiniz (ve anlayabilirsiniz).

HTH!

1
katma