목록 테스트… 각 조건에 대해 동일한 테스트 또는 하나의 테스트에 모두 있습니까?


21

함수가 목록에서 예상 한 작업을 수행하는지 테스트하고 있습니다. 테스트하고 싶습니다

f(null) -> null
f(empty) -> empty
f(list with one element) -> list with one element
f(list with 2+ elements) -> list with the same number of elements, doing what expected

그렇게하기 위해 가장 좋은 방법은 무엇입니까?

  • "WorksAsExpected"라는 이름으로 동일한 (방법) 테스트에서 모든 사례를 테스트
  • 각각의 경우에 대해 하나의 테스트를 실시하여
    • "WorksAsExpectedWhenNull"
    • "WorksAsExpectedWhenEmpty"
    • "WorksAsExpectedWhenSingleElement"
    • "WorksAsExpectedWhenMoreElements"
  • 내가 생각하지 않은 또 다른 선택 :-)


2
나는 그것들을 별도의 테스트 케이스로 쓸 것입니다. 테스트 시스템에서 지원하는 경우 매개 변수화 된 테스트를 사용할 수 있습니다.
jonrsharpe

5
Given ... When ... Then 스타일에서 테스트를 작성하면 실제로 개별적으로 테스트해야한다는 것이 자명 해집니다.
Robbie Dee

1
추가하고 싶습니다 : IMO, 가장자리 사례 (예 : null 및 empty)를 별도의 테스트로 분리하는 것이 좋습니다. 이는 종종 가능한 다른 구현에서 특별한 사례 논리를 포함하기 때문에이 테스트가 실패하면 명확하게 표시됩니다 테스트중인 코드가 실패하는 방식
Filip Milovanović

1
중복 요소가있는 목록?
atayenel

답변:


30

하나의 테스트 사례에서 여러 테스트를 수행할지 여부에 사용하는 간단한 경험 법칙은 다음과 같습니다. 하나의 설정 만 포함됩니까?

따라서 여러 요소에 대해 테스트하고 모든 요소를 ​​처리하고 올바른 결과를 도출 한 경우 두 개 이상의 어설 션이있을 수 있지만 목록을 한 번만 설정하면됩니다. 따라서 하나의 테스트 사례가 좋습니다.

귀하의 경우에는 null 목록, 빈 목록 등을 설정해야합니다. 다중 설정입니다. 따라서이 경우에는 여러 테스트를 작성해야합니다.

다른 사람들이 언급했듯이 이러한 "다중 테스트"는 단일 매개 변수화 된 테스트 사례로 존재할 수 있습니다. 즉, 동일한 테스트 사례가 다양한 설정 데이터에 대해 실행됩니다. 이것이 실행 가능한 솔루션인지 아는 열쇠는 테스트의 다른 부분 인 "action"과 "assert"에 있습니다. 각 데이터 세트에 대해 동일한 작업을 수행하고 주장 할 수 있으면이 방법을 사용하십시오. if예를 들어 해당 데이터의 다른 부분에 대해 다른 코드를 실행하기 위해를 추가 하는 것은 해결책이 아닙니다. 후자의 경우 개별 테스트 사례를 사용하십시오.


14

절충이 있습니다. 한 번의 테스트로 더 많이 포장할수록 양파 효과를 전달하려고 시도 할 가능성이 높아집니다. 즉, 첫 번째 실패는 해당 테스트를 중지합니다. 첫 번째 실패를 해결하기 전에는 다른 어설 션에 대해 알 수 없습니다. 즉, 설정 코드를 제외하고는 대부분 비슷한 단위 테스트를 수행하는 것은 일부 작업은 작성되었지만 다른 작업은 그렇지 않다는 것을 알아내는 데 많은 바쁜 작업입니다.

프레임 워크를 기반으로 가능한 도구 :

  • 이론 . 이론을 사용하면 일련의 데이터에 대한 일련의 사실을 테스트 할 수 있습니다. 그런 다음 프레임 워크는 필드 또는 데이터를 생성하는 정적 방법으로 여러 테스트 데이터 시나리오를 통해 테스트를 제공합니다. 당신의 사실 중 일부가 일부 전제 조건에 기초하여 적용되고 다른 것들은 그렇지 않다면 이러한 프레임 워크는 가정 의 개념을 소개합니다 . 귀하는 Assume.that()이 전제 조건을 실패 할 경우 단순히 데이터에 대한 테스트를 건너 뜁니다. 이를 통해 "예상대로 작동"을 정의하고 많은 양의 데이터를 제공 할 수 있습니다. 결과를 볼 때 상위 테스트 항목과 각 데이터에 대한 하위 항목이 있습니다.
  • 매개 변수화 된 테스트 . 매개 변수화 된 테스트는 이론의 전조 였으므로 이론으로 가질 수있는 전제 조건 검사가 없을 수 있습니다. 최종 결과는 같습니다. 결과를보고 테스트 자체에 대한 상위 항목과 각 데이터 포인트에 대한 특정 항목이 있습니다.
  • 여러 가지 주장을 가진 하나의 테스트 . 설정하는 데 시간이 덜 걸리지 만 한 번에 조금씩 문제를 발견하게됩니다. 테스트가 너무 길고 테스트 된 다른 시나리오가 너무 많으면 크게 두 가지 위험이 있습니다.
  • 유사한 구현으로 여러 테스트 . 어설 션이 다르면 테스트가 겹치지 않는다는 점에 유의해야합니다. 그러나 이것이 TDD 중심 팀의 일반적인 지혜입니다.

나는 assert당신의 시험에 단 하나의 진술 만이있을 수 있다는 엄격한 사고 방식은 아니지만, 모든 주장들이 단일 행동의 사후 조건을 시험해야한다는 제한을 두었다. 테스트 간의 유일한 차이점이 데이터라면 매개 변수화 된 테스트 나 이론과 같은 고급 데이터 중심 테스트 기능을 사용하는 것이 좋습니다.

최상의 결과를 결정하기 위해 옵션의 무게를 eigh니다. "WorksAsExpectedWhenNull"은 다양한 요소가있는 컬렉션을 처리하는 경우와 근본적으로 다릅니다.


5

그것들은 다른 테스트 사례이지만 테스트 코드는 동일합니다. 따라서 매개 변수화 된 테스트를 사용하는 것이 가장 좋습니다. 테스트 프레임 워크가 매개 변수화를 지원하지 않으면 공유 코드를 헬퍼 함수로 추출하여 개별 테스트 케이스에서 호출하십시오.

한 테스트 사례 내에서 루프를 통한 매개 변수화를 피하십시오. 오류가 발생한 데이터 세트를 판별하기 어렵 기 때문입니다.

TDD 빨강-녹색-리 팩터 사이클에서 한 번에 하나의 예제 데이터 세트를 추가해야합니다. 여러 테스트 사례를 매개 변수화 된 테스트로 결합하는 것은 리팩토링 단계의 일부입니다.

다소 다른 접근 방식은 속성 테스트 입니다. 구체적인 입력 데이터를 지정하지 않고 함수의 다양한 속성을 나타내는 다양한 (매개 변수화 된) 테스트를 만들 수 있습니다. 예를 들어 속성은 다음과 같습니다. 모든 목록 xs에서 목록 ys = f(xs)의 길이는 xs입니다. 테스트 프레임 워크는 흥미로운 목록과 임의의 목록을 생성하고 속성이 모든 속성을 보유한다고 주장합니다. 예제를 수동으로 선택하면 흥미로운 경우를 놓칠 수 있기 때문에 수동으로 예제를 지정하는 것에서 멀어집니다.


마지막 문장에서 "miss"를 "find"해서는 안됩니까?
로비 디

@RobbieDee English는 모호하고 고정되어 있습니다.
amon

3

각 테스트마다 단일 개념을 테스트하는 것이 좋은 지침이되기 때문에 각 사례마다 하나의 테스트를 수행하는 것이 좋습니다.

이 게시물을 참조하십시오 . 단일 단위 테스트에서 여러 개의 어설 션을 보유해도 괜찮습니까? . 거기에 관련이 있고 자세한 토론이 있습니다.

내 지침은 일반적으로 테스트 당 하나의 논리적 개념을 테스트하는 것입니다. 동일한 개체에 여러 개의 어설 션이있을 수 있습니다. 그것들은 보통 테스트되는 것과 같은 개념 일 것입니다. 출처-Roy Osherove

[...]

테스트가 한 가지 이유만으로 실패해야한다고해서 항상 단 하나의 Assert 문만 있어야한다는 것은 아닙니다. IMHO "배열, 행동, 주장"패턴을 유지하는 것이 더 중요합니다.

핵심은 작업이 하나 뿐인 다음 어설 션을 사용하여 해당 작업의 결과를 검사하는 것입니다. 그러나 "정렬, 행위, 주장, 시험 종료"입니다. 다른 조치를 수행하여 테스트를 계속하려는 경향이 있고 나중에 더 많은 주장을한다면 대신 별도의 테스트를 수행하십시오. 출처


0

내 생각에는 테스트 조건에 달려 있습니다.

  • 테스트 설정 조건이 하나 뿐이지 만 많은 부작용이있는 경우. 다중 어설 션이 허용됩니다.
  • 그러나 여러 조건이있는 경우 여러 테스트 사례가 있음을 의미하며 각각 하나의 단위 테스트 만 포함해야합니다.

이것은 댓글처럼 더 읽습니다. 답변하는 방법
gnat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.