Uygulama ayrıntılarına bağlanmadan birim test davranışları


16

Her şey yolunda gitmediği konuşmasında TDD, Ian Cooper'ın Kent Beck'in TDD'deki birim testlerinin arkasındaki asıl amacını itiyor (özel olarak sınıf yöntemlerini değil, davranışları test etmek için) ve testleri uygulamaya bağlamaktan kaçınmayı savunuyor.

save X to some data sourceTipik bir hizmet ve depo grubuna sahip bir sistemde olduğu gibi bir davranış durumunda , testi uygulama ayrıntılarıyla (belirli bir yöntemi çağırmak gibi) birleştirmeden, hizmet düzeyinde bazı verilerin depoda nasıl kaydedileceğini nasıl birim olarak test edebiliriz? )? Bu tür bağlantılardan kaçınmak aslında çabaya / kötü bir şekilde değmez mi?


1
Verilerin depoya kaydedildiğini test etmek istiyorsanız, testin aslında veriyi görmek için depoya gitmesi ve kontrol etmesi gerekecektir, değil mi? Yoksa bir şey mi kaçırıyorum?

Sorum daha çok, veri havuzunda belirli bir yöntemi çağırmak gibi testlerin bir uygulama detayıyla eşleştirilmesinden kaçınmaktı, ya da gerçekten yapılması gereken bir şeyse.
Andy Hunt

Yanıtlar:


8

Özel örneğiniz, genellikle belirli bir yöntemin çağrılıp çağrılmadığını kontrol ederek sınamanız gereken bir durumdur, çünkü harici bir bağımlılıklasaving X to data source iletişim kurmak anlamına gelir , bu nedenle sınamanız gereken davranış , iletişimin beklendiği gibi gerçekleşmesidir .

Ancak, bu kötü bir şey değil. Uygulamanız ve dış bağımlılıkları arasındaki sınır arabirimleri uygulama ayrıntıları değildir , aslında sisteminizin mimarisinde tanımlanırlar; yani böyle bir sınırın değişmesi muhtemel değildir (ya da olması gerekiyorsa, en az sıklıkta yapılan değişiklik olacaktır). Bu nedenle, testlerinizi bir repositoryarayüze bağlamak size çok fazla sorun yaratmamalıdır (eğer yaparsa, arayüzün uygulamadan sorumlulukları çalmadığını düşünün).

Şimdi, yalnızca kullanıcı arayüzünden, veritabanlarından ve diğer harici hizmetlerden ayrılmış bir uygulamanın iş kurallarını göz önünde bulundurun. Bu, kodun yapısını ve davranışını değiştirmekte özgür olmanız gerektiğiydi. Burada, bağlama testleri ve uygulama ayrıntıları, uygulamanın genel davranışında bir değişiklik olmasa bile, üretim kodundan daha fazla test kodunu değiştirmeye zorlar. Burası test yapmak Stateyerine Interactiondaha hızlı ilerlememize yardımcı oluyor.

Not: Niyetim, Devlet veya Etkileşimler tarafından testin TDD'nin tek gerçek yolu olup olmadığını söylemek değil - bunun doğru iş için doğru aracı kullanma meselesi olduğuna inanıyorum.


"Harici bir bağımlılıkla iletişim kurma" dan bahsettiğinizde, harici bağımlılıklardan, test edilen ünitenin dışında olanlardan mı yoksa bir bütün olarak sistemin dışında olanlardan mı bahsediyorsunuz?
Andy Hunt

"Dışa bağımlılık" derken, uygulamanız için bir eklenti olarak değerlendirilebileceğiniz her şeyi kastediyorum. Uygulama ile, kalıcılık veya kullanıcı arayüzü için hangi çerçevenin kullanılacağı gibi her türlü ayrıntıdan bağımsız iş kurallarını kastediyorum. Sanırım Bob Amca daha iyi açıklayabilir, bu konuşmada olduğu gibi: youtube.com/watch?v=WpkDN78P884
MichelHenrich

Bence bu, konuşmanın dediği gibi, "özellik" veya "davranış" temelinde test etmek ve özellik veya davranış başına bir test (veya bir değişkenin, yani değişken parametrelerin) testi için ideal bir yaklaşımdır. Ancak, bir özellik için 1 "mutlu" testim varsa, TDD yapmak için, bu özellik için tek bir dev taahhüt (ve kod incelemesi) yapacağım, bu kötü bir fikirdir. Bu nasıl önlenebilir? Bu özelliğin bir bölümünü test olarak ve onunla ilişkili tüm kodları yazın, sonra özelliğin kalanını aşamalı olarak sonraki işlemlere eklensin mi?
Ürdün

Gerçekten uygulamaya bağlı testlerin gerçek dünyadaki bir örneğini görmek istiyorum.
PositiveGuy

7

Bu konuşmayı benim yorumum:

  • sınıflar değil, test bileşenleri.
  • bileşenleri arabirim bağlantı noktaları üzerinden test eder.

Konuşmada belirtilmemiştir, ancak tavsiye için varsayılan bağlamın şöyle olduğunu düşünüyorum:

  • kullanıcılar için bir sistem geliştiriyorsunuz, örneğin bir yardımcı program kütüphanesi veya çerçevesi değil.
  • Testin amacı, rekabetçi bir bütçe dahilinde mümkün olduğunca başarılı bir şekilde sunmaktır.
  • bileşenler C # / Java gibi tek, olgun, muhtemelen statik olarak yazılmış bir dilde yazılır.
  • bir bileşen 10000-50000 satırlık sıradadır; Maven veya VS projesi, OSGI eklentisi vb.
  • bileşenler tek bir geliştirici veya yakın bir şekilde entegre edilmiş bir ekip tarafından yazılır.
  • altıgen mimari gibi bir şeyin terminolojisini ve yaklaşımını takip ediyorsunuz
  • Bileşen bağlantı noktası, yerel dili ve tür sistemini geride bıraktığınız yerdir, http / SQL / XML / bayt / ...
  • her bağlantı noktasını kaydırmak, Java / C # anlamında, anahtarlama teknolojilerine geçmek için uygulamaları devre dışı bırakılabilen yazılı arabirimlerdir.

Bu nedenle, bir bileşeni test etmek, bir şeyin yine de makul şekilde birim testi olarak adlandırılabileceği en büyük kapsamdır. Bu, bazı insanların, özellikle akademisyenlerin bu terimi nasıl kullandıklarından oldukça farklıdır. Tipik birim test aracı eğitimindeki örneklere benzemez. Bununla birlikte, donanım testindeki kökeni ile eşleşir; pano ve modüller kablo ve vidalarla değil, ünite testinden geçirilmiştir. Ya da en azından bir vidayı test etmek için sahte bir Boeing yapmıyorsun ...

Bundan ötürü tahmin etmek ve kendi düşüncelerimin bazılarını atmak,

  • Her arayüz bir girdi, çıktı veya ortak çalışan (veritabanı gibi) olacaktır.
  • giriş arayüzlerini test edersiniz ; yöntemleri çağırın, dönüş değerlerini iddia edin.
  • çıkış arayüzlerini taklit edersiniz ; belirli bir test durumu için beklenen yöntemlerin çağrıldığını doğrulayın.
  • ortak çalışanları sahte yaparsınız ; basit ama çalışan bir uygulama sağlamak

Bunu düzgün ve temiz bir şekilde yaparsanız, alaycı bir araca zar zor ihtiyacınız vardır; sistem başına sadece birkaç kez kullanılır.

Bir veritabanı genellikle bir ortaktır, bu yüzden alay etmek yerine sahte olur. Bu elle uygulamak acı verici olacaktır; Neyse ki böyle şeyler zaten var .

Temel test deseni bir dizi işlem yapmaktır (örneğin bir belgenin kaydedilmesi ve yeniden yüklenmesi); çalıştığını onaylayın. Bu, diğer tüm test senaryoları ile aynıdır; hiçbir (çalışan) uygulama değişikliğinin böyle bir testin başarısız olmasına neden olması muhtemel değildir.

İstisna, veritabanı kayıtlarının yazıldığı ancak test edilen sistem tarafından asla okunmadığı durumdur; örneğin denetim günlükleri veya benzeri. Bunlar çıktılardır ve bu yüzden alay edilmelidir. Test deseni bir dizi işlem yapmaktır; Denetim arabiriminin belirtildiği gibi yöntem ve bağımsız değişkenlerle çağrıldığını doğrulayın.

Burada bile, mockito gibi güvenli bir alay aracı kullanmanız koşuluyla , bir arabirim yönteminin yeniden adlandırılmasının test hatasına neden olamayacağını unutmayın. Testleri yüklerken bir IDE kullanırsanız, yeniden adlandırma yöntemi ile birlikte yeniden düzenlenir. Eğer yapmazsanız, test derlenmeyecektir.


Arayüz bağlantı noktasının somut bir örneğini tarif edebilir / verebilir misiniz?
PositiveGuy

çıkış arabirimi örneği nedir? Kodda spesifik olabilir misiniz? Giriş arayüzü ile aynı.
PositiveGuy

Bir arayüz (Java / C # anlamda), dış dünyayla konuşan herhangi bir şey olabilecek bir bağlantı noktasını sarar (d / b, soket, http, ....). Bir çıkış arabirimi, dış dünyadan bağlantı noktası aracılığıyla gelen dönüş değerlerine sahip herhangi bir yöntemi olmayan, yalnızca istisnalar veya eşdeğeri olan bir arabirimdir.
soru

Bir giriş arayüzü tam tersidir, ortak çalışan hem giriş hem de çıktıdır.
soru

1
Bence tamamen farklı bir tasarım yaklaşımından ve videoda açıklanan terminolojiden bahsediyorsunuz. Ancak zamanın% 90'ı bir depo (yani bir veritabanı) bir girdi veya çıktı değil, bir işbirlikçidir. Ve böylece arayüz bir işbirliği arayüzüdür.
soru

0

Benim önerim durum tabanlı bir test yaklaşımı kullanmaktır:

VERİLDİ Test DB'si bilinen bir durumda

ZAMAN hizmet argümanlar X ile çağrılır

SONRA DB'nin salt okunur depo yöntemlerini çağırarak ve döndürülen değerlerini kontrol ederek orijinal durumundan beklenen duruma değiştiğini iddia edin

Bu şekilde, hizmetin herhangi bir iç algoritmasına güvenmezsiniz ve testleri değiştirmek zorunda kalmadan uygulamasını yeniden düzenleme özgürlüğüne sahip olursunuz.

Buradaki tek bağlantı, servis yöntem çağrısı ve DB'den veri okumak için gerekli olan havuz çağrılarıdı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.