Java 8コードの条件付きカバレッジを測定するのは理にかなっていますか?


19

Java 8が登場して以来、現在のJava用ツールによる条件付きコードカバレッジの測定は時代遅れではないのかと思っています。Javaの8のではOptionalStream私たちはしばしば、それが簡単にすべての可能な実行パスをテストすることなく、非常に高い条件カバレッジを取得することができますコード分岐/ループを回避することができます。古いJavaコードとJava 8コードを比較してみましょう。

Java 8より前:

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

上記のメソッドには3つの実行パスがあります。条件付きカバレッジを100%取得するには、3つの単体テストを作成する必要があります。

Java 8:

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

この場合、ブランチは非表示になり、100%のカバレッジを得るために必要なテストは1つだけで、テストするケースは関係ありません。カバーすべき3つの論理ブランチはまだありますが、信じています。最近の条件付きカバレッジ統計は完全に信頼できないものになっていると思います。

Java 8コードの条件付きカバレッジを測定するのは理にかなっていますか?十分にテストされていないコードを発見する他のツールはありますか?


5
カバレッジ指標はしている決してあなたのコードは、どのような決定するために、単に方法十分にテストされているかどうかを判断するための良い方法ではありませんしていないテストされています。優れた開発者は、心の中のさまざまなケースを熟考し、それらすべて、または少なくとも彼女が重要だと思うすべてのテストを考案します。
kdgregory 16

3
もちろん、条件付きカバレッジが高いということは、良いテストがあるということではありませんが、どの実行パスが発見されたかを知ることは大きな利点だと思います。これが問題の大部分です。条件付きカバレッジがなければ、テストされていないシナリオを見つけるのははるかに困難です。パスに関して:[user:null]、[user:notnull、user.name:null]、[user:notnull、user.name:notnull]。私は何が欠けていますか?
カロルルワンドフスキ

6
の契約はgetName何ですか?usernullの場合、「不明」を返す必要があるようです。usernullでなくnullの場合user.getName()、「不明」を返す必要があります。useruser.getName()nullではなく、nullではない場合、それを返す必要があります。それで、あなたはそれらの3つのケースをユニットテストするでしょう、なぜならそれが契約でgetNameあるからです。あなたはそれを逆方向にやっているようです。ブランチを見たり、それらに従ってテストを書いたり、契約に従ってテストを書いたり、契約が満たされていることを確認したくはありません。それはあなたが良いカバレッジを持っているときです。
ビンセントサバード

1
繰り返しますが、カバレッジが私のコードが完全にテストされていることを証明していると言っているわけではありませんが、それは私が確かにテストしていないことを示す非常に貴重なツールでした。コントラクトのテストは、実行パスのテストと切り離せないと思います(暗黙の言語メカニズムが関係しているため、この例は例外です)。パスをテストしていない場合は、契約を完全にテストしていないか、契約が完全に定義されていません。
カロルルワンドフスキ

2
:私は私の以前のポイント繰り返すつもりは常にあなたが唯一の基本的な言語機能に自分自身を制限しない限り、ケースやインストルメントされていない任意の関数を呼び出すことはありませんが。これは、サードパーティのライブラリがなく、SDKを使用しないことを意味します。
kdgregory 16

回答:


4

Java 8で作成できる論理ブランチを測定するツールはありますか?

私は何も知りません。念のためにJaCoCo(別名EclEmma)を使用してコードを実行しようとしましたが、Optionalバージョンに0のブランチが表示されます。別の言い方をするように構成する方法はわかりません。JDKファイルも含めるように構成した場合、理論的にはにブランチが表示されますがOptional、JDKコードの検証を開始するのはばかげていると思います。あなたはそれが正しいと仮定する必要があります。

ただし、コアの問題は、Java 8以前に追加されたブランチが、ある意味で人為的に作成されたブランチであることに気づいたことだと思います。Java 8にはもう存在しないということは、ジョブに適したツール(この場合はOptional)を手に入れたことを意味します。Java 8より前のコードでは、コードの各ブランチが許容できる方法で動作することを確信できるように、追加のユニットテストを作成する必要がありました。これは、User/ getName例。

Java 8コードでは、代わりに、コードが適切に動作することをJDKに信頼します。Optionalそのまま、その行をコードカバレッジツールが処理するのと同じように処理する必要があります。0行の3行です。以下のコードに他の行とブランチがあることは、今まで注意を払ったことのないものですが、ArrayListor などのようなものを使用するたびに存在していましたHashMap


2
「彼らはもはや... Javaの8には存在しないこと」 - Javaの8は下位互換性があり、私はそれに同意することはできませんとifnullまだ言語の一部である;-)それは古い方法でとパスへの書き込みコードにはまだ可能ですnullユーザーまたはnull名前を持つユーザー。テストでは、メソッドの実装方法に関係なく、契約が満たされていることを証明する必要があります。ポイントは、契約を完全にテストしたかどうかを通知するツールがないことです。
カロルルワンドフスキ

1
@KarolLewandowski Shazが言っていることは、どのようにOptional(および関連するメソッド)が機能するかを信頼すれば、それらをテストする必要がなくなるということです。あなたがテストしたのと同じ方法ではありませんif-else:すべてifが潜在的な地雷原でした。Optional同様の機能的なイディオムはすでにコーディングされており、つまずかないことが保証されているため、本質的には「ブランチ」が消滅します。
アンドレスF.

1
@AndresF。カロルはテストすることを提案しているとは思わないOptional。彼が言ったように、論理的にgetName()は、実装に関係なく、考えられる方法でさまざまな可能な入力を処理するテストを行う必要があります。JDK8より前の方法でコードカバレッジツールを使用せずにこれを判断することは困難です。
マイクパートリッジ

1
@MikePartridgeはい、しかし、ポイントはブランチカバレッジを介して行われないことです。if-elseこれらのコンストラクトはそれぞれ完全にアドホックであるため、作成時にはブランチカバレッジが必要です。これとは対照的に、OptionalorElsemap、など、すべてすでにテストされています。ブランチは、より強力なイディオムを使用すると、事実上「消滅」します。
アンドレスF.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.