C # ve RhinoMocks Kullanarak Test Odaklı Geliştirme İçin En İyi Uygulamalar [kapalı]


87

Ekibimin test edilebilir kod yazmasına yardımcı olmak için, C # kod tabanımızı daha test edilebilir hale getirmek için en iyi uygulamaların bu basit listesini oluşturdum. (Bazı noktalar, C # için bir alay çerçevesi olan Rhino Mocks'ın sınırlamalarına atıfta bulunur, ancak kurallar daha genel olarak da geçerli olabilir.) İzlediği en iyi uygulamaları olan var mı?

Kodun test edilebilirliğini en üst düzeye çıkarmak için şu kuralları izleyin:

  1. Önce testi, ardından kodu yazın. Sebep: Bu, test edilebilir kod yazmanızı ve her kod satırının kendisi için yazılmış testleri almasını sağlar.

  2. Bağımlılık ekleme kullanarak sınıfları tasarlayın. Sebep: Görülemeyenlerle dalga geçemez veya test edemezsiniz.

  3. Model-View-Controller veya Model-View-Presenter kullanarak UI kodunu davranışından ayırın. Sebep: Test edilemeyen parçalar (UI) en aza indirilirken iş mantığının test edilmesini sağlar.

  4. Statik yöntemler veya sınıflar yazmayın. Sebep: Statik yöntemleri izole etmek zor veya imkansızdır ve Rhino Mocks onlarla dalga geçemez.

  5. Arayüzleri programlayın, sınıfları değil. Sebep: Arayüzlerin kullanılması, nesneler arasındaki ilişkileri netleştirir. Bir arayüz, bir nesnenin ortamından ihtiyaç duyduğu bir hizmeti tanımlamalıdır. Ayrıca, arayüzler Rhino Mocks ve diğer alay etme çerçeveleri kullanılarak kolayca alay edilebilir.

  6. Dış bağımlılıkları izole edin. Neden: Çözümlenmemiş dış bağımlılıklar test edilemez.

  7. Alay etmeyi düşündüğünüz yöntemleri sanal olarak işaretleyin. Nedeni: Rhino Mocks, sanal olmayan yöntemlerle dalga geçemez.


Bu kullanışlı bir listedir. Şu anda NUnit ve Rhino.Mocks kullanıyoruz ve birim testinin bu tarafına daha az aşina olan ekip üyeleri için bu kriterleri açıklamakta fayda var.
Chris Ballard

Yanıtlar:


58

Kesinlikle iyi bir liste. İşte bununla ilgili birkaç düşünce:

Önce testi, ardından kodu yazın.

Yüksek düzeyde katılıyorum. Ancak, daha spesifik olacağım: "Önce bir test yazın, ardından testi geçmek için yeterli kodu yazın ve tekrarlayın." Aksi takdirde, birim testlerimin daha çok entegrasyon veya kabul testleri gibi görüneceğinden korkarım.

Bağımlılık ekleme kullanarak sınıfları tasarlayın.

Kabul. Bir nesne kendi bağımlılıklarını yarattığında, onlar üzerinde hiçbir kontrolünüz yoktur. Kontrol / Bağımlılık Enjeksiyonunun Ters Çevrilmesi, test edilen nesneyi taklitler / saplamalar / vb. İle izole etmenize olanak tanıyan bu kontrolü size verir. Bu, nesneleri ayrı ayrı test etme şeklidir.

Model-View-Controller veya Model-View-Presenter kullanarak UI kodunu davranışından ayırın.

Kabul. Sunum yapanın / denetleyicinin bile çizgili / alaylı bir görünüm ve model vererek DI / IoC kullanılarak test edilebileceğini unutmayın. Check Sunucu İlk bu konuda daha fazla bilgi için TDD.

Statik yöntemler veya sınıflar yazmayın.

Buna katılıyorum emin değilim. Statik bir yöntemi / sınıfı, taklitler kullanmadan birim test etmek mümkündür. Belki de bu bahsettiğiniz Rhino Mock'a özgü kurallardan biridir.

Arayüzleri programlayın, sınıfları değil.

Katılıyorum, ancak biraz farklı bir nedenden dolayı. Arayüzler, yazılım geliştiricisine, sadece çeşitli sahte nesne çerçevelerini desteklemenin ötesinde, büyük bir esneklik sağlar. Örneğin, DI'yi arayüzler olmadan düzgün şekilde desteklemek mümkün değildir.

Dış bağımlılıkları izole edin.

Kabul. Dış bağımlılıkları bir arayüzle kendi cephenizin veya adaptörünüzün (uygun şekilde) arkasına gizleyin. Bu, yazılımınızı bir web hizmeti, bir kuyruk, bir veritabanı veya başka bir şey gibi harici bağımlılıktan ayırmanıza olanak tanır. Bu özellikle ekibiniz bağımlılığı (yani harici) kontrol etmediğinde önemlidir.

Alay etmeyi düşündüğünüz yöntemleri sanal olarak işaretleyin.

Bu Rhino Mocks'ın bir sınırlamasıdır. El ile kodlanmış saplamaları sahte bir nesne çerçevesine tercih eden bir ortamda, bu gerekli değildir.

Ve dikkate alınması gereken birkaç yeni nokta:

Yaratıcı tasarım kalıplarını kullanın.Bu, DI'ye yardımcı olacaktır, ancak aynı zamanda bu kodu izole etmenize ve diğer mantıktan bağımsız olarak test etmenize de izin verir.

Bill Wake's Arrange / Act / Assert tekniğini kullanarak testler yazın . Bu teknik, hangi konfigürasyonun gerekli olduğunu, gerçekte neyin test edildiğini ve neyin beklendiğini çok netleştirir.

Kendi taklitlerinizi / taslaklarınızı yuvarlamaktan korkmayın. Çoğu zaman, sahte nesne çerçevelerini kullanmanın testlerinizi okumayı inanılmaz derecede zorlaştırdığını göreceksiniz. Kendinizinkini yuvarlayarak, taklitleriniz / taslaklarınız üzerinde tam kontrole sahip olacaksınız ve testlerinizi okunaklı tutabileceksiniz. (Önceki noktaya geri dönün.)

Birim testlerinizin çoğaltılmasını soyut temel sınıflara veya kurulum / sökme yöntemlerine yeniden düzenleme eğiliminden kaçının.Bunu yapmak, yapılandırma / temizleme kodunu geliştiriciden birim testini karıştırmaya çalışırken gizler. Bu durumda, her bir testin netliği, tekrarlamayı yeniden düzenlemekten daha önemlidir.

Sürekli Entegrasyonu uygulayın. Kodunuzu her "yeşil çubukta" kontrol edin. Yazılımınızı oluşturun ve her girişte tüm birim testlerinizi çalıştırın. (Elbette, bu kendi başına bir kodlama uygulaması değildir; ancak yazılımınızı temiz ve tamamen entegre tutmak için harika bir araçtır.)


3
Genelde bir testin okunması zorsa, bunun çerçevenin değil, test ettiği kodun hatası olduğunu düşünüyorum. SUT kurulumu karmaşıksa, belki daha fazla konsepte bölünmelidir.
Steve Freeman

10

.Net 3.5 ile çalışıyorsanız, Moq alaycı kitaplığına bakmak isteyebilirsiniz - diğer alaycı kitaplıkların çoğunun sezgisel olmayan kayıt-yanıt deyimini kaldırmak için ifade ağaçları ve lambdalar kullanır.

Test senaryolarınızın ne kadar sezgisel hale geldiğini görmek için bu hızlı başlangıca göz atın , işte basit bir örnek:

// ShouldExpectMethodCallWithVariable
int value = 5;
var mock = new Mock<IFoo>();

mock.Expect(x => x.Duplicate(value)).Returns(() => value * 2);

Assert.AreEqual(value * 2, mock.Object.Duplicate(value));

5
Rhino Mocks'ın yeni versiyonunun da böyle çalıştığını düşünüyorum
George Mauer


3

Bu çok faydalı bir gönderi!

Bağlamı ve Test Edilen Sistemi (SUT) anlamanın her zaman önemli olduğunu ekleyeceğim. Mevcut kodun aynı prensipleri takip ettiği bir ortamda yeni kod yazarken TDD prensiplerini harfiyen takip etmek çok daha kolaydır. Ancak TDD olmayan eski bir ortamda yeni kod yazarken, TDD çabalarınızın tahminlerinizin ve beklentilerinizin çok ötesine hızla yükselebileceğini görürsünüz.

Tamamen akademik bir dünyada yaşayan bazılarınız için zaman çizelgeleri ve teslimat önemli olmayabilir, ancak yazılımın para olduğu bir ortamda, TDD çabanızı etkili bir şekilde kullanmak kritik önem taşır.

TDD, Marjinal Getiriyi Azaltma Yasasına büyük ölçüde tabidir . Kısacası, TDD'ye yönelik çabalarınız, bir maksimum getiri noktasına ulaşana kadar giderek daha değerli hale geliyor, bundan sonra TDD'ye daha sonra harcanan zaman gittikçe daha az değere sahip oluyor.

TDD'nin birincil değerinin sınırda (kara kutu) ve sistemin görev açısından kritik alanlarının ara sıra beyaz kutu testinde olduğuna inanma eğilimindeyim.


2

Arayüzlere karşı programlamanın gerçek nedeni, Rhino için hayatı kolaylaştırmak değil, koddaki nesneler arasındaki ilişkileri netleştirmektir. Bir arayüz, bir nesnenin ortamından ihtiyaç duyduğu bir hizmeti tanımlamalıdır. Bir sınıf, bu hizmetin belirli bir uygulamasını sağlar. Rebecca Wirfs-Brock'un Roller, Sorumluluklar ve İşbirliği Yapanlar hakkındaki "Nesne Tasarımı" kitabını okuyun.


Kabul ... Bunu yansıtacak şekilde sorumu güncelleyeceğim.
Kevin Albrecht

1

İyi liste. Kurmak isteyebileceğiniz şeylerden biri - ve ben de bunu düşünmeye yeni başladığım için size fazla tavsiye veremem - bir sınıfın farklı bir kitaplıkta, ad alanında, iç içe geçmiş ad alanlarında olması gerektiğidir. Hatta önceden kitaplıkların ve ad alanlarının bir listesini bulmak ve ekibin toplanıp ikisini birleştirmeye / yeni bir tane eklemeye karar vermesini zorunlu kılmak isteyebilirsiniz.

Oh, sadece benim yaptığım ve senin de yapmak isteyebileceğin bir şey düşündüm. Genelde, her testin karşılık gelen bir ad alanına gittiği, sınıf başına bir test fikstürü içeren bir birim testleri kitaplığım var. Ayrıca daha BDD tarzında olan başka bir test kütüphanesine (entegrasyon testleri?) Sahip olma eğilimindeyim . Bu, yöntemin ne yapması gerektiğini ve uygulamanın genel olarak ne yapması gerektiğini belirlemek için testler yazmama izin veriyor.


Kişisel bir projede benzer bir BDD tarzı test bölümü (birim test koduna ek olarak) yapıyorum.
Kevin Albrecht

0

İşte yapmayı sevdiğimi düşündüğüm bir tane daha.

TestDriven.Net veya NAnt'ın aksine birim test Gui'den testler çalıştırmayı planlıyorsanız, birim test proje türünü kitaplık yerine konsol uygulamasına ayarlamanın daha kolay olduğunu gördüm. Bu, testleri manuel olarak çalıştırmanıza ve hata ayıklama modunda adım adım ilerlemenize olanak tanır (yukarıda bahsedilen TestDriven.Net bunu sizin için gerçekten yapabilir).

Ayrıca, aşina olmadığım kod parçalarını ve fikirleri test etmek için açık bir Oyun Alanı projesine sahip olmayı her zaman seviyorum. Bu, kaynak kontrolünde kontrol edilmemelidir. Daha da iyisi, yalnızca geliştiricinin makinesinde ayrı bir kaynak kontrol havuzunda olması gerekir.

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.