TDD 테스트는 얼마나 세밀해야합니까?


18

의료 소프트웨어 사례를 기반으로 한 TDD 교육 과정에서 "사용자가 저장 버튼을 누르면 시스템이 환자를 추가하고 장치를 추가하며 장치 데이터 레코드를 추가해야합니다"라는 스토리를 구현합니다.

최종 구현은 다음과 같습니다.

if (_importDialog.Show() == ImportDialogResult.SaveButtonIsPressed)
{
   AddPatient();
   AddDevice();
   AddDeviceDataRecords();
}

이를 구현하는 두 가지 방법이 있습니다.

  1. 각각 하나의 메소드 (AddPatient, AddDevice, AddDeviceDataRecords)가 호출되었는지 검증하는 세 가지 테스트가 호출되었습니다.
  2. 세 가지 방법을 모두 검증하는 하나의 테스트가 호출되었습니다.

첫 번째 경우 if 절 조건에 문제가 발생하면 세 가지 테스트가 모두 실패합니다. 그러나 두 번째 경우 테스트에 실패하면 정확히 무엇이 잘못되었는지 확실하지 않습니다. 어떤 방법을 선호하십니까?

답변:


8

그러나 두 번째 경우 테스트에 실패하면 정확히 무엇이 잘못되었는지 확실하지 않습니다.

나는 그것이 테스트가 얼마나 좋은 오류 메시지를 생성하는지에 달려 있다고 생각합니다. 일반적으로 메소드가 호출되었는지 확인하는 다른 방법이 있습니다. 예를 들어 모의 객체를 사용하는 경우 테스트 중에 호출되지 않은 예상 메소드를 설명하는 정확한 오류 메시지가 표시됩니다. 호출의 영향을 감지하여 메소드가 호출되었는지 확인하는 경우 설명 오류 메시지를 작성하는 것은 사용자의 책임입니다.

실제로 옵션 1과 2 사이의 선택은 상황에 따라 다릅니다. 레거시 프로젝트에서 위에 표시된 코드를 볼 경우 조건이 충족 될 때 3 가지 메소드 각각이 올바르게 호출되는지 확인하기 위해 사례 # 2의 실용적인 접근 방식을 선택합니다. 지금이 코드를 개발 중이라면 3 개의 메소드 호출이 별도의 시점에 (아마도 며칠 또는 몇 개월 떨어져서) 하나씩 하나씩 추가 될 가능성이 높으므로 새로운 개별 단위 테스트를 추가 할 것입니다 각 전화를 확인합니다.

또한 두 가지 방법 모두 각각의 개별 방법이 수행해야하는 작업을 수행하는지 확인하기 위해 별도의 단위 테스트를 수행해야합니다.


이 세 가지 테스트를 하나로 결합하는 것이 합리적이지 않습니까?
SiberianGuy

@Idsa는 합리적인 결정이 될 수 있지만 실제로는 이런 종류의 리팩토링에 거의 신경 쓰지 않습니다. 그런 다음 우선 순위가 다른 레거시 코드로 작업하고 있습니다. 기존 코드의 테스트 범위를 늘리고 증가하는 단위 테스트를 유지 관리하는 데 중점을 둡니다.
Péter Török

30

예제의 Granularity는 단위 테스트와 승인 테스트의 차이 인 것 같습니다.

unittest는 가능한 한 적은 종속성으로 단일 기능 단위를 테스트합니다. 귀하의 경우에는 4 가지 단위 테스트가 가능합니다

  • AddPatient가 환자를 추가합니까 (예 : 관련 데이터베이스 기능 호출)?
  • AddDevice가 장치를 추가합니까?
  • AddDeviceDataRecords가 레코드를 추가합니까?
  • 예제에서 Unmended 메인 함수는 AddPatient, AddDevice 및 AddDeviceFunctions를 호출합니다.

단위 테스트는 개발자를위한 것이므로 코드가 기술적으로 정확하다는 자신감을 얻습니다.

승인 테스트는 사용자 관점에서 결합 된 기능을 테스트해야합니다. 그것들은 사용자 스토리를 따라 모델링되어야하며 가능한 한 높은 수준이어야합니다. 따라서 함수가 호출되는지 확인할 필요는 없지만 사용자 에게 표시 되는 이점이 있는지 확인하십시오 .

사용자가 데이터를 입력하면 확인을 클릭하고 ...

  • 환자 목록으로 가서 이름이 지정된 새 환자를 보게됩니다
  • ... 장치 목록으로 이동하면 새 장치가 표시됩니다.
  • ... 새 장치의 세부 정보로 이동하면 새 데이터 레코드가 표시됩니다

수락 테스트는 고객을위한 것이며 고객 과 더 나은 의사 소통을하기위한 것입니다.

"무엇을 원하십니까?"라는 질문에 대답하기 위해 : 지금 당신에게 더 큰 문제는 무엇입니까, 버그와 회귀 (=> 더 많은 단위 테스트) 또는 큰 그림을 이해하고 공식화 (=> 더 많은 합격 테스트)


13

이를 구현하는 두 가지 방법이 있습니다.

그건 틀렸어

각각 하나의 메소드 (AddPatient, AddDevice, AddDeviceDataRecords)가 호출되었는지 검증하는 세 가지 테스트가 호출되었습니다.

당신은 있어야 작동 확인하기 위해이 작업을 수행.

세 가지 방법을 모두 검증하는 하나의 테스트가 호출되었습니다.

당신은해야한다 또한 확인 API의 작품으로이 작업을 수행.

수업은 하나의 단위로 완전히 테스트되어야합니다. 각 방법.

세 가지 방법 모두를 다루는 테스트로 시작할 수 있지만 많은 것을 알려주지는 않습니다.

테스트가 실패하면 정확히 무엇이 잘못되었는지 확실하지 않습니다.

옳은. 이것이 모든 방법 을 테스트 하는 이유 입니다.

당신은 해야한다 공용 인터페이스를 테스트합니다. 이 클래스는 세 가지 더하기 하나를 수행하기 때문에 (사용자 스토리로 인해 하나의 메소드에 번들로 제공되는 경우에도) 네 가지를 모두 테스트해야합니다. 3 개의 하위 레벨 및 1 개의 번들


2

우리는 의미있는 기능성 문장에 대한 단위 테스트를 작성합니다.이 문장은 여러 번 메소드에 매핑되지만 (코드를 잘 작성한 경우) 많은 메소드를 포함하여 더 커집니다.

예를 들어, 환자를 시스템에 추가하려면 몇 가지 서브 루틴 (하위 기능)을 호출해야한다고 상상해보십시오.

  1. 환자 자격 검증
  2. 닥터 존재
  3. CheckInsuranceHistory
  4. 비어있는 침대 확보

이러한 각 기능에 대한 단위 테스트를 작성할 수도 있습니다.


2

내가 따라온 간단한 경험 법칙 중 하나는 테스트가 수행하는 작업을 정확하게 설명하도록 테스트의 이름을 지정하는 것입니다. 테스트 이름이 너무 복잡해지면 테스트가 너무 많이 수행되고 있음을 나타냅니다. 예를 들어 옵션 2에서 제안한 작업을 수행하기 위해 테스트 이름을 지정하는 것은 PatientI BrokerWhenSaved, DeviceI MembersWhenSaved, DataRecordsWhenSaved의 세 가지 개별 테스트보다 훨씬 복잡한 PatientI BrokerDeviceIAgentAndDeviceDataRecordsWhenSaved처럼 보일 수 있습니다. 또한 BDD에서 배울 수있는 교훈은 각 테스트가 실제로 자연 언어로 설명 할 수있는 단일 요구 사항을 나타내는 경우에 매우 흥미 롭습니다.

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