Alay nedir?


Yanıtlar:


598

Prolog: Eğer sözlükte isim alayına bakarsanız , kelimenin tanımlarından birinin taklit olarak yapılmış bir şey olduğunu göreceksiniz .


Alaycı öncelikle birim testlerinde kullanılır. Test edilen bir nesnenin diğer (karmaşık) nesnelere bağımlılıkları olabilir. Nesnenin davranışını yalıtmak için, diğer nesnelerin yerine, gerçek nesnelerin davranışını taklit eden taklitlerle geçin. Bu, gerçek nesnelerin birim testine dahil edilmesi pratik değilse faydalıdır.

Kısacası, alay etmek gerçek nesnelerin davranışını simüle eden nesneler yaratmaktır.


Bazen alay yerine aksine alay arasında ayrım yapmak isteyebilirsiniz . Bu konuda bazı anlaşmazlıklar olabilir, ancak saplama tanımım "minimal" simüle edilmiş bir nesnedir. Saplama, test edilen nesnenin testi yürütmesine izin vermek için yeterli davranışı uygular.

Sahte bir saplama gibidir, ancak test ayrıca test altındaki nesnenin sahte olarak beklendiği gibi çağırdığını doğrular. Testin bir kısmı alayın doğru kullanıldığını doğrulamaktır.

Örnek vermek için: Kayıtları saklamak için basit bir bellek içi yapı uygulayarak bir veritabanını saplayabilirsiniz. Test edilen nesne daha sonra testi yürütmesine izin vermek için veritabanı saplamasına kayıtları okuyabilir ve yazabilir. Bu, veritabanıyla ilgili olmayan nesnenin bazı davranışlarını test edebilir ve sadece testin çalışmasına izin vermek için veritabanı saplaması eklenir.

Bunun yerine, test edilen nesnenin veritabanına belirli veriler yazdığını doğrulamak istiyorsanız, veritabanını taklit etmeniz gerekir. Testiniz, daha sonra veritabanı modeline yazılanlarla ilgili iddiaları içerecektir.


18
Bu iyi bir cevap, ama gereksiz yere nesnelere alay kavramını kısıtlıyor . "Nesne" yi "birim" ile değiştirmek onu daha genel hale getirir.
Rogério

1
Saplama ve sahte arasındaki farkı anlıyorum. Tek şey şu ki, vakalarınızı bir saplama ile test ediyorsanız ve geçerse, saplamayı zaten kullandığınıza karar veremezsiniz, bu nedenle artık doğrulamaya ihtiyacınız yoktur ?
Bal

91

Diğer cevaplar alaycılığın ne olduğunu açıklar. Size farklı örneklerle göz gezdireyim . Ve inan bana, aslında düşündüğünden çok daha basit.

tl; dr Orijinal sınıfın bir örneğidir. İçine enjekte edilen başka veriler de vardır, böylece enjekte edilen parçaları test etmekten kaçınır ve yalnızca sınıfınızın / işlevlerinizin uygulama ayrıntılarını test etmeye odaklanırsınız .

Basit bir örnek:

class Foo {
    func add (num1: Int, num2: Int) -> Int { // Line A 
        return num1 + num2 // Line B
    }
}

let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)

Gördüğünüz gibi, LineA'yı test etmiyorum yani giriş parametrelerini doğrulamıyorum. Num1, num2'nin bir Tamsayı olup olmadığını görmek için doğrulama yapmıyorum. Buna karşı hiçbir iddiam yok.

Sadece LineB (benim uygulama ) alaycı değerleri verilen 1ve 5beklediğim gibi yapıyor olup olmadığını görmek için test ediyorum.

Açıkçası gerçek kelimeyle bu çok daha karmaşık hale gelebilir. Parametreler Kişi, Adres gibi özel bir nesne olabilir veya uygulama ayrıntıları tek bir değerden fazla olabilir +. Ancak test mantığı aynı olurdu.

Kodlama yapmayan Örnek:

Havaalanı güvenliği için elektronik cihazların türünü ve marka adını tanımlayan bir makine yaptığınızı varsayın. Makine bunu, kamerasıyla gördüklerini işleyerek yapar.

Şimdi yöneticiniz kapıya giriyor ve sizden birim test etmenizi istiyor.

Daha sonra bir geliştirici olarak ya bir MacBook pro, Google Nexus, bir muz, bir iPad vb.Gibi 1000 gerçek nesneyi getirebilir ve hepsinin işe yarayıp yaramadığını test edip görebilirsiniz.

Ancak aynı görünümlü MacBook pro (gerçek dahili parçaları olmayan) veya önünde plastik bir muz gibi alaycı nesneleri de kullanabilirsiniz . Kendinizi 1000 gerçek dizüstü bilgisayara ve çürüyen muzlara yatırım yapmaktan kurtarabilirsiniz.

Mesele şu ki, muzun sahte olup olmadığını test etmeye çalışmıyorsunuz. Ne de dizüstü sahte olup olmadığını test. Eğer makine bir muz görür kez söyleyebilirim eğer test ediyor yapıyoruz Bütün not an electronic devicebir MacBook için söyleyebilirim Pro: Laptop, Apple. Makineye göre, tespitinin sonucu sahte / alaylı elektronikler ve gerçek elektronikler için aynı olmalıdır

Yukarıda belirtilen mantık, gerçek kodun birim testi için de geçerlidir. Bu, gerçek girdiden (ve etkileşimlerden) aldığınız veya alay edilen gerçek değerlerle aynı şekilde çalışması gereken bir işlevdirbirim testi sırasında enjekte ettiğiniz değerler. Ve tıpkı gerçek bir muz veya MacBook'u kullanmaktan nasıl kurtulacağınız gibi, birim testleri (ve alaycı) ile, sunucunuzun 500, 403, 200, vb. Durum kodunu döndürmesine neden olan bir şey yapmak zorunda kalmamanızı sağlar (zorlama) sunucunuzu 500 tetiklemek için sadece sunucu kapalı iken, 200 sunucu açıkken. 100 üzerinden ağa geçiş testi yapmak zorlaşır, eğer sunucu arasında yukarı ve aşağı geçiş arasında 10 saniye beklemek zorunda kalırsanız). Bunun yerine, durum kodu 500, 200, 403 vb. İle bir yanıt enjekte eder / alay edersiniz ve ünitenizi / fonksiyonunuzu enjekte edilmiş / alay edilmiş bir değerle test edersiniz.

Kodlama Örneği:

Diyelim ki bir iOS uygulaması yazıyorsunuz ve şebeke çağrılarınız var . İşiniz uygulamanızı test etmektir . Şebeke çağrılarının beklendiği gibi çalışıp çalışmadığını test etmek / tanımlamak SORUMLULUĞUNUZ DEĞİLDİR. Bunu test etmek başka bir tarafın (sunucu ekibi) sorumluluğundadır. Bunu (ağ) bağımlılığı kaldırın ve henüz tüm kodunuzu test devam etmeliyiz eserler olduğu etrafında ona.

Bir şebeke çağrısı, JSON yanıtıyla farklı durum kodları 404, 500, 200, 303 vb.

Uygulamanızın hepsi için çalışması gerekiyor (hata durumunda uygulamanız beklenen hatayı atmalıdır). Ne alay ile ilgisi oluşturup (bir JSON dosyası ile 200 kodu gibi) ağ yanıtları 'gerçek için hayali-benzer' ve kodunuzu test etmeden 'gerçek ağ arama yapmadan ve ağ yanıt bekliyor'. TÜM ağ yanıtları için ağ yanıtını elle sabitler / döndürür ve uygulamanızın beklediğiniz gibi çalışıp çalışmadığını görürsünüz. ( 200'ü asla yanlış verilerle varsaymazsınız / test etmezsiniz, çünkü bu sizin sorumluluğunuz değildir, sorumluluğunuz uygulamanızı doğru bir 200 ile test etmek veya 400, 500 olması durumunda, uygulamanızın doğru hatayı atıp atmadığını test etmektir)

Hayali yaratan bu - gerçeğe benzer şekilde alaycı olarak bilinir.

Bunu yapmak için, sen olamaz (orijinal kod doğru, önceden takılı yanıtları yok?) Orijinal kodu kullanabilirsiniz. Bir şey eklemeniz, normalde gerekli olmayan (veya sınıfınızın bir parçası) o sahte verileri enjekte etmeli / eklemelisiniz.

Böylece, özgün sınıfın bir örneğini oluşturur ve her şeyi eklersiniz (burada ağ HTTPResponse, veri olarak VEYA hata durumunda, buna ihtiyacınız olan doğru errorString, HTTPResponse'yi geçirirsiniz) ve alaycı sınıfı test edersiniz .

Uzun lafın kısası, alay etmek , test ettiğiniz şeyi basitleştirmek ve sınırlamak ve ayrıca bir sınıfın neye bağlı olduğunu beslemenizi sağlamaktır. Bu örnekte , ağ çağrılarını kendileri test etmekten kaçının ve bunun yerine uygulamanızın enjekte edilen çıktılar / yanıtlarla beklediğiniz gibi çalışıp çalışmadığını test edin— Photo by mocking classes

Söylemeye gerek yok, her bir ağ yanıtını ayrı ayrı test ediyorsunuz.


Şimdi her zaman aklımda olan bir soru şuydu: Sözleşmeler / bitiş noktaları ve temelde API'larımın JSON yanıtı sürekli olarak güncelleniyor. Bunu dikkate alan birim testlerini nasıl yazabilirim?

Bu konuyla ilgili daha ayrıntılı bilgi için: diyelim ki model adında bir anahtar / alan gerektiriyor username. Bunu test edersiniz ve testiniz geçer. 2 hafta sonra arka uç anahtarın adını değiştirir id. Testleriniz hala geçiyor. sağ? ya da değil?

Alayları güncellemek arka uç geliştiricinin sorumluluğundadır. Güncellenmiş takılar sağlamaları anlaşmamızın bir parçası olmalı mı?

Yukarıdaki sorunun cevabı şudur: birim testleri + istemci tarafı geliştirici olarak geliştirme süreciniz güncel olmayan sahte yanıtları yakalamalı / yakalamalıdır. Bana nasıl olduğunu sorarsan? iyi cevap:

Gerçek uygulamamız güncellenmiş API'ları kullanmadan başarısız olur (veya başarısız olmaz, ancak istenen davranışa sahip değildir) ... bu nedenle başarısız olursa ... geliştirme kodumuzda değişiklikler yapacağız. Bu da testlerimizin başarısız olmasına yol açar .... ki bunu düzeltmek zorundayız. (Aslında, TDD işlemini doğru bir şekilde yapacaksak, testini yazmadıkça alan hakkında herhangi bir kod yazmamalıyız ... ve başarısız olduğunu görüp gidip bunun için gerçek geliştirme kodunu yazıyoruz.)

Bu, arka ucun "hey alayları güncelledik" demek zorunda olmadığı anlamına gelir ... sonunda kod geliştirme / hata ayıklama yoluyla gerçekleşir. ‌ّ Çünkü hepsi geliştirme sürecinin bir parçası! Arka uç sizin için alaycı yanıt sağlıyorsa daha kolaydır.

Bütün mesele şu ki (güncellenmiş alaycı API yanıtı almayı otomatikleştiremiyorsanız) bazı insan etkileşimi gereklidir, yani JSON'ların manuel güncellemeleri ve değerlerinin güncel olduğundan emin olmak için kısa toplantılar yapmanız sürecinizin bir parçası olacaktır.

Bu bölüm CocoaHead buluşma grubumuzdaki tartışmalar sayesinde yazılmıştır.


Yalnızca iOS geliştiricileri için:

Alaycılığa çok güzel bir örnek, Natasha Muraschev'in Pratik Protokol Odaklı konuşmasıdır . Slaytlar gerçek videoyla senkronize olmayabilir, ancak 18:30 dakikaya atlayın 🤷‍♂️

Ben transkript bu kısmı gerçekten seviyorum:

Bu test olduğu için ... getişlevin Gettableçağrıldığından emin olmak istiyoruz , çünkü geri dönebilir ve fonksiyon teorik olarak her yerden bir dizi gıda öğesi atayabilir . Arandığından emin olmalıyız;


3
Harika bir örnek, sadece bu belirli örnekte alt sınıfın sahte olarak davrandığını ekleyeceğim, ancak bu örnek de stubbing kullanıyor. Sabit kodlanmış JSON yanıtları, anız yanıtlar olarak kabul edilir. Bunu sadece ekliyorum çünkü alaylarla taslakları ayırt etmek zor olabilir, ancak bu örnek her ikisinin birlikte nasıl kullanılabileceğini açıkça göstermektedir.
user3344977

Mükemmel açıklama, teşekkür ederim. API değiştirme ile ilgili soruya küçük bir değişiklik. Ya API'nız değilse geliştirme sürecinin bir parçası değilseniz? İstemci kitaplığımın ne zaman başarısız olduğunu bilmek istiyorum.
ThinkDigital

@ThinkDigital İyi API sağlayıcıları iyi sürüm notlarına sahiptir ve değişiklikleri düzgün bir şekilde iletir, eğer o kanala sahip değilseniz, belki de bir toplantıda oturmak ve tartışmak için zamanı gelmiştir | iyi geliştiriciler her zaman yeni bir sürümün API değişikliklerini inceleyecek ve yalnızca API sürümünü yükseltmekten kaçınacaktır. API sürümleriniz var mı? Bunlardan hiçbiri onu yakalayamazsa, QAing'i öğrendikten sonra testlerinizi ← tüm ekibin görevini güncelleyin. → tek bir dev görev: çok umursamamalı. Sunucunun hata döndürdüğü veya sunucunun hata döndürmediği ancak json ayrıştırılamadığı veya doğru büyük / küçük harf işlenmediği durumu ele almanız yeterlidir.
Bal

Yanıt verdiğiniz için teşekkürler, @Honey! Benim durumumda, bir API olan pub.dev için bir istemci tutuyorum , ancak ciddi şekilde eksik. Öyle ki, sitelerini kazıyarak bir API yapmak, resmi API'larını kullanmaktan daha iyi oldu. Bu nedenle, sitedeki değişiklikler kodu kırabilir ve bu durumda kimsenin güncellenmesini zahmetine gerek yoktur. Site açık kaynaklıdır, ancak daha önemsiz bir temelde yapılan değişikliklere dayanan bir API'yi korumak farklı bir şeydir.
ThinkDigital

32

Alay ve internette alay konusunda iyi mesajlar bolca cevap var. Bakmaya başlamak isteyebileceğiniz bir yer, Martin Fowler Mocks Arub Stubs'un alay fikirlerini tartıştığı bir yazı .

Bir paragrafta - Alay etme, bir kod biriminin bağımlılıklara bağımlı olmadan test edilmesine izin veren tek bir tekniktir. Genel olarak, alay etmeyi diğer yöntemlerden ayıran şey, kod bağımlılıklarını değiştirmek için kullanılan sahte nesnelerin beklentilerin ayarlanmasına izin vermesidir.


Orijinal sorunuz TypeMock'tan bahsetti, bu yüzden cevabımı aşağıda bıraktım:

TypeMock, ticari bir alaycı çerçevenin adıdır .

RhinoMocks ve Moq gibi ücretsiz alaycı çerçevelerin tüm özelliklerinin yanı sıra bazı daha güçlü seçenekler sunar.

İster TypeMock'a ihtiyacınız olsun ya da olmasın, oldukça tartışmalıdır - ücretsiz alay kütüphaneleri ile istediğiniz her şeyi alay edebilirsiniz ve birçoğu TypeMock tarafından sunulan yeteneklerin sizi iyi kapsüllenmiş tasarımdan uzaklaştıracağını iddia eder.

Başka bir cevap olarak 'TypeMocking' aslında tanımlanmış bir kavram değildir, ancak TypeMock'un sahte nesnelere çok daha fazla yetenek vererek (gereklilikler değil) çalışma zamanında. arayüzlere veya sanal yöntemlere ihtiyaç duyulması gibi).


@Masoud, TypeMock'tan hiç bahsetmedi. Sorusu genel olarak "tip alaycı" idi.
Peter Lillevold

4
@Peter - başka bir yorumun söylediği gibi, sorunun düzenleme geçmişini kontrol edin. Bir cevap gönderirsem ve sonra orijinal soru tamamen değiştirilirse yapabileceğim çok şey değil.
David Hall

9

Mock, gerçek bir yöntemin / nesnenin davranışını kontrollü bir şekilde simüle eden bir yöntem / nesnedir. Sahte nesneler birim testinde kullanılır.

Genellikle test altındaki bir yöntem, içindeki diğer harici hizmetleri veya yöntemleri çağırır. Bunlara bağımlılıklar denir. Alay edildikten sonra, bağımlılıklar onları tanımladığımız şekilde davranır.

Bağımlılıklar alaylarla kontrol edildiğinde, kodladığımız yöntemin davranışını kolayca test edebiliriz. Bu Birim testi.

Sahte nesnelerin amacı nedir?

Taklitler vs taslakları

Birim testleri ve İşlevsel testler


7

Mocking, testler için gerçek nesnelerin davranışını simüle eden sözde nesneler üretiyor


5

Alaycı tiplerin amacı, testi belirli bir birime izole etmek için bağımlılıkları koparmaktır. Saplamalar basit taşıyıcılardır, alaylar ise kullanımı doğrulayabilen taşıyıcılardır. Alaycı çerçeve, taslaklar ve alaylar oluşturmanıza yardımcı olacak bir araçtır.

EDIT : Orijinal ifade "tip alaycı" söz beri bunun TypeMock ile ilgili bir izlenim var. Deneyimlerime göre genel terim sadece "alay ediyor". Lütfen aşağıdaki bilgileri özellikle TypeMock'ta dikkate almayın.

TypeMock İzolatör, değiştiren IL'mi anında çalıştırması bakımından diğer çoğu alaycı çerçeveden farklıdır. Bu, diğer çoğu çerçevenin alay edemediği türleri ve örnekleri alay etmesini sağlar. Bu türleri / örnekleri diğer çerçevelerle alay etmek için kendi soyutlamalarınızı sunmalı ve bunları alay etmelisiniz.

TypeMock, temiz bir çalışma zamanı ortamı pahasına büyük esneklik sunar. TypeMock'un sonuçlarına ulaşmasının bir yan etkisi olarak, TypeMock'u kullanırken bazen çok garip sonuçlar elde edersiniz.


@Masoud, TypeMock'tan hiç bahsetmedi. Sorusu genel olarak "tip alaycı" idi.
Peter Lillevold

1
@Peter: Orijinal ifade "tip alaycı nedir?"
Brian Rasmussen

Biliyorum. "Type mocking", "TypeMock" ile eşdeğer olmadığından, hem sizinkini hem de @Oded cevabını işaretin dışında buluyorum.
Peter Lillevold

1
@Peter: Deneyimlerime göre genel terim "alay ediyor", ancak her halükarda, bunu umarım netleştirmek için cevabımı güncelledim. Giriş için teşekkürler.
Brian Rasmussen

3

TypeMock izolatör alaycı çerçeve kullanımı TypeMocking olacağını düşünürdüm.

Kodunuzu IoC ile aklınızda tutmanıza gerek kalmadan, birim testlerde kullanmak için alay üreten bir araçtır.


@Masoud, TypeMock'tan hiç bahsetmedi. Sorusu genel olarak "tip alaycı" idi.
Peter Lillevold

3
Aslında, asıl soru "Alay Etmeden" önce "Tür" kelimesini içeriyordu, ancak daha sonra düzenlendi. Bu nedenle bazı cevaplar TypeMock hakkında özel bilgiler içermektedir.
Martin Liversage

1

Sahte bir ağ isteği içeriyorsa, başka bir alternatif vurmak için gerçek bir test sunucusuna sahip olmaktır. Bu hizmeti, testiniz için bir istek ve yanıt oluşturmak için kullanabilirsiniz. http://testerurl.com/


Sadece erişmeye çalıştım ve birkaç dakika sürdü. Kim de gizlice istekleri günlüğe kaydetmediğini söyleyebilir? Son olarak, bu bir yorum olarak daha iyi olabilir :)
Kieren Johnstone

Aslında ücretsiz bir barındırma taşımak gibi hissetmedim çünkü aşağı aldı. evet, bu bir yorum olmalıydı. açık kaynak kodlu olduğundan, günlük kaydı istekleriyle ilgili bir endişeniz varsa, kendiniz çalıştırabilirsiniz. github.com/captainchung/TesterUrl
Matthew Chung
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.