Ünite değerlerini birim testleri kullanarak test etmeli mi?


15

Yalnızca değerlere sahip bir enum'unuz varsa (Java'da yapılabilecek yöntem yoktur) ve bu numaralandırma sistemin iş tanımının bir parçasıysa, bir birim bunu test etmeli mi?

Yazılmaları gerektiğini düşünüyordum, basit ve gereksiz görünseler bile, iş şartnamesi ile ilgili olan şeyin birim / entegrasyon / ui / vb. test yöntemi olarak veya dilin tip sistemini kullanarak test yöntemi olarak kullanılabilir. Bir enum'un (örneğin Java'da) sahip olması gereken değerler, işletme açısından, bunun için bir birim testi olması gerektiğini düşündüğüm tip sistemi kullanılarak test edilemediğinden.

Bu soru benzemiyor bu bir madene aynı sorunu çözmek olmadığından. Bu soruda bir iş fonksiyonu (savePeople) var ve kişi dahili uygulama (forEach) hakkında soru soruyor. Orada, dil yapısını (forEach) kapsayan orta bir iş katmanı (insanları kurtarmak işlevi) var. Burada dil yapısı (enum), bir iş açısından davranışı belirtmek için kullanılan dildir.

Bu durumda, uygulama ayrıntısı verilerin "gerçek doğası" ile örtüşür, yani: bir değer kümesi (matematiksel anlamda). Değişmez bir küme kullanabilirsiniz, ancak yine de aynı değerler orada bulunmalıdır. Bir dizi kullanırsanız, iş mantığını test etmek için aynı şey yapılmalıdır. Bence buradaki muamma, dil yapısının verilerin doğasıyla çok iyi örtüştüğü gerçeğidir. Kendimi doğru bir şekilde açıklayıp açıklamadığımdan emin değilim


19
Bir enumun birim testi tam olarak nasıl olurdu?
jonrsharpe


@jonrsharpe Numaralandırma içinde yer alan değerlerin beklediğiniz değer olduğunu iddia eder. Bunu, örneğin dizeler gibi bir kümeye ekleyerek, enum değerleri üzerinde yineleme yaparak yapardı. Bu seti sipariş edin. Testte elle yazılan sıralı değerler listesi ile karşılaştırılan karşılaştırma. Eşleşmelidirler.
IS1_SO

1
@jonrsharpe, Ben birim testleri de "tanımları" veya kodda yazılı "gereksinimleri" olarak düşünmek istiyorum. Bir enumun birim testi, enumdaki öğelerin sayısını ve değerlerini kontrol etmek kadar basit olacaktır. Özellikle, numaralandırmaların sınıf olmadığı, ancak tamsayılarla doğrudan eşleştirilebildiği, değerlerini garanti eden ve tesadüfen programlanamayan C # 'da serileştirme amaçları için yararlı olabilir.
Machado

2
IMHO, Evrenin doğru olup olmadığını kontrol etmek için 2 + 2 = 4 olup olmadığını test etmekten daha yararlı değildir. Kodu, numaralandırmanın kendisini değil, bu numaralandırmayı kullanarak test edersiniz.
Agent_L

Yanıtlar:


40

Yalnızca değerlere sahip bir enum'unuz varsa (Java'da yapılabilecek yöntem yoktur) ve bu numaralandırma sistemin iş tanımının bir parçasıysa, bir birim bunu test etmeli mi?

Hayır, onlar sadece devlet.

Temel olarak, bir numaralandırma kullandığınız bir uygulama detayıdır ; bu farklı bir tasarıma yeniden bakmak isteyebileceğiniz bir şey.

Numaraları eksiksizlik açısından test etmek, temsil edilebilir tam sayıların hepsinin mevcut olduğunu test etmeye benzer.

Bununla birlikte, numaralandırmaların desteklediği davranışları test etmek iyi bir fikirdir. Diğer bir deyişle, geçen bir test paketinden başlayıp herhangi bir tek enum değerini yorumluyorsanız, en az bir test başarısız olmalıdır (derleme hataları hata olarak kabul edilir).


5
Ancak bu durumda, uygulama ayrıntısı verilerin "gerçek doğası" ile örtüşür, yani: bir değer kümesi (matematiksel anlamda). Değişmez bir küme kullanabilirsiniz, ancak yine de aynı değerler orada bulunmalıdır. Bir dizi kullanırsanız, iş mantığını test etmek için aynı şey yapılmalıdır. Bence buradaki muamma, dil yapısının verilerin doğasıyla çok iyi örtüştüğü gerçeğidir. Kendimi doğru bir şekilde açıklayıp açıklamadığımı bilmiyorum.
IS1_SO

4
@ IS1_SO - VOU'nun bir testin başarısız olması gerektiği noktaya gelmesi: Bu durumda, Enum'u özel olarak test etmeniz gerekmez. Öyle değil mi? Belki daha basit kodunuzu modellemek ve veri 'gerçek doğası' üzerinde bir soyutlama yaratabileceği bir işareti olduğunu - örneğin bakılmaksızın bir destede kartlarının gerçekten bir temsilini olması gerekir yok, [ Hearts, Spades, Diamonds, Clubs] eğer hiç kart kırmızı / siyah ise hiç kart?
anotherdave

1
@ IS1_SO, enum hata kodlarına sahip olduğunuzu ve bir null_ptrhata atmak istediğinizi varsayalım . Şimdi numaralandırma yoluyla bir hata kodu var. Bir null_ptrhatayı kontrol eden kod , kodu numaralandırma yoluyla da arar. Yani 5(ex için) bir değeri olabilir . Şimdi başka bir hata kodu eklemeniz gerekiyor. Değiştirildiğinde enum değeri (biz enum üstüne yenisini eklemek Diyelim) null_ptrartık 6. Bu bir sorun mu? şimdi bir hata kodu 6döndürüp test edin 6. Her şey mantıksal olarak tutarlı olduğu sürece, bu değişikliğe rağmen teorik testinizi bozarsınız.
Baldrickk

17

Bir numaralandırma bildirimini test etmiyorsun . İşlev giriş / çıkışının beklenen numaralandırma değerlerine sahip olup olmadığını test edebilirsiniz. Misal:

enum Parity {
    Even,
    Odd
}

Parity GetParity(int x) { ... }

Sen yok ardından numaralandırma doğrulama testleri yazmak Paritytanımlarınızı isimleriEven ve Odd. Böyle bir test anlamsız olurdu, çünkü kodda belirtilenleri tekrarlıyorsunuz. Aynı şeyi iki kez söylemek daha doğru yapmaz.

Sen do yazma testleri doğrulayarak GetParitysöz dönecektirEven , 0 Odd1 ve benzeri için. Bu değerlidir çünkü kodu tekrarlamıyorsunuzdur, uygulamadan bağımsız olarak kodun davranışını doğrularsınız. İçindeki kod GetParitytamamen yeniden yazıldıysa, testler yine de geçerli olacaktır. Gerçekten de, birim testlerin en büyük faydaları, kodun beklendiği gibi çalışmasını sağlayarak, kodu güvenli bir şekilde yeniden yazma ve yeniden düzenleme özgürlüğü vermesidir.

Ancak, bir numaralandırma bildiriminin beklenen adları tanımlamasını sağlayan bir testiniz varsa , gelecekte numarada yapacağınız herhangi bir değişiklik, testi de değiştirmenizi gerektirir. Bu, sadece iki kat daha fazla çalışma olmadığı anlamına gelir, aynı zamanda ünite testinin herhangi bir faydasının kaybedildiği anlamına gelir. Kodu değiştirmek ve aynı anda test etmek zorunda kalırsanız, hatalara karşı koruma yoktur.


Bu yanıtı ele almak için sorumu güncelledim, yardımcı olup olmadığını kontrol edin.
IS1_SO

@ IS1_SO: Beni şaşırtan tamam - dinamik olarak numaralandırma değerleri mi oluşturuyorsunuz, ya da ne oluyor?
JacquesB

Hayır. Demek istediğim, bu durumda değerleri temsil etmek için seçilen dil yapısının bir enum olmasıdır. Ama bildiğimiz gibi bu bir uygulama detayı. Değerleri temsil etmek için bir dizi veya bir Set <> (Java'da) veya bazı ayırma jetonlu bir dize seçilirse ne olur? Bu durumda, içerilen değerlerin işletmeyi ilgilendiren değerler olduğunu test etmek mantıklı olacaktır. Demek istediğim bu. Bu açıklama yardımcı oluyor mu?
IS1_SO

3
@ IS1_SO: Bir işlevden döndürülen bir enum örneğinin belirli bir beklenen değere sahip olduğunu test etmekten mi bahsediyorsunuz? Çünkü evet bunu test edebilirsiniz. Numaralandırma bildiriminin kendisini test etmeniz gerekmez.
JacquesB

11

Numarayı değiştirmenin kodunuzu kırma riski varsa, C # [Flags] özniteliğine sahip herhangi bir şey iyi bir durum olacaktır, çünkü 2 ve 4 (3) arasında bir değer eklemek bir bit yerine 1 ve 2 bit olacaktır. gizli öğe.

Bu bir koruma katmanı.

Tüm geliştiricilerin aşina olduğu bir enum uygulama koduna sahip olmayı düşünmelisiniz. Numaralandırmanın metinsel temsillerine güvenmeyin, yaygındır, ancak bu serileştirme yönergelerinizle çakışabilir.

İnsanların enum girişlerinin büyük harf kullanımını "düzelttiğini" gördüm, bunları alfabetik olarak ya da diğer kötü mantık parçalarını bozan başka bir mantıksal gruplandırma ile sıraladım.


5
Numaralandırmanın sayısal değerleri, örneğin bir veritabanında depolandığında herhangi bir yerde kullanılırsa, yeniden sıralama (son değerden önce kaldırma veya ekleme dahil) mevcut kayıtların geçersiz olmasına neden olabilir.
stannius

3
+1, bu cevabın önemsiz olduğu görülüyor. Numaralandırmalarınız ya serileştirmenin, harici sözcük içeren giriş arabiriminin ya da bitsel olarak oluşturulabilir bilgilerin bir parçasıysa, kesinlikle sistemin her sürümünde tutarlılık açısından test edilmeleri gerekir. En azından geriye dönük uyumluluktan endişe ediyorsanız, bu genellikle iyi bir şeydir.
Machado

11

Hayır, bir enum'un tüm geçerli değerleri içerdiğini ve başka bir şey olmadığını kontrol eden bir test, enum'un bildirimini tekrarlıyor. Sadece dilin anlamsız bir test olan enum yapısını doğru bir şekilde uyguladığını test edersiniz.

Bununla birlikte, enum değerlerine bağlı davranışı test etmelisiniz. Örneğin, enum değerlerini varlıkları json'a veya herhangi bir şeye serileştirmek için kullanıyorsanız veya değerleri bir veritabanında saklıyorsanız, davranışı tüm numaralandırma değerleri için test etmelisiniz. Bu şekilde, enum değiştirilirse testlerden en az biri başarısız olmalıdır. Her durumda, test edeceğiniz şey, numaralandırma bildiriminin kendisi değil, numaralandırmanızın etrafındaki davranıştır.


3

Kodunuz bir numaralandırmanın gerçek değerlerinden bağımsız olarak doğru şekilde çalışıyor olmalıdır. Bu durumda, birim testlere gerek yoktur.

Ancak, bir enum değerini değiştirmenin bazı şeyleri kıracağı bir kodunuz olabilir. Örneğin, bir enum değeri harici bir dosyada depolanırsa ve enum değerini değiştirdikten sonra harici dosyayı okurken yanlış sonuç verir. Bu durumda, numaralandırma yakınında kimsenin herhangi bir değeri değiştirmemesi konusunda uyarması için BÜYÜK bir yorumunuz olacaktır ve sayısal değerleri kontrol eden bir birim testi yazabilirsiniz.


1

Genel olarak, sadece bir enum'un sabit kodlanmış bir değerler listesine sahip olup olmadığını kontrol etmek, diğer cevapların söylediği gibi çok değerli değildir, çünkü o zaman test ve numaralandırmayı birlikte güncellemeniz gerekir.

Bir zamanlar bir modülün diğer iki modülden numaralandırma türlerini kullandığı ve aralarında eşleştirdiği bir durum vardı. (Numaralandırmalardan birinin ek mantığı vardı, diğeri DB erişimi içindi, her ikisinin de birbirinden izole edilmesi gereken bağımlılıkları vardı.)

Bu durumda, kaynak numaralandırmadaki tüm numaralandırma girişlerinin hedef numarada da bulunduğunu (ve böylece eşlemenin her zaman çalışacağını) doğrulayan bir test (eşleme modülünde) ekledim. (Bazı durumlarda başka bir şekilde de kontrol ettim.)

Bu şekilde, birisi numaralardan birine numaralandırma girişi ekleyip karşılık gelen girişi diğerine eklemeyi unuttuğunda, bir test başarısız olmaya başladı.


1

Numaralandırmalar özel (umarım anlamlı) isimlerle sonlu türlerdir. Bir enum sadece gibi bir değere sahip olabilir voidancak içeren null(bazı diller diyoruz unitve adını kullanmak voidbir enum için hiçbir elementlerin!). Sanki iki değerlerine sahip olabilir boolsahip olduğu falseve true. Sanki, üç olabilir colourChannelile red, greenveblue . Ve bunun gibi.

İki numara aynı sayıda değere sahipse, bunlar "izomorfik" olur; yani tüm isimleri sistematik olarak değiştirirsek, birini diğerinin yerine kullanabiliriz ve programımız farklı davranmaz. Özellikle, testlerimiz farklı davranmayacak!

Örneğin, resultiçeren win/ lose/ drawYukarıdaki izomorftur colourChannelbiz örneğin yerine bu yana, colourChannelile result, redbirlikte win, greenile loseve blueile drawsürece biz bunu olarak ve her yerde (üretici ve tüketiciler, ayrıştırıcılar ve serialisers, veritabanı girdileri, günlük dosyaları, vb ) programımızda değişiklik olmayacaktır. Yazmış colourChannelolduğumuz tüm " testler",colourChannel !

Ayrıca, bir enum birden fazla değer içeriyorsa , aynı sayıda değer içeren yeni bir enum almak için bu değerleri her zaman yeniden düzenleyebiliriz . Değerlerin sayısı değişmedi yana, yeni düzenleme eskisinin izomorftur ve (not dolayısıyla biz tüm isimlerini geçiş olabilir ve bizim testleri hala geçerdi biz yapamaz sadece tanımını dışarı geçiş; yapmalıysak yine de tüm kullanım sitelerini kapat).

Bunun anlamı, makine söz konusu olduğunda, sıralamalar "ayırt edilebilir isimler" ve başka bir şey değildir . Bir enum ile yapabileceğimiz tek şey, iki değerin aynı (ör. red/ red) Veya farklı (ör. red/ blue) Olup olmadığı konusunda dallanmaktır . Bu yüzden, 'birim testinin' yapabileceği tek şey bu, örn.

(  red == red  ) || throw TestFailure;
(green == green) || throw TestFailure;
( blue == blue ) || throw TestFailure;
(  red != green) || throw TestFailure;
(  red != blue ) || throw TestFailure;
...

@ Jesm00'ün dediği gibi, böyle bir test programınızdan ziyade dil uygulamasını kontrol ediyor . Bu testler asla iyi bir fikir değildir: dil uygulamasına güvenmiyorsanız bile dışarıdan test etmelisiniz , çünkü testleri doğru bir şekilde çalıştırmak güvenilir değildir!

Bu teori; uygulama ne olacak? Enumların bu karakterizasyonu ile ilgili ana sorun, 'gerçek dünya' programlarının nadiren kendi içinde kalmasıdır: eski sürümlerimiz, uzak / gömülü dağıtımlarımız, geçmiş veriler, yedeklemeler, canlı veritabanları vb. bazı kullanımlar eksik olmadan bir adın tüm oluşumları.

Oysa böyle şeyler enum kendisinin 'sorumluluk' değildir: Uzak bir sistem ile iletişimi bozabilir Bir enum değişen, ama tersine biz olabilir düzeltmek böyle bir sorunu bir enum değiştirerek !

Bir sistem olması gerekenden ne olur: Bu senaryolarda, enum kırmızı-ringa olan bu yolu, başka olması ihtiyacı olduğunu yolu? Kaç tane test yazdığımız önemli değil, her ikisi de olamaz! Buradaki asıl suçlu, "yorumlama seçimlerini tam olarak ne olursa olsun" yerine iyi tanımlanmış formatlar üretmesi / tüketmesi gereken giriş / çıkış arayüzüdür. Bu nedenle asıl çözüm, i / o arayüzlerini test etmektir : beklenen formatı ayrıştırdığını / yazdırdığını kontrol etmek için birim testleri ve formatın diğer taraf tarafından gerçekten kabul edildiğini kontrol etmek için entegrasyon testleri ile.

Hala enumun 'yeterince iyi egzersiz yapıp yapmadığını' merak edebiliriz, ancak bu durumda enum yine kırmızı bir ringa balığıdır. Aslında endişelendiğimiz şey test paketinin kendisidir . Burada birkaç yolla güven kazanabiliriz:

  • Kod kapsamı, test paketinden gelen çeşitli numaralandırma değerlerinin koddaki çeşitli dalları tetiklemek için yeterli olup olmadığını bize söyleyebilir. Değilse, ortaya çıkarılan dalları tetikleyen testler ekleyebilir veya mevcut testlerde daha çeşitli numaralar oluşturabiliriz.
  • Mülk denetimi, koddaki dal çeşitliliğinin çalışma zamanı olanaklarını işlemek için yeterli olup olmadığını bize söyleyebilir. Örneğin, kod yalnızca işliyorsa redve yalnızca test yapıyorsak, red% 100 kapsama alanımız vardır. Bir özellik denetleyicisi, testlerimizi unuttuğumuz değerler greenve bluedeğerler üretme gibi iddialarımıza karşı örnekler üretmeye çalışacaktır .
  • Mutasyon testi bize iddialarımızın sadece dalları takip etmek ve farklılıklarını görmezden gelmek yerine, enümü gerçekten kontrol edip etmediğini söyleyebilir .

1

Hayır. Birim testleri, test birimleri içindir.

Nesne yönelimli programlamada, ünite genellikle sınıf gibi bütün bir arayüzdür, ancak bireysel bir yöntem olabilir.

https://en.wikipedia.org/wiki/Unit_testing

Bildirilen bir numaralandırma için otomatik bir test, geliştiricinin yazdığı kodda mantık yerine dilin ve üzerinde çalıştığı platformun bütünlüğünü test eder. Yararlı bir amaca hizmet etmeyecektir - enum'u bildiren kod, aynı zamanda onu test edecek kodun yanı sıra dokümantasyon olarak da hizmet ettiğinden dokümantasyon dahil edilmiştir.


0

Kodunuzun gözlemlenebilir davranışını, yöntem / işlev çağrılarının gözlemlenebilir durum üzerindeki etkilerini test etmeniz beklenir. Kod doğru olanı yaptığında, başka bir şey test etmeniz gerekmez.

Bir enum türünün beklediğiniz girişlere sahip olduğunu açıkça belirtmeniz gerekmez, tıpkı bir sınıfın gerçekten var olduğunu veya beklediğiniz yöntemlere ve niteliklere sahip olduğunu açıkça iddia etmediğiniz gibi.

Aslında, davranışı test ederek, sınava dahil olan sınıfların, yöntemlerin ve değerlerin var olduğunu dolaylı olarak iddia edersiniz, bu nedenle bunu açıkça belirtmeniz gerekmez.

Doğru şeyi yapmak için kodunuz için anlamlı isimlere ihtiyacınız olmadığını unutmayın, bu sadece kodunuzu okuyan insanlar için bir kolaylıktır. Kodunuzun foo, bar... ve gibi yöntemler gibi enum değerleri ile çalışmasını sağlayabilirsiniz frobnicate().

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.