유용성에 따른 단위 테스트 유형


13

가치 관점에서 볼 때 연습에서 두 그룹의 단위 테스트를 봅니다.

  1. 사소한 논리를 테스트하는 테스트. 그것들을 (구현 전 또는 후에) 작성하면 몇 가지 문제 / 잠재적 인 버그가 드러나고 나중에 논리가 변경 될 경우 확신을 가질 수 있습니다.
  2. 아주 사소한 논리를 테스트하는 테스트. 이러한 테스트는 테스트하는 것보다 문서 코드 (일반적으로 모의 코드)와 유사합니다. 이러한 테스트의 유지 관리 워크 플로는 "일부 논리가 변경되고 테스트가 빨간색으로 바뀌 었습니다. 하느님 께서이 테스트를 작성해 주셔서 감사합니다"가 아니라 "일부 사소한 코드가 변경되었습니다. . 대부분의 경우 이러한 시험은 유지해야 할 가치가 없습니다 (종교적인 이유는 제외). 그리고 많은 시스템에서 저의 경험에 따르면이 테스트는 모든 테스트의 80 %와 같습니다.

나는 단위 테스트 주제에 대한 다른 사람들이 가치에 의한 분리와 그것이 분리에 어떻게 대응하는지 알아 내려고 노력하고 있습니다. 그러나 내가 주로 보는 것은 풀 타임 TDD 선전 또는 테스트는 쓸모가 없으며 코드 작성 선전입니다. 나는 중간에 뭔가에 관심이 있습니다. 자신의 생각이나 기사 / 종이 / 책에 대한 언급은 환영합니다.


3
단위 테스트는 원래 단위 테스트 세트를 통해 한 번 알려진 알려진 특정 버그를 회귀 버그를 방지하는 역할을하는 별도의 그룹으로 검사합니다.
Konrad Morawski

6
이 두 번째 종류의 테스트는 일종의 "마찰 변화"로 보는 것입니다. 그들의 유용성을 할인하지 마십시오. 사소한 코드조차도 코드베이스 전체에 파급 효과를 갖는 경향이 있으며, 이러한 종류의 마찰을 도입하는 것은 개발자에게 장애물로 작용 하여 일부 변덕 스럽거나 개인적인 취향보다는 오히려 실제로 필요한 것을 변경 합니다.
Telastyn

3
@ Telastyn-귀하의 의견에 대한 모든 것이 나에게 완전히 화가 보인다. 누가 의도적으로 코드를 변경하기 어렵게 만들었습니까? 개발자가 적합하다고 생각되는 코드를 변경하지 못하게하는 이유는 무엇입니까? 그들은 나쁜 개발자입니까?
Benjamin Hodgson

2
어쨌든 코드를 변경하는 것이 "파급 효과"를 갖는 경향이 있다면 코드 에 디자인 문제있는 것 입니다.이 경우 개발자는 합리적인만큼 리팩토링하도록 권장해야합니다. 깨지기 쉬운 테스트는 리팩토링을 적극적으로 권장하지 않습니다 (테스트 실패; 누가 테스트를 실제로 수행하지 않는 테스트의 80 % 중 하나인지 여부를 고민 할 수있는 사람은 다른 복잡한 방법을 찾을뿐입니다). 그러나 당신은 이것을 바람직한 특성으로 생각하는 것 같습니다 ... 나는 그것을 전혀 얻지 못했습니다.
Benjamin Hodgson

2
어쨌든 OP는 Rails 제작자의 블로그 게시물이 흥미로울 수 있습니다. 그의 요점을 과도하게 단순화하려면 80 %의 테스트를 버려야합니다.
Benjamin Hodgson

답변:


14

단위 테스트에서 차이가 발생하는 것이 당연하다고 생각합니다. 그것을 제대로 자연스럽게 다른 의견이 본질적으로있는 방법에 대한 여러 가지 의견이 있습니다 잘못은 . DrDobbs에는 최근에 답변이 끝날 때 연결되는이 문제를 탐구하는 기사가 꽤 있습니다.

테스트에서 볼 수있는 첫 번째 문제는 테스트하기가 쉽다는 것입니다. 대학 C ++ 수업에서 우리는 1 학기와 2 학기 모두에 단위 시험에 노출되었습니다. 우리는 한 학기 동안 일반적으로 프로그래밍에 대해 전혀 알지 못했습니다. C ++을 통해 프로그래밍의 기초를 배우려고했습니다. 이제 학생들에게 "오, 당신은 매년 작은 세금 계산기를 썼습니다! 이제 제대로 작동하는지 확인하기 위해 몇 가지 단위 테스트를 작성하십시오." 결과는 분명해야합니다. 제 시도를 포함하여 모두 끔찍했습니다.

단위 테스트 작성에 어려움을 겪고 더 나아지기를 원하면 곧 최신 스타일의 테스트 또는 다른 방법론에 직면하게됩니다. 테스트 방법론을 통해 테스트 우선 또는 DrDobbs의 Andrew Binstock이 수행하는 작업 (코드와 함께 테스트를 작성)과 같은 사례를 언급합니다. 둘 다 장단점이 있으며 나는 화염 전쟁을 일으킬 것이기 때문에 주관적인 세부 사항에 들어가기를 거부합니다. 어떤 프로그래밍 방법이 더 좋은지 혼동하지 않는다면 테스트 스타일이 트릭을 수행 할 것입니다. TDD, BDD, 속성 기반 테스트를 사용해야합니까? JUnit에는 TDD와 속성 기반 테스트 사이의 경계를 흐리게하는 이론이라는 고급 개념이 있습니다. 언제 사용할 것인가?

tl; dr 테스트를 잘못하기가 쉽고, 믿기지 않을 정도로 의견이 많으며, 적절한 테스트 환경에서 부지런하고 전문적으로 사용되는 한 테스트 방법이 본질적으로 더 낫다고 생각하지 않습니다. 내 생각에 개발에 대한 실패없는 임시 접근 방식을 보장하는 데 사용되는 주장 또는 위생 테스트에 대한 확장이 훨씬 쉽고 훨씬 쉬워졌습니다.

주관적인 견해로는 더 나은 구절이 없기 때문에 테스트의 "단계"를 작성하는 것을 선호합니다. 필요한 경우 모의를 사용하여 테스트 클래스를 개별적으로 테스트합니다. 이들은 아마도 JUnit 또는 이와 유사한 것으로 실행될 것입니다. 그런 다음 통합 또는 승인 테스트를 작성합니다.이 테스트는 개별적으로 실행되며 보통 하루에 몇 번만 실행됩니다. 이것들은 사소한 사용 사례입니다. JUnit이 쉽게 제공 할 수없는 자연 언어로 기능을 표현하는 것이 좋기 때문에 보통 BDD를 사용합니다.

마지막으로 자원. 이들은 주로 다른 언어와 다른 프레임 워크로 단위 테스트를 중심으로 상충되는 의견을 제시 할 것입니다. 그들은 당신의 생각을 너무 많이 조작하지 않는 한 자신의 의견을 구성 할 수 있도록 이념과 방법론의 구분을 제시해야합니다. :)

[1] Andrew Binstock의 애자일 부패

[2] 이전 기사의 답변에 대한 답변

[3] Bob 아저씨의 민첩성 부패에 대한 대응

[4] Rob Myers의 민첩성 부패에 대한 대응

[5] 오이 테스트를 방해하는 이유는 무엇입니까?

[6] 당신은 잘못 요리하고 있습니다

[7] 도구에서 멀어짐

[8] '해설이있는 로마 숫자 카타'에 대한 해설

[9] 해설을 가진 로마 숫자 Kata


1
친숙한 논쟁 중 하나는 연간 세금 계산기의 기능을 테스트하기 위해 테스트를 작성하는 경우 단위 테스트를 작성하지 않는 것입니다. 그것은 통합 테스트입니다. 계산기는 상당히 간단한 실행 단위로 분류되어야하며 단위 테스트 후 해당 단위를 테스트해야합니다. 해당 장치 중 하나가 제대로 작동하지 않으면 (테스트가 시작되지 않음) 기초 벽의 일부가 녹아웃되는 것처럼 코드를 복구해야합니다 (일반적으로 테스트는 아님). 그 중 하나이거나 더 이상 필요하지 않으며 폐기해야 할 코드를 식별했습니다.
Craig

1
@Craig : 정확하게! 이것이 올바른 테스트를 작성하는 방법을 모른다는 의미입니다. 대학생으로서, 세금 징수 원은 SOLID를 제대로 이해하지 못하고 작성된 큰 수업이었습니다. 이것이 다른 어떤 것보다 통합 테스트에 지나지 않는다고 생각하는 것은 당연하지만, 그것은 우리에게 알려지지 않은 용어였습니다. 우리는 교수님에 의한 "단위"테스트에만 노출되었습니다.
IAE

5

두 가지 유형의 테스트를 모두 거쳐 적절한 곳에서 사용하는 것이 중요하다고 생각합니다.

당신이 말했듯이, 두 가지 극단이 있으며 나는 솔직히 어느 쪽에도 동의하지 않습니다.

핵심은 단위 테스트가 비즈니스 규칙과 요구 사항을 포함해야한다는 것 입니다. 시스템이 개인의 나이를 추적해야하는 요구 사항이있는 경우, "사소한"테스트를 작성하여 나이가 음이 아닌 정수인지 확인하십시오. 시스템에 필요한 데이터 영역을 테스트하고 있습니다. 사소하지만 시스템 의 매개 변수를 적용하기 때문에 가치 가 있습니다 .

더 복잡한 테스트와 마찬가지로 가치도 가져와야합니다. 물론, 요구 사항은 아니지만 어딘가에 상아탑에서 시행해야하는 것을 검증하는 테스트를 작성할 수 있지만, 고객이 지불하는 요구 사항을 검증하는 테스트를 작성하는 데 더 나은 시간입니다. 예를 들어, 왜 코드가 네트워크가 아닌 로컬 파일에서 온 스트림 일 때 시간 초과되는 입력 스트림을 처리 할 수있는 코드를 검증하는 테스트를 작성해야합니까?

나는 단위 테스트를 굳게 믿고 TDD가 사용되는 곳이면 어디든 사용합니다. 단위 테스트는 코드를 변경할 때 품질 향상 및 "실패"동작의 형태로 가치를 제공합니다. 그러나 명심해야 할 오래된 80/20 규칙도 있습니다. 어느 시점에서 테스트를 작성할 때 수익이 감소 할 수 있으며, 더 많은 테스트를 작성하여 측정 할 가치가있는 경우에도보다 생산적인 작업으로 이동해야합니다.


시스템이 개인의 나이를 추적하도록 테스트를 작성하는 것은 단위 테스트 (IMO)가 아닙니다. 그것은 통합 테스트입니다. 단위 테스트는 일반적인 실행 단위 (일명 "프로 시저")를 테스트합니다. 즉, 기본 날짜 및 모든 단위 (일, 주 등)의 오프셋에서 연령 값을 계산합니다. 내 요점은 코드의 나머지 부분이 나머지 시스템에 이상한 외출 의존성을 가져서는 안된다는 것입니다. 그냥 두 개의 입력 값에서 나이를 계산하며,이 경우 단위 테스트에서 올바른 동작을 확인할 수 있습니다. 오프셋이 음의 나이를 생성하면 예외가 발생할 수 있습니다.
Craig

나는 어떤 계산도 언급하지 않았다. 모델이 데이터를 저장하면 데이터가 올바른 도메인에 속하는지 확인할 수 있습니다. 이 경우 도메인은 음이 아닌 정수 세트입니다. 계산은 MVC에서 컨트롤러에서 수행해야하며이 예에서는 연령 계산이 별도의 테스트입니다.

4

여기에 내가 취하는 것이 있습니다 : 모든 테스트에는 비용이 있습니다

  • 초기 시간과 노력 :
    • 무엇을 테스트하고 테스트하는 방법에 대해 생각하십시오
    • 테스트를 구현하고 테스트 대상을 테스트하고 있는지 확인하십시오.
  • 지속적인 유지 보수
    • 코드가 자연스럽게 진화함에 따라 테스트가 수행해야 할 작업을 계속 수행하는지 확인
  • 테스트 실행
    • 실행 시간
    • 결과 분석

또한 모든 테스트에서 혜택을 제공하려고합니다 (제 경험상 거의 모든 테스트에서 혜택이 제공됨).

  • 사양
  • 코너 케이스를 강조
  • 회귀 방지
  • 자동 검증
  • API 사용 예
  • 특정 속성의 정량화 (시간, 공간)

따라서 많은 테스트를 작성하면 가치가있을 것입니다. 이것이 복잡 해지는 곳은 그 값을 비교하기 시작할 때입니다.

이제 시간과 노력이 제한됩니다. 최소 비용으로 최대한의 이익을 제공하는 일을하고자합니다. 그리고 나는 그것이 매우 어려운 일이라고 생각합니다. 적어도 그것이 얻지 못하거나 비용이 많이 드는 지식이 필요할 수 있기 때문입니다.

그리고 그것은이 서로 다른 접근법들 사이의 실질적인 문제입니다. 나는 그들이 유익한 테스트 전략을 모두 식별했다고 생각합니다. 그러나 각 전략은 일반적으로 비용과 이점이 다릅니다. 또한 각 전략의 비용과 이점은 프로젝트, 도메인 및 팀의 특성에 따라 크게 달라질 수 있습니다. 즉, 여러 가지 최상의 답변이있을 수 있습니다.

경우에 따라 테스트없이 코드를 펌핑하면 최상의 이점 / 비용이 제공 될 수 있습니다. 다른 경우에는 철저한 테스트 스위트가 더 나을 수 있습니다. 또 다른 경우에는 디자인을 개선하는 것이 가장 좋습니다.


2

무엇 이다 단위 정말, 시험? 그리고 여기에 실제로 큰 이분법이 있습니까?

버퍼 끝에서 문자 그대로 1 비트를 읽는 것이 프로그램을 완전히 중단 시키거나 프로그램이 완전히 부정확 한 결과를 초래하거나 최근 "HeartBleed"TLS 버그에 의해 입증 된 것처럼 안전한 시스템을 넓게 배치하는 분야에서 일합니다. 결함의 직접적인 증거없이 생산합니다.

이러한 시스템에서 모든 복잡성을 제거하는 것은 불가능합니다. 그러나 우리의 임무는 가능한 한 복잡성을 최소화하고 관리하는 것입니다.

예를 들어 예약이 3 개의 다른 시스템에 성공적으로 게시되고 로그 항목이 작성되고 이메일 확인이 발송되는지 확인하는 테스트가 단위 테스트입니까?

나는 아니오 라고 말할 것 입니다. 그것은 통합 테스트입니다. 그리고 그들은 분명히 자신의 자리를 가지고 있지만, 다른 주제이기도합니다.

통합 테스트는 전체 "기능"의 전체 기능을 확인하기 위해 작동합니다. 그러나이 기능의 배후 코드는 간단하고 테스트 가능한 빌딩 블록, 즉 "단위"로 세분화해야합니다.

따라서 단위 테스트의 범위는 매우 제한적이어야합니다.

이는 단위 테스트에서 테스트 코드의 범위가 매우 제한적 임을 의미합니다 .

이는 훌륭한 디자인의 기둥 중 하나가 복잡한 문제를 서로 독립적으로 테스트 할 수있는 더 작은 단일 목적 조각 (가능한 범위까지)으로 나누는 것임을 암시합니다.

당신이 끝내는 것은 신뢰할 수있는 기초 구성 요소로 구성된 시스템이며, 코드의 기본 단위 중 하나라도 간단하고 작은 범위로 제한된 테스트를 작성하여 정확히 그 사실을 알려 주었기 때문에 알고 있습니다.

대부분의 경우 장치 당 여러 테스트를 수행해야 할 수도 있습니다. 테스트 자체는 단순해야하며 가능한 한 한 가지 동작 만 테스트해야합니다.

사소하고 복잡한 논리를 테스트하는 "단위 테스트"의 개념은 약간의 옥시 모론이라고 생각합니다.

따라서 이러한 종류의 고의적 인 설계 고장이 발생한 경우 , 테스트 된 코드 단위의 기본 기능이 변경 되지 않는 한 , 세계에서 어떻게 단위 테스트가 갑자기 오 탐지를 생성 할 수 있습니까? 만약 일이있다, 당신은 더 나은 플레이의 일부가 아닌 명백한 파급 효과가있다 생각합니다. 오탐 (false positive)을 생성하는 것으로 보이는 깨진 테스트는 실제로 일부 변경으로 인해 코드베이스에서 더 많은 종속성이 손상되었다는 경고이며 실제로 검사하고 수정해야합니다.

이러한 단위 중 일부 (대다수)는 모의 객체를 사용하여 테스트해야 할 수도 있지만, 더 복잡하거나 정교한 테스트를 작성해야한다는 의미는 아닙니다.

예약 시스템 내 인위적인 예를 다시가는, 당신은 정말 라이브 예약 데이터베이스 또는 타사 서비스 (또는 심지어 "dev에"예) 때마다 당신이에 떨어져 요청을 전송 할 수없는 단위 테스트 코드를.

따라서 동일한 인터페이스 계약을 제시하는 모형을 사용합니다. 테스트는 상대적으로 작고 결정적인 코드 덩어리의 동작을 검증 할 수 있습니다. 보드 전체에 초록색이 표시되면 기초 를 구성 하는 블록 이 파손되지 않았 음을 나타냅니다.

그러나 개별 단위 테스트의 논리 자체는 가능한 한 단순하게 유지됩니다.


1

이것은 물론 내 의견 일뿐이지만 지난 몇 개월 동안 fsharp (C # 배경에서 온)로 함수형 프로그래밍을 배우면서 몇 가지 사실을 깨닫게되었습니다.

OP가 언급했듯이 일반적으로 우리는 매일 두 가지 유형의 "단위 테스트"를 봅니다. 일반적으로 가장 귀중하지만 "알고리즘"과 "추상"에 관한 것이 아닌 시스템의 80 %에 대해서는 어려운 테스트 방법에 대한 테스트를 수행합니다.

다른 유형은 추상화 상호 작용을 테스트하는 것이며 일반적으로 조롱과 관련이 있습니다. 내 의견으로는,이 테스트는 대부분 응용 프로그램 디자인으로 인해 필요합니다. 그것들을 생략하면 이상한 버그와 spagetti 코드가 발생할 위험이 있습니다. 사람들은 테스트를 먼저 수행 해야하는 경우가 아니라면 디자인을 올바르게 생각하지 않기 때문입니다. 문제는 테스트 방법론이 아니라 시스템의 기본 디자인입니다. 명령형 또는 OO 언어로 구축 된 대부분의 시스템은 "부작용", 즉 "이를 수행하지만 아무 말도하지 않음"에 대한 의존성을 가지고 있습니다. 부작용에 의존하는 경우 비즈니스 요구 사항이나 작업이 일반적으로 그 일부이므로 테스트해야합니다.

부작용에 대한 의존성을 피하고 불변성을 통한 상태 변경 / 추적을 피하는보다 기능적인 방식으로 시스템을 설계 할 때, 더 많은 작업을 명확하게 테스트하는 "in and out"테스트에 더 집중할 수 있습니다. 그리고 당신이 거기에 도착하는 방법이 적습니다. 불변성과 같은 것들이 동일한 문제에 대한 훨씬 간단한 솔루션이라는 관점에서 당신에게 줄 수있는 것에 놀랄 것입니다. 더 이상 "부작용"에 의존하지 않을 때 거의 추가 비용없이 병렬화 및 비동기식 프로그래밍과 같은 일을 할 수 있습니다.

Fsharp에서 코딩을 시작한 이래로 나는 아무것도 모의 프레임 워크가 필요하지 않았으며 IOC 컨테이너에 대한 의존성을 완전히 잃어 버렸습니다. 필자의 테스트는 비즈니스 요구와 가치에 의해 주도되며, 명령형 프로그래밍에서 컴포지션을 달성하기 위해 일반적으로 필요한 무거운 추상화 계층이 아닙니다.

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