개인 코드에 대한 단위 테스트를 어떻게 옹호 할 수 있습니까?


15

내 작업 그룹에서 단위 테스트를 옹호하려고 노력하고 있지만 종종 얻는 반대 의견은 외부 및 내 보낸 API (시스템의 최소 및 중요하지 않은 부분)에 대해서만 사용해야하며 내부 및 개인에서는 사용하지 않아야한다는 것입니다 코드 (현재 기능 테스트 만 있음).

단위 테스트를 모든 코드에 적용 할 수 있고 적용해야한다고 생각하지만 동료를 어떻게 설득 할 수 있습니까?


3
테스트 할 필요가 있다고 생각되는 개인 메소드가있는 경우 코드가 SRP를 위반하고 자체적으로 추출되고 테스트되기를 요구하는 다른 클래스가 있음을 나타내는 징후 일 때가 많습니다.
Paddyslacker

@ Paddyslacker : 모든 코드를 테스트해야한다고 생각합니다. 단일 책임 원칙을 따르는 코드 단위가 단위 테스트를받지 않아야하는 이유를
모르겠습니다

4
@lorenzo, 당신은 내 요점을 놓쳤다; 어쩌면 나는 그것을 잘하지 못했습니다. 이러한 개인 메서드를 다른 클래스로 추출하면 이제 원래 클래스에서 액세스 할 수 있어야합니다. 메소드가 공개되었으므로 테스트해야합니다. 나는 그들이 테스트를해서는 안된다는 것을 암시하지 않았으며, 메소드를 직접 테스트 할 필요가 있다고 느낀다면 사적인 것이어서는 안된다는 것을 암시했습니다.
Paddyslacker

@Paddyslacker : 개인 메서드도 직접 테스트해야한다고 생각합니다. 왜 그들이 사적이어야한다고 생각하지 않습니까?
Wizard79

6
개인 메소드를 테스트함으로써 추상화를 깨뜨릴 수 있습니다. 단위 테스트에서 구현이 아닌 상태 및 / 또는 동작을 테스트해야합니다. Paddyslacker가 말한 것처럼 Paddyslacker가 말하는 것처럼 SRP를 위반하고 있다는 의미는 귀하의 예제 / 시나리오에서 개인 코드의 결과가 무엇인지 확인할 수 있어야합니다. 또한 코드가 수행하는 작업을 진정으로 대표하기 위해 예제를 증류하지 않았 음을 의미 할 수도 있습니다.
FinnNk

답변:


9

동료가 실제 단위 테스트와 통합 테스트를 혼동 할 수 있습니다. 제품이 API 인 경우 통합 테스트를 NUnit 테스트 사례로 프로그래밍 할 수 있습니다. 어떤 사람들은 그것이 단위 테스트라고 잘못 생각합니다.

동료들에게 다음과 같이 설득 할 수 있습니다 (이미 이미 알고있는 것이 확실합니다. 동료에게 지적하면 도움이 될 수 있습니다).

  • 테스트 범위 . 이러한 통합 테스트의 실제 테스트 범위 백분율을 측정하십시오. 이것은 테스트 범위를 실행 한 적이없는 사람들을위한 현실 점검입니다. 입력이 여러 층 떨어져있을 때 모든 논리 경로를 실행하기가 어렵 기 때문에 테스트 범위는 20 %에서 50 % 사이에서 최고가됩니다. 더 많은 적용 범위를 얻으려면 동료가 실제 격리 된 단위 테스트를 작성해야합니다.
  • 구성 . 테스트중인 동일한 소프트웨어를 배포하면 다른 환경에서 테스트를 실행하는 것이 얼마나 어려운지 동료에게 보여줄 수 있습니다. 다양한 파일, DB 연결 문자열, 원격 서비스 URL 등의 경로-모두 합산됩니다.
  • 실행 시간 . 테스트가 실제 단위 테스트가 아니고 메모리에서 실행될 수 없으면 실행하는 데 많은 시간이 걸립니다.

12

내부 / 개인 코드에서 단위 테스트를 사용하는 이유는 외부 지원 API와 정확히 동일합니다.

  • 버그가 반복되는 것을 방지합니다 (회귀 테스트 스위트의 일부인 단위 테스트).
  • 코드가 작동한다는 것을 문서화 (실행 파일 형식으로!)합니다.
  • "코드 작동"의 의미에 대한 실행 가능한 정의를 제공합니다.
  • 그것들은 코드가 실제로 스펙과 일치 함을 증명하는 자동화 된 수단을 제공합니다 (위의 포인트에 의해 정의 된 바와 같이).
  • 예기치 않은 입력이있을 때 장치 / 클래스 / 모듈 / 함수 / 방법이 실패하는 방법을 보여줍니다.
  • 그들은 유닛을 사용하는 방법에 대한 예제를 제공하는데, 이것은 새로운 팀 멤버들에게 훌륭한 문서입니다.

8

당신이 생각하는 방식대로 사적인 것을 의미한다면, 아니오-당신은 그것을 단위 테스트해서는 안됩니다. 관찰 가능한 행동 / 상태 만 유닛 테스트해야합니다. TDD의 "적색 녹색 리 팩터"주기 뒤의 요점이 없을 수도 있습니다 (먼저 테스트하지 않으면 동일한 원칙이 적용됨). 테스트가 작성되고 통과되면 리팩토링을 수행하는 동안 테스트가 변경되는 것을 원하지 않습니다. 개인 기능을 단위 테스트해야하는 경우 공용 기능에 대한 단위 테스트에 결함이 있음을 의미합니다. 공개 코드를 중심으로 테스트를 작성하는 것이 어렵고 복잡한 경우 클래스가 너무 많이 수행되거나 문제가 명확하게 정의되지 않은 것일 수 있습니다.

더구나 시간이 지남에 따라 단위 테스트는 아무런 가치도 추가하지 않고 공을 쇠약하게하여 사슬을 늦추 게됩니다 (예 : 구현 변경 (예 : 복제 최적화 또는 제거)는 단위 테스트에 영향을 미치지 않습니다). 그러나 내부 코드는 행동 / 상태가 관찰 가능하기 때문에 단위 테스트를 거쳐야합니다 (제한된 방식으로).

처음 유닛 테스트를했을 때 개인 물건을 유닛 테스트하기 위해 모든 종류의 트릭을 가져 왔지만 지금은 몇 년 동안 벨트 아래에서 시간 낭비보다 나쁜 것으로 보았습니다.

다음은 약간 어리석은 예입니다. 물론 실제 상황에서는 다음보다 더 많은 테스트가 필요합니다.

정렬 된 문자열 목록을 반환하는 클래스가 있다고 가정 해보십시오. 실제로 목록을 정렬하는 방법이 아니라 결과가 정렬되어 있는지 확인해야합니다. 목록을 정렬하는 단일 알고리즘으로 구현을 시작할 수 있습니다. 완료되면 정렬 알고리즘을 변경하면 테스트를 변경할 필요가 없습니다. 이 시점에서 단일 테스트가 있습니다 (정렬이 클래스에 포함되어 있다고 가정).

  1. 결과가 정렬되어 있습니까?

이제 두 가지 알고리즘을 원한다고 가정하십시오 (아마도 하나는 다른 환경에서는 더 효율적이지만 다른 알고리즘에서는 그렇지 않음). 각 알고리즘은 다른 클래스와 클래스 선택에 의해 제공 될 수 있으며 일반적으로해야합니다. 모의를 사용하여 선택한 시나리오를 사용하지만 원래 테스트는 여전히 유효하며 관찰 가능한 동작 / 상태 만 확인하므로 변경할 필요가 없습니다. 3 가지 테스트로 끝납니다.

  1. 결과가 정렬되어 있습니까?
  2. 시나리오 (초기 목록이 거의 처음부터 정렬되어 있다고 가정 해 봅시다) 알고리즘 X를 사용하여 문자열을 정렬하는 클래스에 대한 호출이 있습니까?
  3. 시나리오 (초기 목록이 임의의 순서로 나열 됨)가 알고리즘 Y를 사용하여 문자열을 정렬하는 클래스에 대한 호출입니까?

대안은 클래스 내에서 개인 코드 테스트를 시작하는 것입니다. 이로부터 아무것도 얻지 못합니다. 위의 테스트는 단위 테스트와 관련하여 알아야 할 모든 것을 알려줍니다. 개인 테스트를 추가하면 직선 자켓을 만들 수 있습니다. 결과가 정렬되었는지뿐만 아니라 정렬 방법을 확인하면 얼마나 많은 작업이 필요합니까?

이 유형의 테스트는 동작이 변경되고 개인 코드에 대한 테스트 작성을 시작하고 창을 벗어나는 경우에만 변경되어야합니다.


1
아마도 "개인"의 의미에 대한 오해가있을 수 있습니다. 우리 시스템에서 코드의 99 %는 "비공개 (private)"이며, 시스템의 구성 요소 중 하나를 자동화 / 원격 제어하기위한 작은 API가 있습니다. 다른 모든 모듈의 코드를 테스트하는 단위를 의미합니다.
Wizard79

4

여기에는 또 다른 이유가 있습니다. 가상의 경우 외부 API와 개인 부품의 단위 테스트 중에서 선택해야 할 경우 개인 부품을 선택합니다.

모든 개인 부품에 대해 테스트가 적용되는 경우 이러한 개인 부품으로 구성된 API는 거의 100 %까지만 커버되어야하며 상위 계층에만 적용됩니다. 그러나 이것은 얇은 층일 것입니다.

반면에 API 만 테스트 할 때는 가능한 모든 코드 경로를 완전히 다루기가 어려울 수 있습니다.


+1 "반면에 ..."그러나 다른 것이 없다면, 실패가 가장 큰 피해를 줄 수있는 테스트를 추가하십시오.
Tony Ennis

2

시간 낭비 ( "우리는 또 다른 돈 버는 프로젝트를 코딩 할 수 있습니다!") 또는 재귀 적 ( "그런 다음 테스트 사례에 대한 테스트 사례를 작성해야합니다!")처럼 보이기 때문에 사람들이 단위 테스트를 받아들이 기가 어렵습니다. 나는 둘 다 말하는 죄가 있습니다.

버그를 처음 발견하면 완벽하지 않다는 사실 (프로그래머가 얼마나 빨리 잊어 버리는 지)에 직면해야합니다. "흠"


단위 테스트의 또 다른 측면은 코드를 테스트 할 수 있도록 작성해야한다는 것입니다. 일부 코드는 쉽게 테스트 할 수 있고 일부 코드는 좋은 프로그래머가 "흠"이되지 않는다는 것을 인식합니다.


동료에게 단위 테스트가 외부 API에만 유용한 이유를 물었습니까?


단위 테스트의 가치를 보여주는 한 가지 방법은 불쾌한 버그가 발생할 때까지 기다린 다음 단위 테스트로 어떻게 버그를 예방할 수 있었는지 보여주는 것입니다. 그것은 그들의 얼굴에 그것을 문지르는 것이 아니라, 그들의 마음에, 단위 테스트를 아이보리 타워 이론에서 실제의 현실로 옮기는 것입니다.

다른 방법은 동일한 오류가 두 번 발생할 때까지 기다리는 것입니다 . "우장 님, 지난주에 문제가 발생한 후 null을 테스트하는 코드를 추가했지만 이번에는 사용자가 빈 것을 입력했습니다!"


예를 들면. 코드에 대한 단위 테스트를 작성한 다음 상사에게 값을 표시하십시오. 그런 다음 상사가 하루 동안 피자를 먹으며 프레젠테이션을하는지 확인하십시오.


마지막으로, 나는 우리가 자극하려고 할 때 느끼는 안도감을 말할 수 없으며 단위 테스트에서 녹색 막대를 얻습니다.


2

개인 코드에는 두 가지 종류가 있습니다 : 공개 코드에 의해 호출되는 개인 코드 (또는 공개 코드에 의해 호출되는 개인 코드에 의해 호출되는 개인 코드) 결국 공개에 의해 호출 되지 않는 개인 코드입니다. 암호.

전자는 이미 공개 코드 테스트를 통해 테스트를 거쳤습니다. 호출 할 수 없습니다 후자 캔 모두에 따라서는 테스트하지 삭제해야합니다.

TDD를 수행 할 때는 테스트되지 않은 개인 코드가 존재하지 않습니다.


우리 시스템에서 99 %의 코드는 세 번째 종류입니다 : 개인 코드는 공개 코드에 의해 호출되지 않으며 시스템에 필수적입니다 (시스템의 최소 부분에만 외부 공개 API가 있음).
Wizard79

1
"TDD를 수행 할 때는 테스트되지 않은 개인 코드가 존재할 수 없습니다." <-테스트가 특정 분기를 포괄하는 유일한 테스트라는 것을 모르고 테스트 사례를 삭제합니다. 좋습니다.이 코드는 "현재 테스트되지 않은"코드이지만 나중에 코드를 변경하는 사소한 리팩토링을 쉽게 볼 수 있습니다. 테스트 스위트 만 더 이상 다루지 않습니다.
Frank Shearar

2

단위 테스트는 코드 단위를 테스트하는 것입니다. 단위가 무엇인지 정의하는 것은 당신에게 달려 있습니다. 동료는 단위를 API 요소로 정의합니다.

어쨌든 API 테스트는 개인 코드도 행사해야합니다. 코드 범위를 단위 테스트 진행률의 지표로 정의하면 모든 코드를 테스트하게됩니다. 코드의 일부에 도달하지 못한 경우 동료에게 세 가지 선택 사항을 제공하십시오.

  • 해당 부분을 다루는 다른 테스트 사례를 정의하고
  • 단위 테스트의 맥락에서 다루어 질 수 없지만 다른 상황에서 다루어 져야하는 이유를 정당화하기위한 코드 분석
  • 정당화되지 않은 데드 코드를 제거하십시오.

우리 시스템에서 API는 최소한의 부분이므로 타사 응용 프로그램에 대한 자동화 / 원격 제어가 가능합니다. API 만 테스트하면 1 % 코드 적용이 가능합니다.
Wizard79
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.