단위 테스트의 "단위"에서 이해되는 것


9

내가 "단위"아래의 이론에서 이해하는 바와 같이 사람들은 방법 (OOP)을 의미합니다. 그러나 실제로 일부 메소드를 격리하여 검증하는 테스트는 매우 취약한 동작 테스트입니다 (결과를 검증하는 것이 아니라 일부 종속 메소드가 호출 된 사실을 검증). 그래서 나는 단위별로 밀접하게 관련된 소수의 클래스를 이해하는 많은 사람들을 봅니다. 이 경우 외부 종속성 만 조롱 / 스터 빙되며 실제 구현 내부에있는 종속성이 사용됩니다. 이 경우 더 많은 상태, 의미 (사양에 따라) 및 너무 약한 테스트가 없습니다. 따라서 문제는 이러한 접근 방식에 대해 어떻게 생각하고 두 번째 접근 단위 테스트를 호출하는 것이 유효합니까, 아니면 저수준 통합 테스트 일 수 있습니까?

이러한 테스트 방법 중 하나를 사용하여 TDD를 적용 할 때 고려해야 할 몇 가지 사항이 있다면 귀하의 의견에 감사드립니다.

답변:


11

원래 TDD는 민첩한 움직임에서 비롯된 것으로, 테스트 코드에 잘 정의 된 사양에 따라 코딩 된 내용이 올바르게 유지되도록 테스트를 미리 작성했습니다. 코드를 수정했을 때 코드의 동작을 변경하지 않았 음을 증명하기 위해 테스트에 의존 할 수 있다는 점에서 리팩토링의 매우 중요한 측면으로 나타났습니다.

그런 다음 사람들이 와서 코드에 대한 정보를 알고 있다고 생각하고 단위 테스트 작성을 돕기 위해 테스트 스텁을 생성 할 수 있다고 생각했습니다.이 모든 것이 잘못되었다고 생각합니다.

테스트 스텁은 수행중인 작업에 대한 단서가없는 컴퓨터에 의해 생성되며, 모든 방법에 대해 무의식적으로 스텁을 생성합니다. 즉, 해당 방법의 복잡성이나 격리 테스트에 적합한 지 여부에 관계없이 각 방법에 대한 테스트 사례가 있습니다.

이것은 TDD 방법론의 잘못된 끝에서 테스트 중입니다. TDD에서는 코드의 기능을 파악한 다음이를 달성하는 코드를 생성해야합니다. 이것은 코드가 코드가 수행하는 것이 아니라 수행하는 것이 아니라는 것을 입증하는 테스트를 작성한다는 점에서 스스로 충족됩니다. 메소드 기반 테스트 스텁의 자동 생성과 결합하여 코드의 각 작은 부분을 증명하는 데 많은 시간을 낭비하므로 작은 조각을 모두 모을 때 쉽게 잘못 될 수 있습니다.

Fowler는 자신의 책에서 테스트를 설명 할 때 고유 한 주요 방법으로 각 클래스를 테스트하는 것을 언급했습니다. 그는 이것을 개선했지만 개념은 여전히 ​​동일합니다. 전체 클래스를 테스트하여 전체적으로 작동하며 모든 테스트가 함께 묶여 모든 메소드의 상호 작용을 입증하여 클래스를 정의 된 기대에 재사용 할 수 있습니다.

테스트 툴킷이 우리에게 장애를 일으킨다 고 생각합니다. 툴킷이 실제로 할 수있는 유일한 방법이라고 생각하는 길을 안내했습니다. 코드에서 최상의 결과를 얻으려면 스스로 더 생각해야합니다. 맹목적으로 테스트 스텁에 테스트 코드를 넣는 것은 통합 테스트에서 작업을 반복해야 함을 의미합니다 (그렇게하려면 지금 중복되는 단위 테스트 단계를 완전히 건너 뛰지 마십시오). 또한 사람들이 100 % 테스트 범위를 확보하는 데 많은 시간을 낭비하고 코드를 통합 테스트하기가 더 쉬워 지도록 많은 양의 조롱 코드와 데이터를 만드는 데 많은 시간을 소비 함을 의미합니다. 데이터 종속성, 단위 테스트가 최선의 옵션이 아닐 수 있음)

마지막으로, 메소드 기반 단위 테스트의 취약성은 문제를 보여줍니다. 리팩토링은 단위 테스트와 함께 사용하도록 설계되었습니다. 리팩토링으로 인해 테스트가 항상 중단되는 경우 전체 접근 방식에서 심각한 문제가 발생했습니다. 리팩토링은 메소드를 생성하고 삭제하는 것을 좋아하기 때문에 메소드 별 블라인드 기반 테스트 방식은 원래 의도 한 것이 아닙니다.

많은 메소드가 테스트를 작성할 것이라는 데는 의문의 여지가 없지만 클래스의 모든 공개 메소드는 테스트해야하지만 단일 테스트 케이스의 일부로 함께 테스트한다는 개념에서 벗어날 수는 없습니다. 예를 들어, set 및 get 메소드가있는 경우 데이터를 넣고 내부 구성원이 올바르게 설정되었는지 확인하는 테스트를 작성하거나 각각을 사용하여 일부 데이터를 넣은 다음 다시 가져 와서 여전히 동일하고 깨지지 않았습니다. 이것은 각각의 메소드가 아닌 클래스를 테스트하고 있습니다. setter가 helper private 메소드에 의존하는 경우 괜찮습니다. 전체 클래스를 테스트하지 않고 setter가 작동하는지 확인하기 위해 private 메소드를 조롱 할 필요가 없습니다.

종교가이 주제를 다루고 있다고 생각하기 때문에, 이제는 '행동 중심'과 '테스트 중심'개발로 알려진 편협을 봅니다. 단위 테스팅의 원래 개념은 행동 중심 개발이었습니다.


10

단위는 가장 일반적으로 " 응용 프로그램의 테스트 가능한 가장 작은 부분 "으로 정의됩니다 . 그렇지 않은 경우가 종종 있습니다. 이는 방법을 의미합니다. 그리고 네, 이것은 의존적 인 메소드의 결과를 테스트하지 말고 메소드가 호출된다는 것을 의미합니다 (그리고 가능하면 해당 메소드에 대한 모든 테스트에서 한 번만).

당신은 이것을 연약하다고 부릅니다. 나는 그것이 틀렸다고 생각한다. 취약한 테스트는 관련없는 코드를 약간 변경하여 테스트하는 것입니다. 즉, 테스트중인 기능과 관련이없는 코드에 의존하는 것입니다.

그러나 당신이 정말로 말하는 것은 의존성이없는 방법을 테스트하는 것이 철저하지 않다는 것입니다. 그 점에 동의합니다. 또한 응용 프로그램을 만들기 위해 코드 단위가 올바르게 연결되어 있는지 확인하기 위해 통합 테스트가 필요합니다.

이것이 바로 행동 중심 개발 , 특히 수용 테스트 중심 개발 이 해결하려는 문제입니다. 그러나 이것이 단위 테스트 / 테스트 중심 개발의 필요성을 제거하지는 않습니다. 그것은 단지 그것을 보완합니다.


나는 행동 테스트가 연약하다고 말하고 싶었다. 코드베이스가 변경되는 동안 종종 거짓 부정이됩니다. 이 상태 테스트를 덜 발생 (그러나 상태 테스트는 단위 테스트를 위해 매우 거의 없습니다)
SiberianGuy

@ idsa : 나는 당신의 정의에 의해 조금 길을 잃었습니다. 동작 테스트는 지정된대로 동작을 테스트하는 통합 테스트입니다. 원래의 질문을 읽으면 상태 테스트를 말할 때도 같은 것을 의미하는 것 같습니다.
pdr

상태에 따라 상태를 확인하는 테스트, 일부 기능의 결과를 의미합니다. 행동으로 나는 결과를 검증하지 않는 테스트를 의미하지만, 어떤 기능이 호출되었다는 사실
SiberianGuy

@Idsa :이 경우, 나는 완전히 동의하지 않습니다. 상태 테스트라고 부르는 것을 통합이라고 부릅니다. 당신이 행동이라고 부르는 것, 나는 단위를 부릅니다. 정의에 따른 통합 테스트는 더 취약합니다. 구글 "통합 테스트 단위는 깨지기 쉬운"당신은 내가 혼자가 아니라는 것을 알 수 있습니다.
pdr

테스트에 관한 기사가 있지만 그 중 어느 것이 귀하의 의견을 공유합니까?
SiberianGuy

2

이름에서 알 수 있듯이 각 테스트에서 원자 주제를 테스트하고 있습니다. 이러한 주제는 일반적으로 단일 방법입니다. 행복한 길, 가능한 오류 등을 다루기 위해 여러 테스트에서 동일한 방법을 테스트 할 수 있습니다. 내부 메커니즘이 아닌 동작을 테스트하고 있습니다. 따라서 단위 테스트는 실제로 클래스의 공용 인터페이스, 즉 특정 메소드를 테스트하는 것입니다.

단위 테스트에서는 메소드를 독립적으로 테스트해야합니다. 그렇지 않으면 '실제'종속성이있는 장치를 테스트하면 통합 테스트가됩니다. 두 가지 유형의 테스트를위한 시간과 장소가 있습니다. 단위 테스트는 단일 과목이 예상대로 독립 실행되도록합니다. 통합 테스트는 '실제'주제가 올바르게 작동하는지 확인합니다.


1
자동화 된 툴링이 방법을 다루지 않거나 최선을 다하지 않기 때문에 자동화 된 툴링을 선호하기 때문에 유닛은 고립 된 주제입니다. 여기서 '절연'이 핵심입니다. 메서드를 테스트하더라도 개인 메서드도 테스트해야합니다.
gbjbaanb

1

내 경험 법칙 : 버그를 포함하기에 여전히 복잡한 가장 작은 코드 단위.

이것이 메소드 또는 클래스 또는 서브 시스템인지 여부는 특정 코드에 따라 다르지만 일반적인 규칙은 없습니다.

예를 들어, 간단한 getter / setter 메소드를 개별적으로 테스트하거나 다른 메소드 만 호출하는 랩퍼 메소드를 테스트하기위한 값을 제공하지 않습니다. 클래스가 얇은 랩퍼 또는 어댑터 인 경우 전체 클래스도 테스트하기가 너무 간단 할 수 있습니다. 테스트 할 유일한 것이 모의 메소드를 호출하는 것이라면 테스트중인 코드는 얇습니다.

다른 경우에는 단일 방법으로 복잡한 계산을 수행 할 수 있으며 이는 별도로 테스트하는 데 유용합니다.

많은 경우에 복잡한 부분은 개별 클래스가 아니라 클래스 간의 통합입니다. 따라서 한 번에 두 개 이상의 클래스를 테스트합니다. 일부는 이것이 단위 테스트가 아니라 통합 테스트라고 말하지만 용어를 신경 쓰지 마십시오. 복잡한 위치를 테스트해야하며 이러한 테스트는 테스트 스위트의 일부 여야합니다.

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