Yeniden yapılanmadan önce birim testleri nasıl yazılır?


55

"Yeniden yapılanma sırasında ünite testlerinizi nasıl çalışır durumda tutuyorsunuz?" Gibi benzer bir çizgi boyunca soruların bazı cevaplarını okudum. Benim durumumda senaryo biraz farklı çünkü sahip olduğumuz bazı standartları gözden geçirip getirmemiz gereken bir proje verildi, şu anda proje için hiçbir test yok!

DAO tip kodunu bir servis katmanında karıştırmama gibi daha iyi yapabileceğimi düşündüğüm birkaç şey tanımladım.

Yeniden düzenleme işleminden önce, mevcut kod için testler yazmak iyi bir fikir gibi göründü. Bana göre görünen sorun, yeniden yapılanma yaptığım zaman, belirli mantığın yapıldığı yer değiştiğimde testlerim bozulacak ve testlerin önceki yapıyı (alaylı bağımlılıklar vs.) göz önüne alarak yazacağım.

Benim durumumda, ilerlemenin en iyi yolu ne olurdu? Testleri, yeniden kodlanan kodun etrafına yazmak için cazip davranıyorum, ancak istenen davranışı değiştirebilecek bazı şeyleri hatalı şekilde yeniden düzenleme riskim bulunduğunun farkındayım.

Bu bir refactor veya yeniden tasarım olsun, düzeltilmesi gereken bu terimleri anladığım için mutluyum, şu anda yeniden düzenlemek için aşağıdaki tanım üzerinde çalışıyorum "Yeniden yapılanma ile, tanım gereği, yazılımınızın ne yaptığı, Nasıl yaptığını değiştirirsin. Bu yüzden, yazılımın ne yaptığını değiştirmeyeceğim, nasıl / nerede yapacağını değiştireceğim.

Aynı şekilde, yeniden tasarlanması düşünülebilecek yöntemlerin imzasını değiştirirsem argümanını görebiliyorum.

İşte kısa bir örnek

MyDocumentService.java (Mevcut)

public class MyDocumentService {
   ...
   public List<Document> findAllDocuments() {
      DataResultSet rs = documentDAO.findAllDocuments();
      List<Document> documents = new ArrayList<>();
      for(DataObject do: rs.getRows()) {
         //get row data create new document add it to 
         //documents list
      }

      return documents;
   }
}

MyDocumentService.java (yeniden düzenlenmiş / yeniden tasarlandı)

public class MyDocumentService {
   ...
   public List<Document> findAllDocuments() {
      //Code dealing with DataResultSet moved back up to DAO
      //DAO now returns a List<Document> instead of a DataResultSet
      return documentDAO.findAllDocuments();
   }
}

14
Gerçekten mi üstlenmeden yapmanız ya planlıyoruz yeniden ? Çünkü iki durumda cevap farklı olabilir.
otuz

4
Tanım üzerinde çalışıyorum "Yeniden yapılandırma ile, tanım gereği, yazılımınızın ne yaptığını değiştirmezsiniz, nasıl çalıştığını değiştirirsiniz." Bu yüzden üstlenmeden olan bu durumda, terimin benim anlayış doğru çekinmeyin inanıyoruz
PDStat

21
Yapma, entegrasyon testleri yaz. Planladığınız "yeniden düzenleme", birim test seviyesinin üzerindedir. Yalnızca üniteler yeni sınıfları test eder (veya onları sakladığınızı bildiğiniz eskileri).
OrangeDog

2
Yeniden yapılanmanın tanımı ile ilgili olarak, yazılımınız ne yaptığını açıkça tanımlıyor mu? Başka bir deyişle, zaten bağımsız API'lara sahip modüller halinde "faktörlendirilmiş" mi? Eğer değilse, o zaman belki en yüksek (kullanıcıya dönük) seviye hariç, onu yeniden değerlendiremezsiniz. Modül düzeyinde, kaçınılmaz olarak yeniden tasarlayacaksınız. Bu durumda, ünitelere sahip olmadan önce ünite testleri yazarak zamanınızı boşa harcamayın.
Kevin Krumwiede

4
Sadece bir test donanımına girebilmek için, testlerin güvenlik ağı olmadan bir miktar yeniden düzenleme yapmak zorunda kalacaksınız. Size verebileceğim en iyi tavsiye, IDE'niz veya yeniden düzenleme aracınız sizin için yapmazsa, el ile yapmamanızdır. CUT'yi bir kablo demetine sokana kadar otomatik yeniden düzenleme uygulamaya devam edin. Kesinlikle Michael Feather'ın "Eski Kod ile Etkili Çalışma" nın bir kopyasını almak isteyeceksiniz.
RubberDuck

Yanıtlar:


56

Regresyonları kontrol eden testleri arıyorsunuz . yani mevcut bazı davranışları kırmak. Bu davranışın hangi seviyede kalacağını ve bu davranışı sürdüren arayüzün aynı kalacağını belirleyerek başlar ve bu noktada testlere başlar.

Şimdi, bu seviyenin altında ne yaparsanız yapın, davranışınızın aynı kaldığını iddia edecek bazı testleriniz var .

Testlerin ve kodların nasıl eşitlenebileceğini sormakta oldukça haklısınız. Senin Eğer arayüz bir bileşene aynı kalır (yeni uygulama oluşturmak gibi), o zaman bu çevrede bir test yazmak ve her iki uygulama için de aynı koşullar iddia edebilir. Olmazsa, artık bir bileşen için yapılan bir testin bir artık test olduğu kabul edilmelidir.


1
Viz, ünite testinden ziyade entegrasyon veya sistem testi yapıyor olabilirsiniz. Muhtemelen hala bunun için bir "birim test" aracı kullanacaksınız, ancak her testte birden fazla kod birimine çarpacaksınız.
Mżż

Evet. Durum çok fazla. Regresyon testiniz çok yüksek seviyeli bir şey yapıyor olabilir, örneğin REST bir sunucuya ve muhtemelen sonraki bir veritabanı testine istekte bulunur (yani kesinlikle bir birim testi değil !)
Brian Agnew

40

Önerilen uygulama, muhtemelen hatalar da dahil olmak üzere kodun mevcut davranışını test eden "pin-down testler" ile başlamaktır, ancak gerekli belgeleri ihlal eden belirli bir davranışın hata olup olmadığını belirleme deliliğine inmek zorunda kalmadan başlamaktır. Bilmediğiniz veya gereksinimlerinizdeki belgelenmemiş bir değişikliği temsil eden bir çözüm için geçici çözüm.

Bu pin-down testlerinin yüksek seviyede olması, yani birim testlerden ziyade entegrasyon olması en doğru anlamlıdır, böylece yeniden düzenlemeye başladığınızda çalışmaya devam ederler.

Ancak bazı denetleyiciler kodu test edilebilir hale getirmek için gerekli olabilir - yalnızca "güvenli" yeniden düzenlemelere sadık kalmaya dikkat edin. Örneğin, neredeyse her durumda, özel olan yöntemler hiçbir şeyi kırmadan halka açıklanabilir.


Entegrasyon testleri için +1. Uygulamaya bağlı olarak, aslında web uygulamasına istek gönderme düzeyinde başlayabilirsiniz. Uygulamanın geri gönderdiği şey yalnızca yeniden yapılanma nedeniyle değişmemelidir, ancak HTML'yi geri göndermesi durumunda, bu kesinlikle daha az test edilebilir.
jpmc26

'Pin-down' testlerini seviyorum.
Brian Agnew

12

Öneriniz - eğer henüz yapmadıysanız - hem Eski Kodla Etkili Çalışma hem de Yeniden Düzenleme - Mevcut Kod Tasarımını Geliştirme .

[..] Bana göre görünen sorun, yeniden yapılanma yaptığım zaman, belirli bir mantığın yapıldığı yerde yapılan değişiklikler değiştiğimde bu testlerin sona ermesi ve testlerin önceki yapı akılda tutularak yazılmasıdır (alaşımlı bağımlılıklar vs.) [ ..]

Bunu mutlaka sorun olarak görmüyorum: Testleri yazın, kodunuzun yapısını değiştirin ve ardından test yapısını da ayarlayın . Bu size yeni yapınızın eskisinden daha iyi olup olmadığı hakkında doğrudan geri bildirim verecektir, çünkü eğer öyleyse, düzeltilmiş testlerin yazılması daha kolay olacaktır (ve böylece testlerin değiştirilmesi nispeten basit olmalı ve yeni tanıtılmış olma riskini düşürmelidir. hata testleri geçmesi).

Ayrıca, diğerleri zaten yazmış olduğu gibi: Çok detaylı testler yazmayın (en azından başlangıçta değil). Yüksek bir soyutlama seviyesinde kalmaya çalışın (bu nedenle testleriniz muhtemelen regresyon ve hatta entegrasyon testleri olarak nitelendirilecektir).


1
Bu. Testler berbat görünecek , ancak mevcut davranışı kapsayacak. Ardından, kod yeniden yapılandırıldıkça kilitleme adımındaki testleri de yapın. Gurur duyduğunuz bir şey olana kadar tekrarlayın. ++
RubberDuck

1
Ben her iki kitap tavsiyesinden de ikincisiyim - testsiz kodlarla uğraşmak zorunda kaldığımda her zaman elimde her zaman yanımdayım.
Toby Speight

5

Tüm bağımlılıklarla alay ettiğiniz sıkı birim testleri yazmayın. Bazı insanlar size bunların gerçek ünite testleri olmadığını söyleyecektir. Onları önemseme. Bu testler faydalıdır ve önemli olan da budur.

Örnekinize bakalım:

public class MyDocumentService {
   ...
   public List<Document> findAllDocuments() {
      DataResultSet rs = documentDAO.findAllDocuments();
      List<Document> documents = new ArrayList<>();
      for(DataObject do: rs.getRows()) {
         //get row data create new document add it to 
         //documents list
      }

      return documents;
   }
}

Testin muhtemelen şöyle bir şeye benziyor:

DocumentDao documentDao = Mock.create(DocumentDao.class);
Mock.when(documentDao.findAllDocuments())
    .thenReturn(DataResultSet.create(...))
assertEquals(..., new MyDocumentService(documentDao).findAllDocuments());

DocumentDao'yle dalga geçmek yerine, bağımlılıklarıyla dalga geçin:

DocumentDao documentDao = new DocumentDao(db);
Mock.when(db...)
    .thenReturn(...)
assertEquals(..., new MyDocumentService(documentDao).findAllDocuments());

Artık, mantığı , testleri bozmadan MyDocumentServiceiçine taşıyabilirsiniz DocumentDao. Testler, işlevselliğin aynı olduğunu gösterecektir (test ettiğinize kadar).


DocumentService'i test ediyorsanız ve DAO ile dalga geçmiyorsanız, bu bir birim testi değildir. Üniter ve entegrasyon testi arasında bir şey var. Değil mi?
LAIV

7
@Laiv, insanların birim testi terimini nasıl kullandıkları konusunda gerçekten çok çeşitli var. Bazıları yalnızca kesin olarak izole edilmiş testler anlamına gelir. Diğerleri hızlı çalışan herhangi bir testi içerir. Bazıları test çerçevesinde çalışan her şeyi içerir. Fakat nihayetinde, birim test terimini nasıl tanımlamak istediğiniz önemli değildir. Soru, hangi testlerin yararlı olduğu sorusudur, bu nedenle birim testini tam olarak nasıl tanımladığımızdan rahatsız olmamamız gerekir.
Winston Ewert

Yararlılığın en önemli olduğunu gösteren mükemmel bir nokta. Sadece çok fazla zaman harcayan algoritmalar için abartılı ünite testleri, ünite testlerinin sadece büyük bir zaman kaybı ve değerli kaynaklar olmasa bile, faydadan daha fazla zarar vermesi adına. Bu hemen hemen her şeye uygulanabilir ve kariyerimde daha önce bilmek istediğim bir şey.
Lee

3

Dediğiniz gibi, eğer davranışı değiştirirseniz, o zaman bir refactor değil bir dönüşümdür. Davranışı hangi seviyede değiştirirseniz, fark yaratan şey budur.

En üst düzeyde resmi testler yoksa, kodunuzun çalışıyor olması için yeniden tasarlanmanızdan sonra aynı kalması gereken müşterilerin (çağrı kodu veya insanları) aynı kalması gereken bir dizi gereksinimi deneyin. Uygulamanız gereken test durumlarının listesi budur.

Değişen test durumlarını gerektiren uygulamaları değiştirmekle ilgili sorunuza değinmek için Detroit (klasik) - Londra (mockist) TDD'ye bir göz atmanızı öneririm. Martin Fowler, büyük makalesinde Mocks'in taslaklar olmadığını ancak pek çok kişinin görüşüne sahip olduğunu söylüyor. Eğer dışarıdakilerin değişemediği en yüksek seviyeden başlarsanız ve yolunuzu aşarsanız, gerçekten değişmesi gereken bir seviyeye gelene kadar gereksinimler oldukça kararlı kalmalıdır.

Herhangi bir test yapmadan bu zor olacak ve yeni kodunuzun tam olarak yapması gerekeni yaptığından emin olana kadar müşterileri çift kodlu yollardan (ve farkları kaydederek) kullanmayı düşünebilirsiniz.


3

İşte benim yaklaşımım. Zaman açısından bir maliyeti var çünkü 4 aşamada bir yeniden test edicidir.

Açıklayacağım şey, sorunun örneğinde açıklanandan daha karmaşık olan bileşenlerde daha iyi olabilir.

Her halükarda, strateji, herhangi bir bileşen adayının bir arayüz tarafından normalleştirilmesi için geçerlidir (DAO, Servisler, Kontrolörler, ...).

1. arayüz

Tüm genel yöntemleri MyDocumentService'ten toplayalım ve hepsini bir araya getirelim . Örneğin. Zaten varsa, yenisini ayarlamak yerine onu kullanın .

public interface DocumentService {

   List<Document> getAllDocuments();

   //more methods here...
}

Sonra MyDocumentService'i bu yeni arayüzü uygulamaya zorluyoruz .

Çok uzak çok iyi. Önemli bir değişiklik yapılmadı, mevcut sözleşmeye saygı gösterdik ve davranışlar dokunulmadı.

public class MyDocumentService implements DocumentService {

 @Override
 public List<Document> getAllDocuments(){
         //legacy code here as it is.
        // with no changes ...
  }
}

2. Eski kod Birim testi

İşte zor işimiz var. Bir test takımı kurmak için. Mümkün olduğu kadar çok vaka belirlemeliyiz: başarılı vakalar ve ayrıca hata davaları. Bu son, sonucun kalitesinin iyiliği içindir.

Şimdi, MyDocumentService'i test etmek yerine arayüzü test edilecek sözleşme olarak kullanacağız.

Ayrıntılara girmeyeceğim, bu yüzden beni affet. Kodum çok basit veya çok agnostik görünüyorsa

public class DocumentServiceTestSuite {

   @Mock
   MyDependencyA mockDepA;

   @Mock
   MyDependencyB mockDepB;

    //... More mocks

   DocumentService service;

  @Before
   public void initService(){
       service = MyDocumentService(mockDepA, mockDepB);
      //this is purposed way to inject 
      //dependencies. Replace it with one you like more.  
   }

   @Test
   public void getAllDocumentsOK(){
         // here I mock depA and depB
         // wanted behaivors...

         List<Document> result = service.getAllDocuments();

          Assert.assertX(result);
          Assert.assertY(result);
           //... As many you think appropiate
    } 
 }

Bu aşama, bu yaklaşımda diğerlerinden daha uzun sürer. Ve en önemlisi çünkü gelecekteki karşılaştırmalar için referans noktası belirleyecektir.

Not: Büyük değişiklikler yapılmamasından ve davranışçıya dokunulmadan kalmasından dolayı. Burada SCM'ye bir etiket yapmayı öneririm. Etiket veya dal önemli değil. Sadece bir versiyon yap.

Geri almalar, sürüm karşılaştırmaları için istiyoruz ve eski kodun ve yenisinin paralel yürütülmesi için olabilir.

3. Yeniden düzenleme

Refactor yeni bir bileşene uygulanacak. Mevcut kodda herhangi bir değişiklik yapmayız. İlk adım MyDocumentService’in kopyalayıp yapıştırmak ve CustomDocumentService olarak yeniden adlandırmak kadar kolaydır (örneğin).

Yeni sınıf, DocumentService'i uygulamaya devam ediyor . Sonra gidip getAllDocuments () işlevini yeniden düzenleyin . (Hadi başlayalım. Pin-refactors)

DAO'nun arayüzünde / yöntemlerinde bazı değişiklikler gerektirebilir. Eğer öyleyse, mevcut kodu değiştirmeyin. DAO arayüzünde kendi metodunuzu kullanın. Eski kodu Kaldırıldı olarak not edin ve daha sonra kaldırılması gerekenleri bileceksiniz.

Mevcut uygulamayı bozmamak / değiştirmemek önemlidir. Her iki hizmeti de paralel olarak yürütmek ve sonuçları karşılaştırmak istiyoruz.

public class CustomDocumentService implements DocumentService {

 @Override
 public List<Document> getAllDocuments(){
         //new code here ...
         //due to im refactoring service 
         //I do the less changes possible on its dependencies (DAO).
         //these changes will come later 
         //and they will have their own tests
  }
 }

4. DocumentServiceTestSuite'ın güncellenmesi

Tamam, şimdi daha kolay olanı. Yeni bileşenin testlerini eklemek.

public class DocumentServiceTestSuite {

   @Mock
   MyDependencyA mockDepA;

   @Mock
   MyDependencyB mockDepB;

   DocumentService service;
   DocumentService customService;

  @Before
   public void initService(){
       service = MyDocumentService(mockDepA, mockDepB);
        customService = CustomDocumentService(mockDepA, mockDepB);
       // this is purposed way to inject 
       //dependencies. Replace it with the one you like more
   }

   @Test
   public void getAllDocumentsOK(){
         // here I mock depA and depB
         // wanted behaivors...

         List<Document> oldResult = service.getAllDocuments();

          Assert.assertX(oldResult);
          Assert.assertY(oldResult);
           //... As many you think appropiate

          List<Document> newResult = customService.getAllDocuments();

          Assert.assertX(newResult);
          Assert.assertY(newResult);
           //... The very same made to oldResult

          //this is optional
Assert.assertEquals(oldResult,newResult);
    } 
 }

Artık her ikisi de bağımsız olarak doğrulanmış oldResult ve newResult değerlerine sahibiz, ancak birbirleriyle de karşılaştırabiliriz. Bu son doğrulama isteğe bağlıdır ve sonuca bağlıdır. Bu karşılaştırılabilir değil olabilir.

İki koleksiyonun bu şekilde karşılaştırılması çok fazla duyarlı olmayabilir, ancak başka herhangi bir nesne için geçerli olur (pojos, veri modeli varlıkları, DTO'lar, Sarmalayıcılar, yerel türler ...)

notlar

Birim testleri yapmayı ya da sahte kütüphaneleri nasıl kullanacağımı söylemeye cesaret edemem. İkisini de nasıl refactor yapmak zorunda olduğunu söylemeye cesaret edemem. Yapmak istediğim küresel bir strateji önermek. Nasıl ileri götürüleceğiniz size bağlıdır. Tam olarak kodun ne olduğunu, karmaşıklığını ve bu tür bir stratejinin denemeye değer olduğunu biliyorsunuz. Zaman ve kaynaklar gibi gerçekler burada önemlidir. Ayrıca gelecekte bu testlerden ne beklediğiniz önemlidir.

Örneklerimi bir Servis tarafından başlattım ve DAO ile takip ediyorum. Bağımlılık seviyelerine derinlemesine gitmek. Aşağı yukarı strateji olarak tanımlanabilir . Ancak küçük değişiklikler / refactors ( tur örneğinde maruz kalan gibi ) için aşağıdan yukarıya bir iş daha kolay olacaktır. Çünkü değişikliklerin kapsamı azdır.

Son olarak, kullanımdan kaldırılmış kodu kaldırmak ve eski bağımlılıkları yenisine yönlendirmek size kalmıştır.

Kaldırılan testleri de kaldırın ve işiniz bitti. Eski çözümü testleriyle birlikte sürümlendirdiyseniz, istediğiniz zaman birbirinizi kontrol edip karşılaştırabilirsiniz.

Bu kadar çok çalışmanın sonucunda test edilmiş, onaylanmış ve versiyonlanmış eski kodlara sahipsiniz. Ve yeni kod, test edildi, onaylandı ve versiyonlanmaya hazır.


3

tl; dr Birim testleri yazmayın. Testleri daha uygun bir seviyede yazın.


Yeniden yapılanma çalışma tanımınıza bakıldığında:

yazılımınızın ne yaptığını değiştirmezsiniz, nasıl çalıştığını değiştiremezsiniz

orada çok geniş spektrumlu. Bir ucunda, belki de daha verimli bir algoritma kullanarak, belirli bir metotta bağımsız bir değişiklik var. Diğer tarafta başka bir dile taşıyor.

Yeniden yapılanma / yeniden tasarlama seviyesi ne olursa olsun, bu seviyede veya daha yüksek düzeyde çalışan testlerin yapılması önemlidir.

Otomatik testler genellikle seviye olarak şu şekilde sınıflandırılır:

  • Birim testleri - Bireysel bileşenler (sınıflar, yöntemler)

  • Entegrasyon testleri - Bileşenler arasındaki etkileşimler

  • Sistem testleri - Komple uygulama

Yeniden yapılanmaya dayanamayan test seviyesini esasen el değmeden yazın.

düşünün:

Uygulama , yeniden düzenleme işleminden önce ve sonra ne gibi halka açık olarak görülebilen bir davranışa sahip olacak ? Bu şeyin hala aynı şekilde çalıştığını nasıl test edebilirim?


2

Arayüzün önemsiz bir şekilde değişeceğini tahmin edebileceğiniz noktalarda bağlanan zaman yazma testlerini boşa harcamayın. Bu genellikle, doğası gereği “işbirlikçi” olan sınıfları test etmeye çalıştığınızın bir işaretidir - değeri kendi yaptıklarında değildir, ancak değerli davranışlar üretmek için birbirleriyle yakından ilgili birkaç sınıfla nasıl etkileşime girdiklerini . O var o size daha yüksek bir seviyede test etmek istiyorum, yani test etmek istediğiniz davranışı. Bu seviyenin altında test etmek çoğu zaman çok çirkin alaycılığa ihtiyaç duyar ve sonuçta ortaya çıkan testler, davranışı savunmak için bir yardımdan çok, geliştirme üzerinde bir sürükleyici olabilir.

Bir refactor yapıp yapmadığınızı ya da yeniden tasarladığınızı ya da her neyse onu fazla takma. Daha düşük seviyelerde birkaç bileşenin yeniden tasarlanmasını oluşturan değişiklikler yapabilirsiniz, ancak daha yüksek bir entegrasyon düzeyinde sadece bir refaktöre eşittir. Mesele hangi davranışın sizin için değerli olduğu konusunda net olmak ve ilerledikçe bu davranışı savunmak.

Testlerinizi yazarken düşünmeniz faydalı olabilir - bu testin gerçekte ne test ettiğini bir QA, ürün sahibi veya kullanıcı için kolayca açıklayabilir miyim? Testi açıklamak çok ezoterik ve teknik olurdu gibi görünüyorsa, belki de yanlış seviyede test yapıyorsunuzdur. 'Mantıklı' noktalarda / seviyelerde test edin ve her seviyedeki testlerle kodunuzu saklamayın.


Her zaman tekliflerin sebepleriyle ilgilen!
topo morto

1

İlk göreviniz, testleriniz için “ideal yöntem imzası” bulmaya çalışmaktır. Saf bir işlev yapmak için çaba gösterin . Bu aslında test edilen koddan bağımsız olmalıdır; bu küçük bir adaptör katmanıdır. Kodunuzu bu adaptör katmanına yazın. Artık kodunuzu yeniden yapılandırdığınızda, yalnızca adaptör katmanını değiştirmeniz gerekir. İşte basit bir örnek:

[TestMethod]
public void simple_addition()
{
    Assert.AreEqual(7, Eval("3 + 4"));
}

[TestMethod]
public void order_of_operations()
{
    Assert.AreEqual(52, Eval("2 + 5 * 10"));
}

[TestMethod]
public void absolute_value()
{
    Assert.AreEqual(9, Eval("abs(-9)"));
    Assert.AreEqual(5, Eval("abs(5)"));
    Assert.AreEqual(0, Eval("abs(0)"));
}

static object Eval(string expression)
{
    // This is the code under test.
    // I can refactor this as much as I want without changing the tests.
    var settings = new EvaluatorSettings();
    Evaluator.Settings = settings;
    Evaluator.Evaluate(expression);
    return Evaluator.LastResult;
}

Sınamalar iyi, ancak sınamadaki kodun hatalı bir API'si var. Sadece adaptör katmanımı güncelleyerek testleri değiştirmeden yeniden deneyebilirim:

static object Eval(string expression)
{
    // After refactoring...
    var settings = new EvaluatorSettings();
    var evaluator = new Evaluator(settings);
    return evaluator.Evaluate(expression);
}

Bu örnek, Kendinizi Tekrar Etme ilkesi uyarınca yapmanız oldukça açık bir şey gibi görünmektedir, ancak diğer durumlarda çok açık olmayabilir. Avantaj DRY'nin ötesine geçiyor - gerçek avantaj, testlerin test edilen koddan ayrılmasıdır.

Tabii ki, bu teknik her durumda uygun olmayabilir. Örneğin, POCO'lar / POJO'lar için adaptörler yazmak için hiçbir sebep olmaz, çünkü test kodundan bağımsız olarak değişebilecek bir API'leri yoktur. Ayrıca az sayıda test yazıyorsanız, nispeten büyük bir adaptör katmanı muhtemelen boşa harcanacaktı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.