Java 8 kodu için koşullu kapsamı ölçmek anlamlı mı?


19

Java 8 için geçerli araçlarla koşullu kod kapsamının ölçülmesinin geçersiz olup olmadığını merak ediyorum. Java 8'lerle Optionalve Streamçoğu zaman kod dallarından / döngülerden kaçınabiliriz, bu da tüm olası yürütme yollarını test etmeden çok yüksek koşullu kapsama alanı almayı kolaylaştırır. Eski Java kodunu Java 8 koduyla karşılaştıralım:

Java 8'den önce:

public String getName(User user) {
    if (user != null) {
        if (user.getName() != null) {
            return user.getName();
        }
    }
    return "unknown";
}

Yukarıdaki yöntemde 3 olası yürütme yolu vardır. Şartlı kapsamın% 100'ünü elde etmek için 3 birim test oluşturmamız gerekiyor.

Java 8:

public String getName(User user) {
    return Optional.ofNullable(user)
                   .map(User::getName)
                   .orElse("unknown");
}

Bu durumda, dallar gizlidir ve% 100 kapsama almak için sadece 1 teste ihtiyacımız var ve hangi durumda test edeceğimiz önemli değil. Yine de ele alınması gereken aynı 3 mantıksal dal olmasına rağmen inanıyorum. Bugünlerde koşullu kapsama istatistiklerinin tamamen güvenilmez hale geldiğini düşünüyorum.

Java 8 kodu için koşullu kapsamı ölçmek anlamlı mı? Test edilmemiş kodu tespit eden başka araçlar var mı?


5
Kapsama ölçümlerini asla kodunuzu, ne olduğunu belirlemek için sadece bir yol iyi yapılmasıdır olup olmadığını belirlemek için iyi bir yol olmuştur olmamıştır sınanmıştır. İyi bir geliştirici zihnindeki çeşitli vakaları düşünecek ve hepsi için ya da en azından önemli olduğunu düşündüğü tüm testler yapacak.
kdgregory

3
Elbette yüksek koşullu kapsam, iyi testlerimiz olduğu anlamına gelmez, ancak hangi yürütme yollarının ortaya çıktığını bilmek BÜYÜK avantaj olduğunu ve sorunun çoğunlukla bununla ilgili olduğunu düşünüyorum. Koşullu kapsam olmadan test edilmemiş senaryoları tespit etmek çok daha zordur. Yollarla ilgili: [kullanıcı: null], [kullanıcı: notnull, kullanıcı.adı:null], [kullanıcı: notnull, kullanıcı.adı: notnull]. Ne eksik?
Karol Lewandowski

6
Kontrat nedir getName? Görünüşe göre usernull olursa , "bilinmeyen" dönmelidir. Eğer userboş değil ve user.getName()null, bu "bilinmeyeni" dönmelidir. Eğer userboş değil ve user.getName()boş değil, o dönmelidir. Yani bu üç vakayı birim olarak test edersiniz çünkü sözleşmenin konusu getNamebudur. Geriye doğru yapıyor gibisin. Şubeleri görmek ve testleri bunlara göre yazmak istemiyorsunuz, testlerinizi sözleşmenize göre yazmak ve sözleşmenin eksiksiz olarak doldurulmasını istiyorsunuz. O zaman iyi bir kapsama sahip olursunuz.
Vincent Savard

1
Yine, kapsama kodumun mükemmel bir şekilde test edildiğini kanıtladığını söylemiyorum, ama kesin olarak test etmediğimi gösteren son derece değerli bir araçtı. Test sözleşmelerinin, yürütme yollarını test etmekten ayrılmaz olduğunu düşünüyorum (örneğin, örtük dil mekanizmasını içerdiği için örneğiniz olağanüstü). Yolu test etmediyseniz, sözleşmeyi tam olarak test etmediniz veya sözleşme tam olarak tanımlanmadı.
Karol Lewandowski

2
Var: Ben daha önce noktayı tekrar edeceğim hep sadece temel dil özelliklerine kendinizi sınırlamak sürece, vaka ve aletli edilmemiştir herhangi bir işlev hiç aramıyorsun. Bu, üçüncü taraf kütüphaneleri ve SDK'nın kullanılmaması anlamına gelir.
kdgregory

Yanıtlar:


4

Java 8'de oluşturulabilecek mantıksal dalları ölçen herhangi bir araç var mı?

Hiçbirinin farkında değilim. Emin olmak için JaCoCo (aka EclEmma) üzerinden sahip olduğunuz kodu çalıştırmayı denedim, ancak Optionalsürümde 0 şube gösteriyor . Başka türlü söylemek için yapılandırmanın herhangi bir yöntemini bilmiyorum. JDK dosyalarını da içerecek şekilde yapılandırdıysanız, teorik olarak dalları gösterir Optional, ancak JDK kodunu doğrulamaya başlamanın saçma olacağını düşünüyorum. Sadece doğru olduğunu varsaymalısınız.

Bence asıl sorun, Java 8'den önce sahip olduğunuz ek dalların bir anlamda yapay olarak yaratılmış dallar olduğunun farkında olmaktır. Artık Java 8'de mevcut olmamaları, artık iş için doğru araca sahip olduğunuz anlamına gelir (bu durumda Optional). Java 8 öncesi kodda, her bir kod dalının kabul edilebilir bir şekilde davrandığından emin olabilmeniz için fazladan birim testleri yazmanız gerekiyordu ve bu, User/ gibi önemli olmayan kod bölümlerinde biraz daha önemli oluyor getNamemisal.

Java 8 kodunda, kodun düzgün çalıştığına dair JDK'ya güveniyorsunuz. Olduğu gibi, bu Optionalsatırı kod kapsama araçları gibi davranmalıdır: 0 dallı 3 satır. Aşağıdaki kodda başka çizgiler ve dallar olması, daha önce dikkat etmediğiniz bir şeydir, ancak her zaman bir ArrayListveya gibi bir şey kullandığınızda var olmuştur HashMap.


2
"Artık ... Java 8 var That" - Java 8 geriye uyumlu, onunla kabul edemez ve ifve nullyine dilin parçalarıdır ;-) Eski bir şekilde ve geçmek yazma koduna hala mümkündür nullkullanıcı veya kullanıcı nulladı. Testleriniz, yöntemin nasıl uygulandığına bakılmaksızın sözleşmenin yerine getirildiğini kanıtlamalıdır. Mesele şu ki, sözleşmeyi tamamen test edip etmediğinizi size söyleyecek bir araç yoktur.
Karol Lewandowski

1
@KarolLewandowski Sanırım Shaz'ın söylediği şey, Optional(ve ilgili yöntemlerin) nasıl çalıştığına güveniyorsanız , artık onları test etmek zorunda kalmamanızdır . Test ettiğiniz gibi değil if-else: her ifbiri potansiyel bir mayın tarlasıydı. Optionalve benzer işlevsel deyimler zaten kodlanmış ve sizi atlatmayacağınızı garanti ediyor, bu yüzden esasen yok olan bir "dal" var.
Andres F.

1
@AndresF. Karol'ın test etmemizi önerdiğini sanmıyorum Optional. Dediği gibi, mantıksal getName()olarak, uygulanmasına bakılmaksızın, çeşitli olası girdileri istediğimiz şekilde işlediğini test etmeliyiz . JDK8 öncesi gibi yardımcı olacak kod kapsama araçları olmadan bunu belirlemek daha zordur.
Mike Partridge

1
@MikePartridge Evet, ama önemli olan bunun şube kapsamı ile yapılmaması. Yazarken şube kapsamı gereklidir, if-elseçünkü bu yapıların her biri tamamen ad hoctur. Buna karşılık, Optional, orElse, map, vs, tüm zaten test edilir. Aslında daha güçlü deyimler kullandığınızda dallar "yok olur".
Andres F.
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.