통합 테스트는 모든 단위 테스트를 반복해야합니까?


36

내가 함수를 가지고 있다고 가정 해 봅시다 (루비로 작성되었지만 모든 사람이 이해할 수 있어야합니다).

def am_I_old_enough?(name = 'filip')
   person = Person::API.new(name)
   if person.male?
      return person.age > 21
   else
      return person.age > 18
   end
end

단위 테스트에서는 모든 시나리오를 포괄하는 4 가지 테스트를 작성합니다. 각각은 Person::API스텁 된 메소드 male?와 함께 조롱 된 객체를 사용 합니다 age.

이제 통합 테스트를 작성합니다. Person :: API를 더 이상 조롱해서는 안된다고 가정합니다. 따라서 Person :: API 객체를 조롱하지 않고 정확히 동일한 네 가지 테스트 사례를 만들 것입니다. 그 맞습니까?

그렇다면 단위 테스트 작성의 요점은 무엇입니까? (스텁이나 모의가 아닌 실제 객체에서 작업 할 때) 더 자신감을주는 통합 테스트를 작성할 수 있다면?


3
요점 중 하나는 그것을 모의 / 단위 테스트함으로써 코드의 문제를 격리시킬 수 있다는 것입니다. 통합 테스트가 실패하면 코드가 누구인지, 사용자 코드 또는 API인지 알 수 없습니다.
Chris Wohlert 2016

9
네 가지 테스트 만? 17, 18, 19, 20, 21, 22 ...;)
David Arno

22
@FilipBartuzi, 예를 들어 방법이 남성이 21 세 이상인지 확인한다고 가정합니까? 현재 작성된 것처럼 그렇게하지 않습니다 .22 이상인 경우에만 사실입니다. 영어로 "21 세 이상"은 "21+"를 의미합니다. 따라서 코드에 버그가 있습니다. 이러한 버그는 경계 값, 즉 남성의 경우 20, 21, 22, 여성의 경우 17,18,19를 테스트하여 캡처됩니다. 따라서 최소한 6 번의 테스트가 필요합니다.
David Arno

6
0과 -1의 경우는 말할 것도 없습니다. 사람이 -1 세라는 것은 무엇을 의미합니까? API가 의미없는 것을 반환하면 코드는 어떻게해야합니까?
RubberDuck

9
사람 객체를 매개 변수로 전달했는지 테스트하는 것이 훨씬 쉽습니다.
JeffO

답변:


72

아니요, 통합 테스트 단위 테스트의 적용 범위를 복제 해서는 안됩니다. 그들은 일부 범위를 복제 할 수 있지만 요점이 아닙니다.

단위 테스트의 요점은 특정 소량의 기능이 의도 한대로 정확하고 완벽하게 작동하는지 확인하는 것입니다. 단위 테스트는 am_i_old_enough연령이 다른 데이터, 특히 임계 값에 가까운 데이터, 가능한 모든 연령대에 대한 데이터를 테스트합니다 . 이 테스트를 작성한 후에는 무결성 am_i_old_enough에 대해 다시 질문하지 않아야합니다.

통합 테스트의 요점은 전체 시스템 또는 상당수의 구성 요소 조합이 함께 사용될 때 올바른 일을 수행하는지 확인하는 것 입니다. 고객은 사용자가 작성한 특정 유틸리티 기능을 신경 쓰지 않고 미성년자가 웹 앱을 액세스하지 못하도록 보호합니다.

사용자의 나이를 확인하는 것입니다 하나 개 그 기능의 작은 부분 만 통합 테스트는 유틸리티 함수가 올바른 임계 값을 사용하는지 여부를 확인하지 않습니다. 호출자가 해당 임계 값, 유틸리티 함수의 호출 여부, 기타 액세스 조건 충족 여부 등을 기반으로 올바른 결정을 내리는 지 여부를 테스트합니다 .

두 가지 유형의 테스트가 모두 필요한 이유는 기본적으로 실행에 필요한 코드 기반을 통한 경로에 대한 가능한 시나리오의 조합 폭발이 있기 때문입니다. 유틸리티 기능에 약 100 개의 입력이 있고 수백 개의 유틸리티 기능이있는 경우 모든 경우 에 올바른 일이 발생하는지 확인 하려면 수백만 개의 테스트 사례가 필요합니다. 아주 작은 범위의 모든 사례를 확인한 다음 이러한 범위에 대해 일반적이고 관련성이 있거나 가능한 조합 을 확인 하면 이러한 작은 범위가 이미 정확하다고 가정하고 단위 테스트로 입증 된 것처럼 시스템이 수행하고 있다는 확신을 얻을 수 있습니다 대체 시나리오에서 익사 하지 않고 테스트 해야 할 사항 .


6
"우리는 대체 시나리오에서 익사하지 않고 시스템이해야 할 일을하고 있다는 확신을 가질 수 있습니다." 고맙습니다. 나는 누군가가 온전한 자동화 테스트에 접근하는 것을 좋아합니다.
jpmc26 2016 년

1
JB Rainsberger는 마지막 단락에서 "통합 테스트는 사기입니다" 라는 테스트와 조합 폭발에 대해 이야기 합니다. 통합 테스트에 관한 것이 아니라 여전히 흥미 롭습니다.
Bart van Nierop 2016 년

The customer doesn't care about a particular utility function you wrote, they care that their web app is properly secured against access by minors-> 그것은 매우 영리한 사고 방식입니다, 감사합니다! 문제는 스스로 프로젝트를 할 때입니다. 프로그래머와 제품 관리자 사이에서 사고 방식을 나누기가 어렵습니다.
Filip Bartuzi

14

짧은 대답은 "아니오"입니다. 더 흥미로운 부분은 이러한 상황이 발생하는 이유 / 방법입니다.

엄격한 관행을 준수하지 않는 코드에 대해 엄격한 테스트 관행 (단위 테스트 대 통합 테스트, 조롱 등)을 준수하려고하기 때문에 혼란이 발생한다고 생각합니다.

코드가 "잘못되었다"고 말하거나 특정 관행이 다른 것보다 낫다는 것은 아닙니다. 테스트 실습에 의해 만들어진 일부 가정은이 상황에 적용되지 않을 수 있으며 코딩 실무 및 테스트 실습에서 비슷한 수준의 "엄격 성"을 사용하는 데 도움이 될 수 있습니다. 또는 적어도 균형이 맞지 않을 수 있음을 인정하기 위해 일부 측면은 적용 할 수 없거나 중복 될 수 있습니다.

가장 확실한 이유는 함수가 두 가지 다른 작업을 수행하고 있기 때문입니다.

  • Person그들의 이름을 기반으로 찾고 있습니다. Person아마도 다른 곳에서 생성 / 저장된 객체를 찾을 수 있도록 통합 테스트가 필요합니다 .
  • Person성별에 따라 a 가 충분한 지 계산합니다 . 계산이 예상대로 수행되도록하려면 유닛 테스트가 필요합니다.

이러한 작업을 하나의 코드 블록으로 그룹화하면 다른 작업 없이는 실행할 수 없습니다. 계산을 단위 테스트하려면 Person실제 데이터베이스 또는 스텁 / 모의에서 조회를 수행해야합니다 . 조회가 나머지 시스템과 통합되는지 테스트하려는 경우 연령에 대한 계산도 수행해야합니다. 우리는 그 계산으로 무엇을해야합니까? 무시하거나 점검해야합니까? 그것은 당신이 당신의 질문에 묘사 한 정확한 곤경 인 것처럼 보입니다.

대안을 상상한다면, 우리는 그 자체로 계산을 할 수 있습니다.

def is_old_enough?(person)
   if person.male?
      return person.age > 21
   else 
      return person.age > 18
   end
end

이는 순수한 계산이므로 통합 테스트를 수행 할 필요가 없습니다.

조회 작업을 별도로 작성하려는 유혹을받을 수도 있습니다.

def person_from_name(name = 'filip')
   return Person::API.new(name)
end

그러나이 경우 기능이 너무 가까워서 Person::API.new대신 사용해야한다고 말하고 싶습니다 (기본 이름이 필요한 경우 클래스 속성과 같이 다른 곳에 더 잘 저장 하시겠습니까?).

통합 테스트를 작성할 때 Person::API.new(또는 person_from_name) 관심을 가져야 할 것은 예상 한 결과를 다시 얻는 지 여부입니다 Person. 모든 연령 기반 계산은 다른 곳에서 처리되므로 통합 테스트에서 무시할 수 있습니다.


11

Killian의 대답 에 덧붙이는 또 다른 요점 은 단위 테스트가 매우 빠르게 실행되므로 1000 개를 가질 수 있다는 것입니다. 통합 테스트는 일반적으로 웹 서비스, 데이터베이스 또는 기타 외부 종속성을 호출하기 때문에 시간이 오래 걸리므로 통합 시나리오에 대해 너무 많은 시간이 걸리는 동일한 테스트 (1000)를 실행할 수 없습니다.

또한 단위 테스트는 일반적으로 빌드 시 (빌드 머신에서) 실행되고 통합 테스트 는 환경 / 컴퓨터에 배포 한 후에 실행 됩니다.

일반적으로 모든 빌드에 대해 1000 개의 단위 테스트를 수행 한 다음 모든 배치 후에 100 개 이상의 고가의 통합 테스트를 실행합니다. 각 빌드를 배포로 가져갈 수는 없지만 배포 테스트를 수행하면 빌드가 실행되므로 괜찮습니다. 일반적으로 배포를 너무 오래 유지하고 싶지 않기 때문에 이러한 테스트를 10 분 또는 15 분 내에 실행하도록 제한하려고합니다.

또한 주별 일정에 따라 주말 또는 기타 다운 타임에 더 많은 시나리오를 다루는 회귀 통합 테스트 모음을 실행할 수 있습니다. 더 많은 시나리오를 다루기 때문에 15 분 이상 걸릴 수 있지만 일반적으로 아무도 토 / 일에 대해 작업하지 않으므로 테스트에 더 많은 시간을 할애 할 수 있습니다.


동적 언어에는 적용되지 않습니다 (예 : 빌드 단계 제외)
Filip Bartuzi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.