Alaycılar Açık / Kapalı prensibini ihlal ediyor mu?


13

Bir süre önce, bulamadığım bir Yığın Taşması cevabında, genel API'leri test etmeniz gerektiğini açıklayan bir cümle okudum ve yazar arayüzleri test etmeniz gerektiğini söyledi. Yazar ayrıca, bir yöntem uygulaması değiştiyse, test senaryosunu değiştirmeniz gerekmediğini, çünkü bunu yapmak, test altındaki sistemin çalıştığından emin olmak için sözleşmeyi bozacağını açıkladı. Başka bir deyişle, yöntem çalışmazsa test başarısız olur, ancak uygulama değiştiği için değil.

Alaycılık hakkında konuşurken dikkatimi çekti. Alay etme, büyük ölçüde testin bağımlılıkları altındaki sistemden beklenti çağrılarına dayandığından, alaylar arayüzden ziyade uygulama ile sıkı sıkıya bağlıdır.

Sahte ve saplama araştırılırken , çeşitli makaleler bağımlılıklardan beklentilere dayanmadığı için alay yerine saplamalar kullanılması gerektiği konusunda hemfikirdir, yani testin test uygulaması altındaki temel sistem hakkında hiçbir bilgiye ihtiyacı yoktur.

Sorularım şöyle olurdu:

  1. Alaycılar açık / kapalı prensibini ihlal ediyor mu?
  2. Tartışmada, son paragraftaki taslaklar lehine, saplamaları alaylara karşı çok büyük olmayan bir şey eksik mi?
  3. Öyleyse, ne zaman alay etmek için iyi bir kullanım durumu ve ne zaman taslak kullanmak için iyi bir kullanım durumu olur?


8
Since mocking relays heavily on expectation calls from system under test's dependencies...Sanırım bu, nereye gittiğin. Alay etmek, harici bir sistemin yapay bir temsilidir. Harici sistemi , testlerin söz konusu harici sisteme bağımlılığı olan koda karşı yürütülmesine izin verecek şekilde simüle ettiği sürece harici sistemi hiçbir şekilde temsil etmez . Kodunuzun gerçek, engellenmemiş sistemle
Robert Harvey

8
Başka bir deyişle, sahte bir ikame uygulamasıdır. Bu yüzden ilk olarak bir arayüze programladık, böylece gerçek uygulama için alayları bir stand-in olarak kullanabiliriz. Başka bir deyişle, alaylar gerçek uygulamadan ayrılır, birleştirilmez.
Robert Harvey

3
"Diğer bir deyişle, yöntem çalışmazsa bir test başarısız olmalıdır, ancak uygulama değiştiği için değil", bu her zaman doğru değildir. Hem uygulamanızı hem de testlerinizi değiştirmeniz gereken birçok koşul vardır.
whatsisname

Yanıtlar:


4
  1. Alaycıların neden açık / kapalı prensibini ihlal ettiğini anlamıyorum. Bize neden olabileceğini düşündüğünüzü açıklayabilirseniz, endişelerinizi hafifletebiliriz.

  2. Düşünebileceğim saplamaların tek dezavantajı, genellikle yazmaktan daha fazla iş gerektirmeleri, çünkü bunların her biri aslında bağımlı bir arayüzün alternatif bir uygulamasıdır, bu yüzden genellikle tam (veya ikna edici bir şekilde tamamlanmış) bağımlı arayüzün uygulanması. Size aşırı bir örnek vermek gerekirse, test altındaki alt sisteminiz bir RDBMS çağırıyorsa, RDBMS'nin bir örneği, test edilen alt sistem tarafından yayınlandığı bilinen belirli sorgulara yanıt verir ve önceden belirlenmiş test verisi kümeleri verir. Öte yandan, alternatif bir uygulama, muhtemelen üretimde kullandığınız gerçek istemci-sunucu RDBMS'nin tuhaflıklarını taklit etmek zorunda kalmanın ek yükü olan, tam gelişmiş bir bellek içi RDBMS olacaktır. (Neyse ki, HSQLDB gibi şeylerimiz var, bu yüzden aslında bunu yapabiliriz, ama yine de,

  3. Alay için iyi kullanım durumları, bağımlı arayüzün bunun için alternatif bir uygulama yazmak için çok karmaşık olduğu veya sahte olanı yalnızca bir kez yazacağınızdan ve bir daha asla dokunmayacağınızdan eminseniz. Bu durumlarda, hızlı ve kirli bir sahte kullanın. Sonuç olarak, taslaklar için iyi kullanım durumları (alternatif uygulamalar) hemen hemen her şeydir. Özellikle test edilen alt sistemle uzun vadeli bir ilişki kurmayı öngörürseniz, kesinlikle güzel ve temiz olacak ve arayüz değiştiğinde bakım gerektirmek yerine sadece arayüz değiştiğinde bakım gerektirecek alternatif bir uygulamaya gidin. değişiyor ve test altındaki alt sistemin uygulaması her değiştiğinde.

Not: Bahsettiğiniz kişi, programmers.stackexchange.com'daki testle ilgili diğer cevaplarımdan birinde , örneğin bu benim olabilirdi .


an alternative implementation would be a full-blown in-memory RDBMS- Bir saplama ile o kadar ileri gitmek zorunda değilsiniz.
Robert Harvey

@RobertHarvey iyi, HSQLDB ve H2 ile aslında o kadar ileri gitmek zor değil. Bir şey için yarım assed yapmak muhtemelen daha zordur değil uzakta olduğunu gidin. Ancak bunu kendi başınıza yapmaya karar verirseniz, bir SQL ayrıştırıcısı yazarak başlamanız gerekir. Tabii, bazı köşeleri kesebilirsin, ama çok iş var . Her neyse, yukarıda söylediğim gibi, bu sadece aşırı bir örnek.
Mike Nakis

9
  1. Açık / Kapalı prensibi çoğunlukla bir sınıfın davranışını değiştirmeden değiştirebilmeyle ilgilidir. Bu nedenle, sınanan bir bileşen bağımlılığının sınanan bir sınıfa enjekte edilmesi onu ihlal etmez.

  2. Test çiftleri (sahte / saplama) ile ilgili sorun, temel olarak test edilen sınıfın çevresiyle nasıl etkileşime girdiğiyle ilgili keyfi varsayımlar yapmanızdır. Bu beklentiler yanlışsa, kod dağıtıldıktan sonra bazı sorunlar yaşayabilirsiniz. Ödeyebiliyorsanız, kodunuzu üretim ortamınızı sınırlayanla aynı kısıtlamalar içinde test edin. Yapamıyorsanız, mümkün olan en az varsayımı yapın ve yalnızca sisteminizin çevre birimlerini (veritabanı, kimlik doğrulama hizmeti, HTTP istemcisi vb.) Taklit edin / saplayın.

Bir çiftin IMHO'nun kullanılmasının tek geçerli nedeni, test edilen sınıfla etkileşimlerini kaydetmeniz gerektiğinde veya sahte veriler sağlamanız gerektiğinde (her iki tekniğin de yapabileceği). Ancak, bunun kötüye kullanılması kötü bir tasarımı veya test uygulaması altındaki API'ya çok fazla dayanan bir testi yansıtır.


6

Not: Ben "izlemek, hiçbir uygulamaya sahip bir sınıf sadece bir şey olabilir" Şunu etmek Mock tanımlayan varsayarak ve Saplama ediyorum uyarınca, "kısmi sahte, nam uygulanan sınıfın gerçek davranışının bazı kullanır" olarak bu Yığın Taşma sorusu .

Mutabakatın saplamaları kullanmak olduğunu düşündüğünüzden emin değilim, örneğin Mockito Belgelerinde bunun tam tersi

Her zamanki gibi kısmi alay uyarısını okuyacaksınız: Nesneye yönelik programlama, karmaşıklığı ayrı, spesifik, SRPy nesnelerine bölerek karmaşıklığı daha az ele alır. Kısmi alay bu paradigmaya nasıl uyuyor? Sadece ... Kısmi alay genellikle karmaşıklığın aynı nesne üzerinde farklı bir yönteme taşındığı anlamına gelir. Çoğu durumda, uygulamanızı tasarlamak istediğiniz yol bu değildir.

Ancak, kısmi alayların işe yaradığı nadir durumlar vardır: kodla uğraşmak kolayca değiştiremezsiniz (3. taraf arayüzleri, eski kodun yeniden düzenlenmesi vb.) Ancak, yeni, test odaklı ve iyi- tasarlanmış kod.

Bu belgeler benden daha iyi diyor. Alaycıları kullanmak, sadece belirli bir sınıfı test etmenizi sağlar ve başka hiçbir şey yapmaz; Aradığınız davranışı elde etmek için kısmi alaylara ihtiyacınız varsa, muhtemelen yanlış bir şey yaptınız, SRP'yi ihlal ediyorsunuz vb. ve kodunuz bir refactor'a dayanabilir. Alaylar açık-kapalı prensibini ihlal etmez , çünkü zaten testlerde zaten kullanılırlar, bu kodda gerçek değişiklikler değildirler. Genellikle zaten cglib gibi bir kütüphane tarafından anında üretilirler.


2
Sağlanan SO sorusundan (kabul edilen cevap), bu da atıfta bulunduğum Mock / Stub tanımıdır: Mock nesneleri beklentileri tanımlamak için kullanılır, yani: Bu senaryoda, bu ve bu tür parametrelerle A () yönteminin çağrılmasını bekliyorum. Alaycılar bu beklentileri kaydeder ve doğrular. Öte yandan, taslakların farklı bir amacı vardır: beklentileri kaydetmezler veya doğrulamazlar, aksine bir test senaryosunu kullanmak için davranışı, “sahte” nesnenin durumunu “değiştirmemize” izin verirler ...
Christopher Francisco

2

Mesele, tek geçerli testlerin açık / kapalı testi karşılayan testler olduğu varsayımından kaynaklanabilir.

Önemli olan tek testin arayüzü test eden test olduğunu görmek kolaydır. Bununla birlikte, gerçekte, iç aralıkları test ederek bu arayüzü test etmek genellikle daha etkilidir.

Örneğin, "uygulama herhangi bir istisna atmayacaktır" gibi herhangi bir olumsuz gereksinimi test etmek neredeyse imkansızdır. Bir hashmap ile uygulanmış bir harita arayüzü düşünün. Hashmap'ın harita arayüzünü, atmadan, bir şeyleri yeniden canlandırmak zorunda olsa bile (ki bu da dicey alabilir) karşıladığından emin olmak istersiniz. Arabirim gereksinimlerini karşıladığından emin olmak için her girdi kombinasyonunu test edebilirsiniz, ancak bu evrenin ısı ölümünden daha uzun sürebilir. Bunun yerine, kapsüllemeyi biraz kırıyorsunuz ve daha sıkı etkileşime giren alaylar geliştiriyorsunuz, hashmap'ı, rehash algoritmasının atmadığından emin olmak için gereken rehash'ı tam olarak yapmaya zorluyorsunuz.

Tl / Dr: bunu "kitapla" yapmak güzel, ama itme kıpırdamaya geldiğinde, Cuma gününe kadar patronunuzun masasında bir ürün bulundurmak, kitapların ısı ölümüne kadar süren bir kitap içi test paketinden daha yararlıdır. uygunluğu doğrulamak için evren.

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.