Alt sınıflarımı veya soyut ana sınıfımı birim test etmeli miyim?


12

Etkili Java ( burada genişletilmiş tartışma ) Madde 18 gibi bir iskelet uygulaması var . Soyut olarak tanımlayamadığım "boşlukları doldurmak" için alt sınıf yöntemlerini çağıran 2 genel yöntem methodA () ve methodB () sağlayan soyut bir sınıftır.

Önce somut bir sınıf oluşturarak ve bunun için birim testleri yazarak geliştirdim. İkinci sınıf geldiğinde, ortak davranışları elde edebildim, ikinci sınıfta "eksik boşlukları" uygulayabildim ve hazırdı (tabii ki ikinci alt sınıf için birim testleri oluşturuldu).

Zaman geçti ve şimdi 4 alt sınıfım var, her biri somut uygulamalarına çok spesifik olan 3 kısa korumalı yöntem uyguluyor, iskelet uygulaması ise genel işi yapıyor.

Benim sorunum, yeni bir uygulama oluşturduğunuzda, testleri tekrar yazıyorum:

  • Alt sınıf belirli bir gerekli yöntemi çağırıyor mu?
  • Belirli bir yöntemin belirli bir açıklaması var mı?
  • Beklenen sonuçları A yönteminden alabilir miyim?
  • Beklenen sonuçları B yönteminden alabilir miyim?

Bu yaklaşımın avantajlarına bakın:

  • Testler yoluyla alt sınıf gereksinimlerini belgeler
  • Sorunlu bir yeniden düzenleme durumunda hızlı başarısız olabilir
  • Alt sınıfı bir bütün olarak ve genel API'leriyle test edin ("bu korunan yöntem çalışıyor mu?" Değil, "methodA () çalışıyor mu?")

Sahip olduğum sorun, yeni bir alt sınıf için testler temelde bir beyinsiz olmasıdır: - Testler tüm alt sınıflarda hepsi aynıdır, sadece yöntemlerin dönüş tipini değiştirirler (iskelet uygulaması geneldir) ve özellikleri I testin onaylanmış kısmını kontrol edin. - Genellikle alt sınıfların kendilerine özgü testleri yoktur

Testlerin alt sınıfın sonucuna odaklanmasını ve yeniden düzenlemeye karşı korumasını seviyorum, ancak testin uygulanmasının sadece "manuel çalışma" olması beni yanlış bir şey yaptığımı düşündürüyor.

Sınıf hiyerarşisini test ederken bu sorun yaygın mıdır? Bundan nasıl kaçınabilirim?

ps: İskelet sınıfını test etmeyi düşündüm, ama aynı zamanda onu test edebilmek için soyut bir sınıfın alayını oluşturmak garip görünüyor. Ve alt sınıfın beklemediği davranışı değiştiren soyut sınıfa yeniden düzenleme yapmanın bu kadar hızlı fark edilmeyeceğini düşünüyorum. Bağırsaklarım, "bir bütün olarak" alt sınıfını test etmenin burada tercih edilen yaklaşım olduğunu söylüyor, ancak lütfen bana yanlış olduğumu söylemekten çekinmeyin :)

ps2: Google'ı araştırdım ve konuyla ilgili birçok soru buldum. Bunlardan biri Nigel Thorne'dan büyük bir cevabı olan bu , benim durumum onun "1 sayısı" olurdu. Bu harika olurdu, ama bu noktada yeniden düzenleme yapamam, bu yüzden bu problemle yaşamak zorunda kalacağım. Refactor yapabilseydim, her alt sınıfı bir strateji olarak görürdüm. Bu iyi olurdu, ama yine de "ana sınıfı" ve stratejileri test ederdim, ama ana sınıf ve stratejiler arasındaki entegrasyonu bozan herhangi bir yeniden düzenleme fark etmezdim.

ps3: Soyut sınıfı test etmek "kabul edilebilir" diyen bazı cevaplar buldum. Bunun kabul edilebilir olduğuna katılıyorum, ancak bu durumda tercih edilen yaklaşımın hangisi olduğunu bilmek istiyorum (hala birim testlerle başlıyorum)


2
Soyut bir test sınıfı yazın ve iş kodunuzun yapısını yansıtarak somut testlerinizi miras edin. Testlerin, bir birimin uygulanmasını değil, davranışı test etmesi gerekir, ancak bu, bu hedefe daha verimli bir şekilde ulaşmak için sistem hakkındaki içeriden bilginizi kullanamayacağınız anlamına gelmez.
Kilian Foth

Testlerde kalıtım kullanmaması gereken bir yerde okudum, dikkatlice okumak için kaynak arıyorum
JSBach

4
@KilianFoth Bu tavsiyeden emin misin? Bu, kırılgan birim testleri için bir reçete gibi görünüyor, tasarım değişikliklerine son derece duyarlı ve bu nedenle çok bakım gerektirmiyor.
Konrad Morawski

Yanıtlar:


5

Soyut bir temel sınıf için testleri nasıl yazacağınızı göremiyorum ; başlatamazsınız, bu yüzden test etmek için bir örneğine sahip olamazsınız . Sadece test etmek için "kukla", somut bir alt sınıf oluşturabilirsiniz - ne kadar kullanacağından emin değilsiniz. YMMV.

Her yeni uygulama (sınıf) oluşturduğunuzda, o yeni uygulamayı uygulayan testler yazmalısınız. İşlevselliğin bazı bölümleri ("boşluklarınız") her alt sınıfta uygulandığından , bu kesinlikle gereklidir; kalıtsal yöntemlerin her birinin çıktısı her yeni uygulama için farklı olabilir (ve muhtemelen olmalıdır ).


Evet, farklılar (türler ve içerik farklı). Teknik olarak konuşursak, bu sınıfla alay edebilir veya sadece boş uygulamalar ile test amacıyla basit bir uygulamaya sahip olabilirim. Bu yaklaşımı sevmiyorum. Ancak yeni uygulamalarda başarılı testler yaptırmayı düşünmem gerekmediği gerçeği beni garip hissettiriyor ve ayrıca bu testte kendime ne kadar güven duyduğumu da sorguluyor (tabii ki temel sınıfı bilerek değiştirirsem, testleri başarısız olur, bu onlara güvenebileceğimin bir kanıtıdır)
JSBach

4

Genellikle bir arabirimi zorlamak için bir temel sınıf yaratırsınız. Aşağıdaki ayrıntıları değil, bu arayüzü test etmek istiyorsunuz. Bu nedenle, her sınıfı ayrı ayrı başlatan ancak yalnızca temel sınıfın yöntemlerini kullanarak sınamalar oluşturmalısınız.

Bu yöntemin avantajları, arayüzü test ettiğiniz için, şimdi arayüzün altında yeniden düzenleme yapabilmenizdir. Bir alt sınıftaki kodun üst öğede olması veya tam tersi olması gerektiğini görebilirsiniz. Şimdi testleriniz, bu kodu taşıdığınızda davranışı bozmadığınızı kanıtlayacak.

Genel olarak, kodu nasıl kullanıldığını test etmelisiniz. Bu, özel yöntemleri test etmekten kaçınmak anlamına gelir ve genellikle test edilen ünitenizin başlangıçta düşündüğünüzden biraz daha büyük olabileceği anlamına gelir - belki de tek bir sınıftan ziyade bir sınıf sınıfı. Hedefiniz değişiklikleri izole etmek olmalıdır, böylece belirli bir kapsamda yeniden düzenleme yaptığınızda bir testi nadiren değiştirmeniz 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.