IF 문에서 여러 조건을 단위 테스트


25

다음과 같은 코드 덩어리가 있습니다.

function bool PassesBusinessRules()
{
    bool meetsBusinessRules = false;

    if (PassesBusinessRule1 
         && PassesBusinessRule2
         && PassesBusinessRule3)
    {
         meetsBusinessRules= true;
    }

    return meetsBusinessRules;
}

이 특정 기능에 대해 4 가지 단위 테스트가 있어야한다고 생각합니다. if 문에서 각 조건을 테스트하고 false를 반환하는지 확인하려면 세 개입니다. 그리고 함수가 true를 반환하는지 확인하는 또 다른 테스트.

질문 : 실제로 10 개의 단위 테스트가 있어야합니까? 9 개의 가능한 실패 경로를 확인합니다. IE :

  • 거짓 거짓 거짓
  • 거짓 거짓 참
  • 거짓 참 거짓

그리고 가능한 모든 조합에 대해서도 마찬가지입니다.

나는 그것이 과잉이라고 생각하지만, 우리 팀의 다른 멤버들 중 일부는 그렇지 않습니다. 내가 보는 방법은 BusinessRule1이 실패하면 항상 false를 반환해야합니다. 처음으로 확인했는지 또는 마지막으로 확인했는지는 중요하지 않습니다.


컴파일러는 && 연산자에 대해 탐욕스러운 평가를 사용합니까?
suszterpatt

12
10 개의 단위 테스트를 작성했다면 메소드가 아닌 테스트 및 연산자입니다.
Mert Akcakaya

2
가능한 모든 조합을 테스트 한 경우 8 개의 테스트 만 있지 않습니까? 3 개의 부울 매개 변수가 켜지거나 꺼졌습니다.
Kris Harper

3
@Mert : &&가 항상 있음을 보장 할 수있는 경우에만.
Misko

Hickey : 테스트 작성에 소비한다면, 다른 일을하지 않는 시간입니다. 우리 각자는 수량과 품질면에서 결과를 극대화하기 위해 시간을 가장 잘 보내는 방법을 평가해야합니다. 사람들이 테스트 작성 시간의 50 %를 소비하면 결과가 극대화된다고 생각하면 알 수 있습니다. 나는 그것이 사실이 아니라고 확신한다. 오히려 내 문제에 대해 생각하면서 그 시간을 보내고 싶다. 나는 이것이 내가 다른 시간을 사용하는 것보다 적은 결함으로 더 나은 솔루션을 생산할 것이라고 확신합니다. 완벽한 테스트 스위트를 갖춘 나쁜 디자인은 여전히 ​​나쁜 디자인입니다.
Job

답변:


28

공식적으로 이러한 유형의 보장에는 이름이 있습니다.

첫째, 술어 적용 범위가 있습니다 . if 문을 true로 만드는 테스트 사례와 false로 만드는 테스트 사례를 원합니다. 이 범위를 충족시키는 것은 좋은 테스트 스위트의 기본 요구 사항 일 것입니다.

그런 다음 Condition Coverage : 여기에서 if의 각 하위 조건에 true 및 false 값이 있는지 테스트하려고합니다. 이것은 분명히 더 많은 테스트를 생성하지만 일반적으로 더 많은 버그를 포착하므로 시간이 있으면 테스트 스위트에 포함시키는 것이 좋습니다.

가장 광범위한 적용 범위 기준은 일반적으로 조합 조건 적용 범위 라고합니다 . 여기서 목표는 테스트에서 가능한 모든 부울 값 조합 을 통과하는 테스트 사례를 갖는 입니다.

이것이 단순한 술어 나 조건 범위보다 낫습니까? 물론 커버리지 측면에서. 그러나 무료는 아닙니다. 테스트 유지 관리 비용이 매우 많이 듭니다. 이러한 이유로 대부분의 사람들은 완전한 조합 범위를 신경 쓰지 않습니다. 일반적으로 모든 지점 (또는 모든 조건)을 테스트하면 버그를 잡기에 충분합니다. 조합 테스트를위한 추가 테스트를 추가하면 일반적으로 더 많은 버그가 발생하지 않지만 작성 및 유지 관리에 많은 노력이 필요합니다. 추가 노력은 일반적으로 매우 작은 보상 가치가되지 않으므로 권장하지 않습니다.

이 결정의 일부는 해당 코드가 얼마나 위험한 지에 따라 결정되어야합니다. 실패 할 여지가 많은 경우 테스트 할 가치가 있습니다. 다소 안정적이며 많이 변경되지 않으면 다른 곳에서 테스트 노력을 집중해야합니다.


2
부울 값이 외부 소스에서 전달되면 (항상 유효성이 확인되지는 않음) 조합 조건부 적용 범위가 필요한 경우가 많습니다. 먼저 조합 표를 만드십시오. 그런 다음 각 항목에 대해 해당 항목이 의미있는 사용 사례를 나타내는 지 결정하십시오. 그렇지 않은 경우 해당 조합이 실행되지 않도록 어딘가에 코드 (소프트웨어 어설 션 또는 유효성 검사 절)가 있어야합니다. 단일 조합 테스트에서 모든 매개 변수를 일괄 처리 하지 않는 것이 중요 합니다. 매개 변수를 서로 상호 작용하는 그룹으로 분할하십시오. 즉 동일한 부울 식을 공유하십시오.
rwong

굵은 글씨가 얼마나 확실합니까? 귀하의 답변은 "Combinatorial Condition Coverage"의 유일한 발생으로 보이며 일부 리소스는 "predicate coverage"와 "conditional coverage"가 동일하다고 말합니다.
Stijn

8

궁극적으로, 그것은 당신 (팀), 코드 및 특정 프로젝트 환경에 달려 있습니다. 보편적 인 규칙은 없습니다. 귀하 (팀)는 코드가 실제로 올바른지 편안하게 느끼기 위해 필요한만큼 많은 테스트를 작성해야합니다 . 따라서 팀원이 4 번의 테스트로 확신하지 못하면 더 많은 것이 필요할 수 있습니다.

단위 테스트를 작성하는 OTOH 시간은 일반적으로 희소 한 자원입니다. 따라서 제한된 시간을 보낼 수있는 가장 좋은 방법을 찾기 위해 노력하십시오 . 예를 들어, 적용 범위가 0 % 인 다른 중요한 방법이있는 경우이 방법에 대한 추가 테스트를 추가하지 않고 두 가지 단위 테스트를 작성하여 해당 테스트를 커버하는 것이 좋습니다. 물론 각각의 구현이 얼마나 취약한 지에 달려 있습니다. 가까운 시일 내에이 특정 방법에 대한 많은 변경을 계획하면 추가 단위 테스트 범위가 정당화 될 수 있습니다. 따라서 프로그램 내부의 중요한 경로에있을 수 있습니다. 이것들은 오직 당신 (팀)만이 평가할 수있는 모든 요소입니다.

나는 개인적으로 네가 설명하는 4 가지 테스트, 즉 :

  • 참 거짓 거짓
  • 거짓 사실 거짓
  • 거짓 거짓 사실
  • 사실 사실 사실

플러스 하나 :

  • 참 참 거짓

리턴 값을 얻는 유일한 방법 true은 3 가지 비즈니스 규칙을 모두 충족시키는 것입니다. 그러나 결국 팀원들이 조합 경로를 다룰 것을 주장하면 인수를 훨씬 더 오래 지속하는 것보다 추가 테스트를 추가하는 것이 더 저렴 할 수 있습니다.


3

안전을 원한다면 3 개의 변수 진리표 ( http://teach.valdosta.edu/plmoch/MATH4161/Spring%202004/and_or_if_files/image006.gif )로 표시되는 조건을 사용하여 8 개의 단위 테스트가 필요합니다 .

비즈니스 로직이 항상 점검이 순서대로 수행되고 테스트가 가능한 실제 구현에 대해 거의 알기를 원하지 않는다고 확신 할 수는 없습니다.


2
단위 테스트 화이트 박스 테스트입니다.
Péter Török

질서가 문제가되지 않아야하며 &&는
Zachary K

2

그렇습니다. 이상적인 세상에는 완전한 조합이 있어야합니다.

단위 테스트를 수행 할 때, 당신은 정말 무시하려고한다 방법 이 방법은 작업을 수행합니다. 간단히 3 개의 입력을 제공하고 출력이 올바른지 확인하십시오.


1
단위 테스트 화이트 박스 테스트입니다. 그리고 우리는 이상적인 세상에 살고 있지 않습니다.
Péter Török

PéterTörök @ - 우리는 확실하게 이상적인 세계에없는 라이브 않지만, stackexchange의 다른 점에 당신과 함께 동의하지. 특히 TDD의 경우 테스트가 구현이 아닌 사양에 기록됩니다. 개인적으로 모든 입력 (구성원 변수 포함) 및 모든 출력 (부작용 포함)을 포함하기 위해 '사양'을 사용합니다.
Telastyn

1
특정 경우에 대해 StackOverflow에서 하나의 특정 스레드이며 과도하게 생성해서는 안됩니다. 특히이 현재 게시물은 분명히 이미 작성된 코드 테스트에 관한 것입니다.
Péter Török

1

국가는 악하다. 다음 기능은 부작용이없고 기능과 기능이 무엇인지 잘 알고 있기 때문에 단위 테스트가 필요하지 않습니다. 왜 테스트해야합니까? 당신은 자신의 두뇌를 믿지 않습니까 ??? 정적 기능이 훌륭합니다!

static function bool Foo(bool a, bool b, bool c)
{
    return a && b && c;
}

2
아니, 나는 내 자신의 두뇌를 믿지 않는다-나는 내가하는 일을 항상 재확인하는 어려운 방법을 배웠다 .-) 그래서 내가 잘못 입력하지 않았고 아무도 가고 있지 않다는 것을 보장하기 위해 여전히 단위 테스트가 필요하다. 앞으로 코드를 깨뜨릴 수 있습니다. 보다 단위 테스트가 나타내는 상태를 계산 발신 방법을 확인하기 위해 a, b그리고 c. 원하는 방식으로 비즈니스 로직을 옮길 수 있으며, 결국에는 어딘가에서 테스트해야합니다.
Péter Török

@Peter Török, 당신은 또한 당신의 테스트에서 오타를 만들어 오탐으로 끝날 수 있습니다. 단위 테스트를위한 단위 테스트를 작성합니까? 나는 뇌도 100 % 신뢰하지 않지만, 마지막 날에 코드 작성은 내가 생계를 위해하는 일이다. 이 함수에 버그가있을 수 있지만 버그를 소스로 쉽게 추적 할 수있는 방식으로 코드를 작성하는 것이 중요하므로 일단 문제를 격리하고 수정 한 후에는 더 나아질 수 있습니다. . 잘 작성된 코드는 주로 infoq.com/presentations/Simple-Made-Easy
Job

2
실제로 테스트도 잘못 될 수 있습니다. (TDD는 먼저 테스트에 실패함으로써이를 해결합니다.) 그러나 같은 종류의 오류를 두 번 (그리고 간과하게) 만들면 확률이 훨씬 낮아집니다. 일반적으로, 테스트 아무리 입력을 수행 할 수 있습니다 증명할 소프트웨어 버그 - 무료입니다 단지 줄이기 수용 가능한 수준으로 버그의 가능성을. 그리고 버그를 소스로 추적하는 속도에서 IMO는 단위 테스트를 이길 수 없습니다. 빠른 피드백 규칙 :-)
Péter Török

"다음 함수는 단위 테스트가 필요하지 않습니다."나는 당신이 냉소적이라고 생각하지만 명확하지 않습니다. 내 뇌를 믿습니까? 아니! 코드를 만지는 다음 사람의 두뇌를 믿습니까? 더 안돼! 코드 뒤의 모든 가정이 지금부터 1 년 후에 이루어질 것이라고 믿습니까? 내 표류를 얻습니다. 또한 FP를 수행하려면 정적 함수가 OO를 종료합니다. 그런 다음 FP 언어를 사용하십시오.
Rob

1

나는이 질문이 아주 오래되었다는 것을 안다. 그러나 나는 그 문제에 대한 또 다른 관점을 제시하고 싶다.

먼저, 단위 테스트에는 두 가지 목적이 있어야합니다.

  1. 일정 시간이 지나면 단위 테스트를 읽고 이해 what's the class' intention하고 확인하기 위해 귀하와 팀 동료를위한 문서를 작성하십시오.how the class is doing its work
  2. 개발하는 동안 단위 테스트는 우리가 작성하는 코드가 의도 한대로 작동하는지 확인합니다.

따라서 문제를 되풀이하여 우리 complex if statement는 주어진 예에 대해 2 ^ 3 가능성이 있습니다. 우리가 쓸 수있는 중요한 양의 테스트입니다.

  • 이 사실에 적응하고 8 개의 테스트를 작성하거나 매개 변수화 된 테스트를 사용할 수 있습니다.
  • 당신은 또한 다른 답변을 따를 수 있으며, 의도와 함께 테스트가 명확해야한다는 것을 기억할 수 있습니다. what is doing the code

반면에 테스트가 구현보다 훨씬 복잡한 위치에 있다면 테스트 자체보다는 구현을 다시 디자인해야하기 때문입니다 (사례에 따라 다소).

예를 들어 복잡한 if 문의 경우 체인 책임 패턴을 생각하여 각 핸들러를 다음과 같이 구현할 수 있습니다.

If some simple business rule apply, derive to the next handler

복잡한 규칙 대신 여러 간단한 규칙을 테스트하는 것이 얼마나 간단합니까?

도움이 되길 바랍니다.


0

이것은 quickcheck ( http://en.wikipedia.org/wiki/QuickCheck 와 같은 것)과 같은 경우 중 하나입니다 ) 것이 친구가 . 모든 N 사례를 직접 작성하는 대신 컴퓨터가 가능한 모든 테스트 사례 (또는 최소한 다수)를 생성하고 모든 것이 합리적인 결과를 반환하는지 확인합니다.

우리는 여기에 생계를 위해 컴퓨터를 프로그래밍합니다. 테스트 케이스를 생성하도록 컴퓨터를 프로그래밍 해보십시오.


0

조건을 보호 조건으로 리팩터링 할 수 있습니다.

if (! PassesBusinessRule1) {
    return false;
}

if (! PassesBusinessRule2) {
    return false;
}

if (! PassesBusinessRule3) {
    return false;
}

나는 그것이 사건의 수를 줄이지 않는다고 생각하지만, 내 경험은 이런 식으로 사건을 해결하는 것이 더 쉽다는 것입니다.

(저는 "단일 종료 지점"팬이지만 보호 조건에 대한 예외는 있지만 코드를 구성하는 다른 방법이 있으므로 별도의 수익이 발생하지 않습니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.