Java 8 코드에 대한 조건부 적용 범위를 측정하는 것이 이치에 맞습니까?


19

Java 8이 등장한 이후 현재 Java 도구로 조건부 코드 적용 범위를 측정하는 것이 더 이상 사용되지 않는지 궁금합니다. 자바 8의로 Optional하고 Stream우리는 종종 쉽게 가능한 모든 실행 경로를 테스트하지 않고 매우 높은 조건 적용을받을 수 있습니다 코드 지점 / 루프를 방지 할 수 있습니다. 오래된 Java 코드와 Java 8 코드를 비교해 보겠습니다.

자바 8 이전 :

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

위의 방법에는 3 가지 가능한 실행 경로가 있습니다. 조건부 적용 범위를 100 % 달성하려면 3 가지 단위 테스트를 작성해야합니다.

자바 8 :

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

이 경우 브랜치는 숨겨져 있으며 100 % 적용 범위를 얻으려면 한 번의 테스트 만 필요하며 테스트 할 사례는 중요하지 않습니다. 여전히 똑같은 3 가지 논리적 인 브랜치가 있지만 다루어야합니다. 요즘 조건부 적용 범위 통계를 완전히 신뢰할 수 없다고 생각합니다.

Java 8 코드에 대한 조건부 적용 범위를 측정하는 것이 이치에 맞습니까? 저평가 된 코드를 발견하는 다른 도구가 있습니까?


5
커버리지 측정은 한 결코 당신의 코드가 무엇을 결정하기 위해 단지 방법을 잘 테스트 여부를 결정하는 좋은 방법이 없었다 되지 않은 테스트를. 훌륭한 개발자는 다양한 사례를 생각하고 모든 테스트 또는 적어도 그녀가 중요하다고 생각하는 테스트를 고안합니다.
kdgregory

3
물론 높은 조건부 적용 범위는 테스트가 훌륭하다는 것을 의미하지는 않지만 어떤 실행 경로가 밝혀 졌는지 아는 것이 큰 이점이라고 생각합니다. 이것이 대부분의 질문입니다. 조건부 적용 범위가 없으면 테스트되지 않은 시나리오를 찾기가 훨씬 어렵습니다. 경로 관련 : [user : null], [user : notnull, user.name:null], [user : notnull, user.name:notnull]. 내가 뭘 놓친거야?
Karol Lewandowski

6
계약은 getName무엇입니까? 이 경우 것 같다 user널 (null)이, 그것은 "알"을 반환해야합니다. user널이 아니고 널인 경우 user.getName()"알 수 없음"을 리턴해야합니다. user널이 아니고 널이 아닌 경우 user.getName()이를 리턴해야합니다. 이 세 가지 사례를 계약 한 것이기 때문에 단위 테스트 getName를합니다. 당신은 그것을 뒤로하고있는 것 같습니다. 지점을보고 그에 따라 테스트를 작성하고 싶지 않고 계약에 따라 테스트를 작성하고 계약이 가득 찼는 지 확인하고 싶습니다. 그때는 당신이 좋은 보험 혜택을받을 때입니다.
Vincent Savard

1
다시 말하지만, 적용 범위가 내 코드가 완벽하게 테스트되었음을 ​​증명하는 것은 아니지만, 내가 테스트하지 않은 것을 보여주는 매우 귀중한 도구였습니다. 계약 테스트는 실행 경로 테스트와 분리 할 수 ​​없다고 생각합니다 (예 : 암시 적 언어 메커니즘이 포함되어 있기 때문에 예외적입니다). 경로를 테스트하지 않은 경우 계약을 완전히 테스트하지 않았거나 계약이 완전히 정의되지 않았습니다.
Karol Lewandowski

2
이전의 요점을 반복하겠습니다. 기본 언어 기능으로 만 자신을 제한하고 계측되지 않은 함수를 호출하지 않는 한 항상 그렇습니다. 이는 타사 라이브러리가없고 SDK를 사용하지 않음을 의미합니다.
kdgregory

답변:


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 행. 다른 라인 및 지점 코드에 있다는 것을 아래 직전에주의를 지불하지 않은 일이지만, 당신이 같이 사용 무언가했습니다마다 존재하고 ArrayList또는 HashMap.


2
"더 이상 ... 자바 (8)에 존재하지 않음"- 자바 8은 이전 버전과의 호환, 내가 동의 할 수없고 if그리고 null여전히 언어의 부분입니다 ;-) 그것은 옛날 방식 및 통과하는 코드를 작성 여전히 가능 이름을 null가진 사용자 또는 사용자 null. 테스트는 메소드 구현 방법에 관계없이 계약이 충족되었음을 입증해야합니다. 요점은 계약을 완전히 테스트했는지 알려주는 도구가 없다는 것입니다.
Karol Lewandowski

1
@KarolLewandowski Shaz의 말에 따르면 Optional(및 관련 방법) 작동 방식 을 신뢰 하면 더 이상 테스트 할 필요가 없습니다. 같은 방법으로 테스트하지 않았습니다 if-else. 모든 if것이 잠재적 인 지뢰밭이었습니다. Optional비슷한 기능적 관용구가 이미 코딩되어있어 넘어지지 않도록 보장되어 있기 때문에 본질적으로 사라진 "분기"가 있습니다.
Andres F.

1
@AndresF. 나는 Karol이 우리가 테스트를 제안한다고 생각하지 않는다 Optional. 그가 말했듯이 논리적으로 우리는 getName()구현에 관계없이 의도 한 방식으로 다양한 가능한 입력 을 처리하는 테스트를 수행해야 합니다. JDK8 이전의 방식으로 코드 커버리지 툴링을 사용하지 않고서는이를 결정하기가 더 어렵습니다.
Mike Partridge

1
@MikePartridge 예. 요점은 지점 커버리지를 통해 수행되지 않는다는 것입니다. if-else각 구성은 완전히 임시이므로 작성시 분기 적용이 필요합니다 . 대조적으로, Optional, orElse, map, 등, 모든 이미 테스트됩니다. 더 강력한 관용구를 사용하면 실제로 분기가 "소멸"됩니다.
Andres F.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.