단위 테스트 코드가“냄새가 나는”것이 정말로 중요합니까?


52

일반적으로 복사 및 붙여 넣기 및 기타 모든 종류의 나쁜 습관을 사용하여 단위 테스트를 함께 수행합니다. 단위 테스트는 일반적으로 매우 추악하게 보이고, "코드 냄새"로 가득 차 있지만 이것이 정말로 중요합니까? 나는 "실제"코드가 "좋은"것이기 만하면 항상 나 자신에게 말한다. 또한 단위 테스트에는 일반적으로 스터 빙 기능과 같은 다양한 "스 멜리 해킹"이 필요합니다.

제대로 설계되지 않은 ( "취약한") 단위 테스트에 대해 어떻게 우려해야합니까?


8
항상 복사하는 코드를 수정하는 것이 얼마나 어려울 수 있습니까?
JeffO

7
테스트의 코드 냄새는 코드의 나머지 부분에서 숨겨진 냄새의 지표 일 수 있습니다. 왜 테스트가 "실제"코드가 아닌 것처럼 접근합니까?
HorusKol

답변:


75

단위 테스트 냄새가 중요합니까? 물론 이죠 그러나, 그들은은 서로 다른 단위 테스트가 다른 목적을 제공하고 자신의 디자인을 알리는 긴장의 다른 세트를 가지고 있기 때문에 코드는 냄새에서. 코드의 많은 냄새는 테스트에 적용되지 않습니다. 내 TDD 사고 방식을 감안할 때 실제로 코드가 테스트를 충족시키기 위해 단위 테스트 냄새가 코드 냄새보다 중요 하다고 주장합니다 .

일반적인 단위 테스트 냄새는 다음과 같습니다.

  • 취약성 : 사소하거나 관련없는 코드 변경으로 인해 테스트가 자주 예기치 않게 실패합니까?
  • State Leak : 실행 순서에 따라 테스트가 다르게 실패합니까?
  • 설정 / 해체 블로 트 : 설정 / 해체 블록이 길고 길어지고 있습니까? 그들은 어떤 종류의 비즈니스 로직을 수행합니까?
  • 느린 런타임 : 테스트를 실행하는 데 시간이 오래 걸립니까? 개별 단위 테스트 중 실행하는 데 10 분의 1 초 이상이 걸립니까? (예, 진지합니다. 1/10 초입니다.)
  • 마찰 : 기존 테스트로 인해 새로운 테스트를 작성하기가 어렵습니까? 리팩토링 중에 테스트 실패로 어려움을 겪고 있습니까?

냄새의 중요성은 디자인이나 기타 더 근본적인 문제, 즉 "연기가있는 곳, 불이있는 곳"의 유용한 지표라는 점입니다. 테스트 냄새 만 발견하지 말고 근본적인 원인도 찾으십시오.

반면에 여기에 단위 테스트에 대한 몇 가지 모범 사례가 있습니다.

  • 신속하고 집중적 인 피드백 : 테스트는 실패를 신속하게 격리하고 원인에 대한 유용한 정보를 제공해야합니다.
  • 테스트 코드 거리 최소화 : 테스트와 테스트를 구현하는 코드 사이에 분명하고 짧은 경로가 있어야합니다. 장거리는 불필요하게 긴 피드백 루프를 만듭니다.
  • 한 번에 테스트 한 것 : 단위 테스트는 단 한 가지를 테스트해야합니다. 다른 것을 테스트해야 할 경우 다른 테스트를 작성하십시오.
  • 버그 당신이 작성하는 것을 잊어 버린 시험이다 : 당신은 미래에 더 좋고 더 완전한 시험을 작성하지 못함으로 이로부터 무엇을 배울 수 있는가?

2
"단위 테스트는 다른 목적으로 사용되며 디자인에 영향을주는 다른 장력 세트를 가지고 있습니다." 예를 들어, 반드시 DRY가 아닌 DAMP 여야합니다.
Jörg W Mittag

3
@ Jörg Agreed, 그러나 DAMP는 실제로 무엇을 의미합니까? : D
Rein Henrichs

5
@Rein : 설명적이고 의미있는 문구. 또한 완전히 건조되지는 않습니다. codeshelter.wordpress.com/2011/04/07/…
Robert Harvey

+1. 나는 또한 DAMP의 의미를 몰랐다.
egarcia

2
@ironcode 다른 시스템과의 통합을 중단 할 염려없이 한 시스템에서 격리 된 상태로 작업 할 수 없다면, 그것은 나에게 긴밀한 결합 인 것 같습니다. 이것은 긴 런타임과 같은 테스트 냄새를 정확하게 식별하는 목적입니다. 긴밀한 커플 링과 같은 설계 문제를 알려줍니다. 응답은 "아, 그러면 테스트 냄새가 유효하지 않습니다", "이 냄새가 내 디자인에 대해 무엇을 말합니까?"가 아니어야합니다. 시스템의 외부 인터페이스를 지정하는 단위 테스트는 변경 사항이 소비자와의 통합을 방해하는지 여부를 알려주기에 충분해야합니다.
Rein Henrichs

67

걱정하세요. 코드가 예상대로 작동하는지 입증하기 위해 단위 테스트를 작성합니다. 자신감을 가지고 신속하게 리팩토링 할 수 있습니다. 테스트가 깨지기 쉽고 이해하기 어렵거나 유지하기 어려운 경우 코드 기반이 발전함에 따라 테스트 실패를 무시하거나 테스트를 해제하여 테스트 작성의 이점을 대부분 무시합니다.


17
+1 실패한 테스트를 무시하기 시작하면 아무런 가치가 없습니다.

19

방금 며칠 전에 The Unit of Unit Testing을 읽었습니다 . 저자는 생산 코드를 작성하는 것처럼 단위 테스트에 많은주의를 기울 이도록 권장합니다.

잘 작성되지 않았고 유지 관리 할 수없는 테스트를 직접 경험했습니다. 나는 내 자신의 일부를 작성했습니다. 테스트가 유지 보수에 어려움이 있다면 유지되지 않을 것이라는 것이 사실상 보장됩니다. 테스트가 테스트중인 코드와 동기화되지 않으면 거짓말과 속임수가됩니다. 단위 테스트의 모든 요점은 우리가 아무것도 부수 지 않았다는 확신을 심어주는 것입니다. 테스트를 신뢰할 수 없으면 쓸모없는 것보다 나쁩니다.


4
+1 프로덕션 코드와 마찬가지로 테스트를 유지해야합니다
Hamish Smith

이 주제에 관한 또 다른 아주 좋은 책은 Gerard Meszaros의 "xUnit 테스트 패턴-Refatcoring 테스트 코드"입니다.
adrianboimvaser

7

단위 테스트가 실제로 "대부분의"경우 코드를 테스트하는 한. (가끔 가능한 모든 결과를 찾기가 어려우므로 대부분의 경우 의도적으로 말함) 나는 "취약한"코드가 당신의 개인적인 취향이라고 생각합니다. 나는 항상 정크를 파고 무엇이 무엇인지 이해하려고 노력하지 않고 코드를 읽고 몇 초 안에 이해할 수있는 방식으로 코드를 작성합니다. 특히 상당한 시간 후에 다시 돌아올 때.

결론-테스트는 쉽다고 가정합니다. 당신은 "취약한"코드와 혼동하기를 원하지 않습니다.


5
+1 : 단위 테스트 코드를 소홀히하지 마십시오. 가장 멍청한 질문 중 일부는 프로그래밍 변경으로 인해 단위 테스트가 중단되지 않도록 단위 테스트 코드를보다 "강력한"상태로 만드는 것입니다. 조용함. 단위 테스트는 취성을 갖도록 설계되었습니다. 테스트하도록 설계된 응용 프로그램 코드보다 덜 강력하면 괜찮습니다.
S.Lott

1
@ S.Lott 내 대답에 더 잘 설명 된 이유로 동의하고 동의하지 않습니다.
Rein Henrichs

1
@Rein Henrichs : 질문에 설명 된 것보다 훨씬 더 심각한 냄새가납니다. "복사하여 붙여 넣기"와 "꽤보기 흉한"은 테스트가 신뢰할 수없는 위치를 설명하는 냄새만큼 나쁘지 않습니다.
S.Lott

1
@ S.Lott 정확하게, 우리가 "단위 테스트 냄새"에 대해 이야기한다면, 그 구별을하는 것이 중요하다고 생각합니다. 단위 테스트에서 코드 냄새는 종종 그렇지 않습니다. 그것들은 다른 목적을 위해 쓰여졌으며 어떤 상황에서 냄새를 맡게하는 긴장은 다른 상황에서는 매우 다릅니다.
Rein Henrichs

2
@ S.Lott btw 이것은 무시 된 채팅 기능을 사용할 수있는 완벽한 기회 인 것 같습니다 :)
Rein Henrichs

6

명확히. 어떤 사람들은 "테스트가 전혀없는 것보다 낫다"고 말합니다. 나쁘게 작성된 테스트는 개발 시간을 단축시키고, 처음에는 좋은 단위 테스트가 아니기 때문에 "손상된"테스트를 수정하는 데 며칠을 낭비하게됩니다. 지금 저에게있어, 테스트 대신 부담없이 테스트를 수행하기 위해 집중하고있는 두 가지 사항은 다음과 같습니다.

유지 보수성

당신은 결과를 (테스트해야 무슨 일이)가 아닌 방법 ( 어떻게 그런 일이). 테스트 설정은 가능한 한 구현에서 분리되어야합니다. 서비스 요청 등에 대한 결과 만 설정해야합니다.

  • 테스트가 외부에 의존하지 않도록 조롱 프레임 워크를 사용하십시오.
  • 가능한 경우 모의에 대한 스텁을 선호하십시오 (프레임 워크가 구별되는 경우).
  • 테스트에 논리가 없습니다! If, 스위치, For-eaches, case, try-catch 등은 테스트 코드 자체에 버그를 유발할 수 있으므로 모두 큰 문제가되지 않습니다.

가독성

테스트에서 조금 더 반복하는 것이 좋습니다. 프로덕션 코드에서는 읽기 쉽도록 만들면 일반적으로 허용되지 않습니다. 위의 유지 관리 가능성과 균형을 맞추십시오. 시험이 무엇을하고 있는지 명시하십시오!

  • 테스트를 위해 "정렬, 행동, 주장"스타일을 유지하십시오. 이를 통해 시나리오의 설정과 기대를 수행중인 조치 및 주장되는 결과와 분리합니다.
  • 테스트 당 하나의 논리적 어설 션을 유지하십시오 (테스트 이름에 "및"이 있으면 여러 테스트로 나누어야 할 수 있습니다)

결론적으로, 당신은 "취약한"시험에 매우 관심을 가져야합니다. 시험은 시간 낭비로 끝날 수 있으며 가치가 없습니다.

당신은 말했다 :

단위 테스트에는 일반적으로 스터 빙 기능과 같은 다양한 "스 멜리 해킹"이 필요합니다.

Mocking 프레임 워크 사용과 같은 일부 단위 테스트 기술을 읽고 생활을 훨씬 쉽게 할 수있는 것처럼 들릴 수 있습니다. 위의 내용과 그 이상을 다루는 The Art of Unit Testing을 강력히 추천 합니다. 잘못 작성되고 유지하기 어려운 "취약한"테스트로 오랫동안 어려움을 겪고 나서 깨달음을 얻었습니다. 내가 올해 최고의 투자 중 하나입니다!


훌륭한 답변입니다. 작은 퀴즈가 하나 있습니다. "테스트 당 하나의 논리적 어설 션"보다 훨씬 중요한 것은 테스트 당 하나의 동작입니다. 요점은 테스트를 준비하는 데 걸리는 단계 수에 관계없이 "테스트중인 프로덕션 코드 작업"은 하나만 있어야합니다. 해당 조치에 둘 이상의 부작용이 있어야하는 경우 여러 어설 션이있을 수 있습니다.
환멸

5

두 가지 질문이 있습니다.

  • 테스트하고 있다고 생각 하는 것을 테스트하고 있다고 절대적으로 긍정적 입니까?
  • 다른 사람이 단위 테스트를 보면 코드가 무엇을해야하는지 알아낼 있습니까?

단위 테스트에서 반복 작업을 처리하는 방법은 가장 일반적으로 설정 및 해제 코드입니다. 기본적으로 테스트 설정 방법과 테스트 분리 방법이 있습니다. 모든 단위 테스트 프레임 워크에서이를 지원합니다.

단위 테스트는 작고 이해하기 쉬워야합니다. 그렇지 않은데 테스트에 실패한 경우 합리적으로 짧은 시간 내에 문제를 어떻게 해결 하시겠습니까? 코드로 돌아와야 할 때 몇 달 동안 길을 쉽게 찾을 수 있습니다.


5

쓰레기가 냄새를 맡기 시작하면 꺼낼 시간입니다. 테스트 코드는 프로덕션 코드만큼 깨끗해야합니다. 엄마 한테 보여 줄래?


3

다른 답변 외에도 여기에.

단위 테스트의 품질이 나쁜 코드는 단위 테스트 스위트로 제한되지 않습니다.

유닛 테스팅이 담당하는 역할 중 하나는 문서입니다.

단위 테스트 제품군은 API 사용 방법을 찾는 곳 중 하나입니다.

API 호출자는 유닛 테스트 스위트의 일부를 복사하지 않아 다른 곳에서 라이브 코드를 감염시키는 테스트 스위트 코드가 잘못 될 수 있습니다.


3

나는 이것을 합법적 인 질문으로 접근하는 방법을 알아내는 데 시간이 걸렸기 때문에 대답을 거의 제출하지 않았습니다.

프로그래머가 "모범 사례"에 참여하는 이유는 미적인 이유가 아니거나 "완벽한"코드를 원하기 때문이 아닙니다. 시간을 절약하기 때문입니다.

  • 좋은 코드를 읽고 이해하기 쉽기 때문에 시간이 절약됩니다.
  • 버그를 수정해야 할 때 쉽고 빠르게 찾을 수 있기 때문에 시간이 절약됩니다.
  • 코드를 확장 할 때 더 쉽고 빠르기 때문에 시간이 절약됩니다.

따라서 (내 관점에서) 묻는 질문은 시간을 절약하거나 시간을 낭비하는 코드를 작성해야합니까?

그 질문에 내가 말할 수있는 것은 시간이 얼마나 중요합니까?

참고 : 스터 빙, 조롱 및 원숭이 패치는 모두 합법적으로 사용됩니다. 그들은 그들의 사용이 적절하지 않을 때만 "냄새".


2

단위 테스트를 너무 강력하게하지 않기 위해 특별히 노력합니다. 견실 한 이름으로 오류 처리를 시작하는 단위 테스트를 보았습니다. 당신이 끝내는 것은 그들이 잡으려고하는 버그를 삼키는 테스트입니다. 단위 테스트는 또한 작동하기 위해 펑키 한 일을 자주해야합니다. 리플렉션을 사용하는 개인 접근 자의 전체 아이디어를 생각해보십시오. 제작 코드에서 여러 사람을 본다면 10에서 9 번 걱정할 것입니다. 테스트 대상에 대해 더 많은 시간을 투자해야한다고 생각합니다. 코드 청결보다는 오히려. 주요 리팩토링을 수행하는 경우 어쨌든 테스트를 자주 변경해야하므로 왜 함께 해킹하고 소유권이 적고 시간이 오면 다시 작성하거나 재 작업해야 하는가?


2

무거운 저수준 적용 범위를 사용하려는 경우 심각한 수정 작업을 수행 할 때 제품 코드에서보다 테스트 코드에서 더 많은 시간을 소비하게됩니다.

테스트 설정의 복잡성에 따라 코드가 더 복잡 할 수 있습니다. (httpcontext.current와 끔찍한 괴물, 예를 들어 허위 사실을 정확하게 만들려고하는 경우)

귀하의 제품이 기존 인터페이스를 거의 변경하지 않고 단위 레벨 입력을 매우 간단하게 설정하지 않는 한 실제 제품과 같은 테스트에 대한 이해가 가장 중요합니다.


0

코드 냄새는 나중에 변경하거나 이해해야하는 코드의 문제 일뿐입니다.

따라서 주어진 단위 테스트에 "가까이"가야 할 때 코드 냄새를 해결해야한다고 생각합니다.

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