Test Odaklı Geliştirme: Dosya sistemi işlemlerini test etmenin iyi / kabul gören bir yolu var mı?


14

Şu anda bir dosya sisteminin içeriğine dayalı bir tablo (diğer şeylerin yanı sıra) üreten bir proje üzerinde çalışıyorum ve sırayla bulduğu şeyler üzerinde bazı meta veri değişiklikleri yapar. Soru şudur: Testler bunun etrafında nasıl yazılmalı veya oluşturulmalıdır? Bunu yapmanın kolay bir yolu var mı? Yoksa bir "korumalı alan" oluşturmalı mıyım?

Yanıtlar:


13

TDD'de her zaman dış kaynaklarla yaptığınız gibi: dosya sistemi işlemleriniz için bir veya daha fazla arabirim oluşturur ve "bunları alay eder". Dosya sistemi işlemlerinin kendisini değil, "tablo oluşturucunuzu" ve meta veri değiştirme kodunuzu test etmek istiyorsunuz (büyük olasılıkla dosya sistemine erişmek için hazır kütüphane uygulamalarını kullanıyorsunuz).


TDD, test edilen ünitenin uygulanmasının alay edilmesini önermez. Bkz. (E, g) solnic.eu/2014/05/22/mocking-and-ruby.html
soru

1
@soru: Bu cevabın önerdiği şey bu değil. Önce arayüzler oluşturulmasını, ardından arayüzün alay edilmesini önerir . Böylece iş mantığını test edersiniz, ancak dosya sistemi arayüzünü test etmezsiniz.
sleske

5
Ancak iş mantığının dosyalar ve dizinler olarak tanımlandığı anlaşılıyor. Dosya sistemi API'sini çağırır şeyler Yani olduğunu ihtiyaçlarını test gibi şeyler. İlgili herhangi bir dosya dışı iş mantığını test etmek için alay gerektirmez; sadece test edin.
soru

@soru doğru, böylece dosya ve klasörlerin etrafında, etki alanına özgü tüm işlemlerin istemci tarafında olacağı ve uygulama tarafının birim sınaması olmadan çalışacağından emin olacak kadar önemsiz bir arayüzle ince bir katman oluşturursunuz (entegrasyon testleri hala gerekli). UI kodunda bir Mütevazi İletişim Kutusu fikrine benzer veya kalıcı nesneler üzerinde çalışan kodda sahte bir Havuz kullanma.
Jules

2
Bu yüzden etkili bir şekilde dosya sistemi, veritabanı vb. İle etkileşime giren gerçek sınıfı test etmekten istifa ediyoruz ... bunun yerine, sahte / saplama ile aynı arayüzle farklı bir uygulama yaratırız, ancak herhangi bir birim testi olmadan ayrıldığımız gerçek sınıfı, çünkü bunu birim test edemeyeceğimize inanıyoruz ve bunun yerine test etmek için entegrasyon testi yapmamız gerekiyor. Bu doğru mu?
Andrew Savinykh

11

"Test" dosya sistemine sahip olmanın nesi yanlış?

İşlemlerinizi test etmek için yeterli içeriğe sahip bir şablon klasörü / dizin yapısı oluşturun.

Ünite testinizin kurulumu sırasında bu ilk yapıyı kopyalayın (şablonu ZIP olarak eklemenizi ve test alanınıza çıkartmanızı önerir). Testlerinizi yapın. Yırtma sırasında her şeyi silin.

Mocking ile ilgili sorun öncelikle projenize ait dosya sistemleri, işletim sistemleri ve veritabanlarının gerçekten dış kaynak olarak nitelendirilmemesi ve ikinci olarak düşük seviyeli sistem çağrılarının alay edilmesinin hem zaman alıcı hem de hataya yatkın olmasıdır.


5
Dosya sistemi işlemlerini alay etmek, gerçek bir dosya sistemi kullanmaktan çok (!) Daha hızlı çalışan testler yaratacaktır ve bu daha "hata eğilimli" ise tartışmalı ise, uygulamaya bağlı olduğunu söyleyebilirim. Bununla birlikte, önerinizin otomatik entegrasyon testleri oluşturmak için iyi olduğunu düşünüyorum (genellikle TDD yapmadığımda ilk yapacağım). Ancak OP özellikle TDD istedi ve TDD birim testleri hızlı olmalı.
Doc Brown

1
Bence dosya sistemleri, alay edilirse, ideal olarak bir grup tarafından yazılmış ve korunan bütün bir API'ye sahip olmalıdır, çünkü dosya sistemi ile önemli bir şey yaparsanız tekerleği yeniden keşfediyorsunuz.
Frank Hileman

2
@Doc Brown - Taklit etmek için acı veren kenar vakaları olan tip işlemleri yapmak, dir ve silmek ve yeniden adlandırmak istediğini varsayıyorum. Ayrıca modern donanımda unzipping a Bir küçük dosya bir dizine sadece bir Java sınıfı yüklemekten biraz daha yavaş - sonuçta tüm IO.
James Anderson

Test dosya sistemi hakkında ne kadar çok düşünürsem o kadar çok hoşuma gider.
Frank Hileman

3

Gerçek dünya dosya sistemleri her türlü garip davranışa sahip olduğundan, bu kesinlikle entegrasyon testine ihtiyacınız olan tür bir şeydir (silme de dahil olmak üzere herhangi bir işlem açıksa Windows'un bir dosyayı silmeye izin vermemesi gibi).

Bu yüzden TDD yaklaşımı önce entegrasyon testini yazmaktır (TDD, kesinlikle konuşursak, 'birim test' ve 'entegrasyon testi' gibi farklı kavramlara sahip değildir; bunlar sadece testlerdir). Büyük olasılıkla bu yeterli olacaktır; böylece işi, durak, eve gitmek .

Değilse, dosyaları düzenleyerek yeterince sınanması kolay olmayan bir iç karmaşıklık olacaktır. Bu durumda, bu karmaşıklığı çıkarın, bir sınıfa koyun ve o sınıf için birim testleri yazın . Büyük olasılıkla bu ortak sınıfın veritabanı, xml dosyası vb. Durumlarda da kullanılabilir olduğunu göreceksiniz.

Hiçbir durumda, yazdığınız kodun temel çekirdeğini almaz ve test edilen ünitenin yanlış olup olmadığını geçecek testleri yazmak için 'taklit edemezsiniz'.


Bu cevap gerçekten benim için bir perspektife koydu - 'unit test' and 'integration test'; they are just tests.bence gerçekçi, bu benim durumum için en iyi çözüm olacak - kenar durumlarda kullandığım dosya sistemi kitaplıklarını ve uygulamanın nasıl yanıt vermesi gerektiğini gerçekten test etmem gerekiyor şunlar. Farklı bir dosya sistemi kitaplığına geçersem, bir grup sahte / test kodunu yeni kitaplıkla çalışmak için yeniden yazmak zorunda kalmam, ancak bir test klasörü yapısına ve entegrasyon testlerine sahip olmak çok daha kolay olur.
tehDorf

2

Sorunuzu "Dosya sistemi işlemlerine bağlı bir sınıfı test etmenin iyi / kabul gören bir yolu" olarak anlıyorum. İşletim sisteminizin dosya sistemini test etmek istediğinizi düşünmüyorum.

@Doc Brown yanıtı olabildiğince küçük olarak önerilen 'dosya sistemi işlemlerinizle arayüzler oluşturmak ve "onları alay etmek" için çaba sarf etmek için java ikili akışları veya metin okuyucu (veya c # veya eşdeğeri) kullanmak iyi bir fikirdir. tdd tarafından geliştirilen sınıfta dosya adlarına sahip Dosyaları doğrudan kullanmak yerine ) .

Misal:

Java kullanarak bir sınıf CsvReader uyguladık

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

Test için böyle bellek verilerinde kullandım

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

veya test verilerini kaynaklara dahil edin

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

Üretimde dosya sistemini kullanıyorum

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

Bu şekilde CsvReader'ım dosya sistemine değil, dosya sistemi için bir uygulamanın olduğu bir soyutlama "Okuyucu" ne bağlıdır.


2
Buradaki tek sorun OP'nin dosya işlemlerinden değil, dosya sistemi işlemlerinden ve meta veri işlemlerinden bahsetmesiydi - sanırım bir dizindeki tüm dosyaları listelemek, tüm resim dosyalarındaki bazı EXIF ​​bilgilerini güncellemek gibi bir şey demekti.
Doc Brown

Doğru.
Kirbinator

1
String [] List (String dizini) yöntemine sahip IDirectoryLister oluşturabilirsiniz; FakeDirectoryLister, yeni String [] {".", "..", "foo.bat", "bar.exe"} döndürerek bu yöntemi uygulayabilir;
Anders Lindén

0

Dosya sistemi işlemleri için bir sarıcı oluşturun. Testlerde, sarıcı ile aynı arayüzü uygulayan bir sahte alay edin. Üretimde, sargıyı geçirin.

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.