유닛 테스트

Unit testing

컴퓨터 프로그래밍에서 유닛 테스트소스 코드의 개별 단위(하나 이상의 컴퓨터 프로그램 모듈과 관련된 제어 데이터, 사용 절차 및 조작 절차)를 테스트하여 [1]사용하기에 적합한지 여부를 판단하는 소프트웨어 테스트 방법입니다.

역사

유닛 테스트 전에는 캡처 리플레이 테스트 도구가 표준이었습니다.1997년 Kent Beck와 Erich Gamma는 Java [2]개발자들에게 인기를 끌었던 유닛 테스트 프레임워크인 JUnit을 개발하여 출시하였습니다.Google은 2005~[3]2006년경에 자동화된 테스트를 도입했습니다.

묘사

유닛 테스트는 일반적으로 소프트웨어 개발자에 의해 작성 및 실행되는 자동 테스트로, 애플리케이션의 일부("유닛")가 설계에 적합하고 의도한 [4]대로 동작하는지 확인합니다.프로시저 프로그래밍에서는 유닛이 모듈 전체일 수 있지만 일반적으로 개별 기능 또는 프로시저입니다.객체 지향 프로그래밍에서 유닛은 클래스 또는 개별 [5]메서드와 같은 전체 인터페이스인 경우가 많습니다.테스트 가능한 최소 유닛에 대해 먼저 테스트를 작성한 후 이들 유닛 간의 복합 동작을 작성함으로써 복잡한 애플리케이션에 [4]대한 포괄적인 테스트를 구축할 수 있습니다.

발생할 수 있는 문제를 분리하기 위해 각 테스트 케이스를 개별적으로 테스트해야 합니다.메서드 스터브, 모의 객체,[6] 가짜테스트 하네스같은 대체품을 사용하여 모듈을 분리하여 테스트할 수 있습니다.

개발 중에 소프트웨어 개발자는 장치의 정확성을 검증하기 위해 테스트에 기준 또는 양호한 결과를 코드화할 수 있습니다.테스트 케이스 실행 중 프레임워크는 모든 기준에 불합격한 테스트를 기록하고 요약하여 보고합니다.이를 위해 가장 일반적으로 사용되는 접근법은 테스트 - 함수 - 기대치입니다.

매개 변수화된 테스트를 사용하면 장치 테스트의 쓰기 및 유지 관리를 보다 빠르게 수행할 수 있습니다.이를 통해 서로 다른 입력 세트를 사용하여 하나의 테스트를 여러 번 실행할 수 있으므로 테스트 코드 중복이 줄어듭니다.일반적으로 닫힌 방법이고 불변 조건인 전통적인 단위 검정과는 달리, 매개 변수화된 검정에는 모든 매개 변수 집합이 사용됩니다.파라미터화된 테스트는 TestNG, JUnit 및 그 에서 지원됩니다.넷파트너, 쉬닛.장치 테스트에 적합한 매개변수를 수동으로 제공하거나 경우에 따라 테스트 프레임워크에 의해 자동으로 생성됩니다.최근 몇 년 동안 [7][8][9]사전 정의된 입력 세트에 동일한 실행 단계를 사용하는 일반 매개 변수화 테스트와는 달리 이론의 개념을 활용하여 테스트 사례를 활용하여 보다 강력한(단위) 테스트를 작성하는 지원이 추가되었습니다.

이점

유닛 테스트의 목적은 프로그램의 각 부품을 분리하여 각 부품이 [1]올바른지 확인하는 것입니다.유닛 테스트는 코드 조각이 충족해야 하는 엄격한 서면 계약을 제공합니다.그 결과, 몇 가지 이점이 있습니다.

유닛 테스트는 개발 사이클 초기에 문제를 발견합니다.여기에는 프로그래머 구현의 오류와 장치 사양의 결함 또는 누락된 부분이 포함됩니다.철저한 테스트 세트를 작성하는 과정은 필자가 입력, 출력 및 오류 조건을 고려하도록 강요하며, 따라서 유닛이 원하는 동작을 보다 명확하게 정의합니다.코딩이 시작되기 전 또는 코드가 처음 작성되었을 때 버그를 발견하는 비용은 버그를 나중에 검출, 식별 및 수정하는 비용보다 상당히 낮습니다.릴리스된 코드의 버그로 인해 소프트웨어의 [10][11][12]최종 사용자에게 비용이 많이 드는 문제가 발생할 수도 있습니다.코드가 잘못 작성되면 단위 테스트가 불가능하거나 어려울 수 있습니다. 따라서 단위 테스트는 개발자가 더 나은 방식으로 기능 및 객체를 구성하도록 강요할 수 있습니다.

Extreme Programming과 Scrum 모두에서 자주 사용되는 Test-Driven Development(TDD; 테스트 구동 개발)에서는 코드 자체 작성 전에 유닛 테스트가 생성됩니다.테스트에 합격하면 그 코드는 완료된 것으로 간주됩니다.코드가 변경되거나 빌드를 통한 자동화된 프로세스를 통해 대규모 코드 베이스가 개발될 때 해당 기능에 대해 동일한 유닛 테스트가 자주 실행됩니다.유닛 테스트가 실패하면 변경된 코드 또는 테스트 자체의 버그로 간주됩니다.그런 다음 장치 테스트를 통해 고장 또는 고장 위치를 쉽게 추적할 수 있습니다.유닛 테스트는 테스트 담당자 또는 고객에게 코드를 전달하기 전에 개발팀에 문제를 경고하기 때문에 개발 프로세스 초기에 잠재적인 문제가 발견됩니다.

유닛 테스트를 통해 프로그래머는 나중에 코드를 리팩터링하거나 시스템 라이브러리를 업그레이드하여 모듈이 올바르게 동작하는지 확인할 수 있습니다(: 회귀 테스트).이 절차는 변경으로 인해 결함이 발생할 때마다 신속하게 식별할 수 있도록 모든 기능 및 방법에 대한 테스트 케이스를 작성하는 것입니다.유닛 테스트에서는 설계 계약을 위반할 가능성이 있는 변경을 검출합니다.

단위 테스트는 단위 자체의 불확실성을 줄일 수 있으며 상향식 시험 방식으로 사용할 수 있습니다.프로그램의 부품을 먼저 테스트하고 부품의 합계를 테스트하면 통합 테스트가 훨씬 [citation needed]쉬워집니다.

유닛 테스트는 시스템에 대한 일종의 살아있는 문서를 제공합니다.유닛에 의해 제공되는 기능과 그 사용법을 알고자 하는 개발자는 유닛의 인터페이스([citation needed]API)에 대한 기본적인 이해를 얻기 위해 유닛 테스트를 살펴볼 수 있습니다.

유닛 테스트 케이스에는 유닛의 성공에 중요한 특성이 포함되어 있습니다.이러한 특성은 장치의 적절한/부적절한 사용 및 장치에 의해 갇힐 부정적인 동작을 나타낼 수 있습니다.유닛 테스트 케이스 자체는 이러한 중요한 특성을 문서화합니다.다만, 많은 소프트웨어 개발 환경은,[citation needed] 개발중의 제품을 문서화하기 위해서 코드에만 의존하는 것은 아닙니다.

테스트 중심 접근법을 사용하여 소프트웨어를 개발할 경우, 인터페이스를 지정하기 위한 단위 테스트 작성과 테스트 통과 후 수행된 리팩터링 활동의 조합이 정식 설계를 대체할 수 있습니다.각 단위 테스트는 클래스, 방법 및 관측 가능한 [citation needed]동작을 지정하는 설계 요소로 볼 수 있습니다.

제한 및 단점

가장 사소한 프로그램을 제외한 모든 실행 경로를 평가할 수 없기 때문에 테스트에서 프로그램의 모든 오류를 탐지할 수는 없습니다. 문제는 판별할 수 없는 정지 문제의 슈퍼셋입니다.유닛 테스트에서도 마찬가지입니다.또한 장치 테스트는 정의상 장치 자체의 기능만 테스트합니다.따라서 통합 오류나 광범위한 시스템 수준 오류(복수의 유닛에 걸쳐 수행되는 기능 또는 성능 등의 비기능 테스트 영역 등)는 포착되지 않습니다.유닛 테스트는 다른 소프트웨어 테스트액티비티와 함께 실시해야 합니다.이것은, 특정의 에러의 유무만을 나타낼 수 있기 때문입니다.이러한 액티비티는, 에러가 완전하게 없는 것을 증명할 수 없습니다.모든 실행 경로 및 가능한 모든 입력에 대해 올바른 동작을 보장하고 오류가 발생하지 않도록 하려면 다른 기술, 즉 소프트웨어 컴포넌트에 예기치 않은 [citation needed]동작이 없음을 증명하는 정식 방법을 적용해야 합니다.

유닛 테스트의 계층 구조는 통합 테스트와 동일하지 않습니다.주변 장치와의 통합은 통합 테스트에 포함되어야 하지만 장치 [citation needed]테스트에는 포함되지 않아야 합니다.통합 테스트는 일반적으로 여전히 수동 테스트에 크게 의존하고 있습니다.고레벨 또는 글로벌 범위의 테스트는 자동화하기 어렵기 때문에 수동 테스트가 더 빠르고 [citation needed]저렴하게 표시되는 경우가 많습니다.

소프트웨어 테스트는 조합의 문제입니다.예를 들어, 모든 부울 의사 결정문에는 적어도 두 가지 테스트가 필요합니다. 하나는 "참"의 결과이고 다른 하나는 "거짓"의 결과입니다.그 결과 프로그래머는 코드 한 줄당 3~5줄의 테스트 [13]코드가 필요한 경우가 많습니다.이것은 분명히 시간이 걸리고 그 투자는 노력할 가치가 없을지도 모른다.쉽게 테스트할 수 없는 문제가 있습니다.를 들어 비확정적이거나 여러 스레드가 관련된 문제 등입니다.또한 유닛 테스트용 코드는 테스트 중인 코드와 마찬가지로 버그가 발생할 수 있습니다."신화 속의 인간-월"에 나오는 프레드 브룩스는 "두 개의 크로노미터로 바다에 가지 말고 한 세 [14]개를 가져가라."라고 인용한다.즉, 두 의 크로노미터가 모순된다면, 어느 것이 맞는지 어떻게 알 수 있습니까?

단위 테스트 작성과 관련된 또 다른 과제는 현실적이고 유용한 테스트를 설정하는 것의 어려움입니다.테스트 대상 어플리케이션의 일부가 시스템 전체의 일부처럼 동작하도록 관련 초기 조건을 작성해야 합니다.이러한 초기 조건이 올바르게 설정되지 않으면 테스트는 현실적인 맥락에서 코드를 실행하지 않을 것이며, 이는 단위 테스트 [15]결과의 가치와 정확성을 감소시킨다.

유닛 테스트의 이점을 얻으려면 소프트웨어 개발 프로세스 전체에서 엄격한 규율이 필요합니다.수행된 테스트뿐만 아니라 이 소프트웨어 또는 기타 장치의 소스 코드에 수행된 모든 변경 사항도 신중하게 기록해야 합니다.버전 관리 시스템의 사용은 필수적입니다.장치의 최신 버전이 이전에 통과한 특정 테스트에 불합격하면 버전 제어 소프트웨어는 그 이후 [citation needed]장치에 적용된 소스 코드 변경 목록을 제공할 수 있습니다.

또한 테스트 사례의 실패를 정기적으로 검토하고 [16]즉시 대처하기 위한 지속 가능한 프로세스를 구현하는 것도 중요합니다.이러한 프로세스가 구현되지 않고 팀의 워크플로우에 내재되어 있지 않으면 응용 프로그램이 유닛 테스트 스위트와 동기화되지 않고 발전하여 잘못된 긍정 결과가 증가하고 테스트 스위트의 효과가 감소합니다.

임베디드 시스템 소프트웨어의 유닛 테스트에는 다음과 같은 독특한 과제가 있습니다.소프트웨어는 최종적으로 실행되는 플랫폼과는 다른 플랫폼에서 개발되기 때문에 실제 도입 환경에서는 데스크톱 프로그램처럼 테스트 프로그램을 [17]쉽게 실행할 수 없습니다.

단위 테스트는 메서드에 입력 매개 변수와 출력이 있을 때 가장 쉽습니다.이 메서드의 주요 기능이 애플리케이션 외부의 무엇과 상호 작용하는 경우 유닛 테스트를 만드는 것은 쉽지 않습니다.예를 들어, 데이터베이스와 함께 작동하는 방법은 실제 데이터베이스 상호 [18][better source needed]작용만큼 포괄적이지 않은 데이터베이스 상호 작용의 목업을 작성해야 할 수 있습니다.

다음은 구현의 여러 요소를 지정하는 Java 테스트 사례 세트입니다.첫째, Adder라는 인터페이스와 AdderImpl이라는 제로 인수 컨스트럭터를 가진 구현 클래스가 있어야 합니다.또한 Adder 인터페이스에는 2개의 정수 파라미터를 가진 add라는 메서드가 있어야 합니다.이 메서드는 다른 정수를 반환합니다.또한 여러 테스트 방법에 걸쳐 작은 범위의 값에 대해 이 방법의 동작을 지정합니다.

Import 스태틱 org.junit.Assert.assertEquals;  수입품 org.junit.시험;  일반의 학급 테스트 추가 {      @테스트     일반의 무효 test Sum Positive Numbers One And One() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(2, 가산기.더하다(1, 1));     }      // 양수 1과 2를 추가할 수 있습니까?     @테스트     일반의 무효 test Sum Positive Numbers One And Two() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(3, 가산기.더하다(1, 2));     }      // 양수 2와 2를 추가할 수 있습니까?     @테스트     일반의 무효 test Sum Positive Numbers Two And Two() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(4, 가산기.더하다(2, 2));     }      // 0은 중립입니까?     @테스트     일반의 무효 테스트 Sum Zero Neutral() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(0, 가산기.더하다(0, 0));     }      // 음수 -1과 -2를 추가할 수 있습니까?     @테스트     일반의 무효 test Sum Negative Numbers(음수)() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(-3, 가산기.더하다(-1, -2));     }      //양과 음을 추가할 수 있습니까?     @테스트     일반의 무효 테스트 합계와 음성() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(0, 가산기.더하다(-1, 1));     }      // 큰 숫자는 어떻습니까?     @테스트     일반의 무효 테스트 Sum Large Numbers() {         덧셈 가산기 = 신규 추가임플();         assert Equals(동일)(2222, 가산기.더하다(1234, 988));     } } 

이 경우 유닛 테스트는 처음에 작성된 후 원하는 솔루션의 형태와 동작을 지정하는 설계 문서로서 기능하지만 구현 세부 사항은 프로그래머에게 남겨지지 않습니다.「가장 간단한 조작을 실시할 수 있는 방법」에 따라, 테스트에 합격하는 가장 쉬운 솔루션을 다음에 나타냅니다.

인터페이스 덧셈 {     인트 더하다(인트 a, 인트 b); } 학급 추가임플 용구 덧셈 {     일반의 인트 더하다(인트 a, 인트 b) {         돌아가다 a + b;     } } 

실행 가능한 사양으로

단위 검정을 설계 규격으로 사용하면 다른 설계 방법보다 한 가지 중요한 이점이 있습니다.설계 문서(유닛 테스트 자체)를 사용하여 구현을 검증할 수 있습니다.개발자가 설계에 따라 솔루션을 구현하지 않는 한 테스트는 통과하지 못할 것입니다.

유닛 테스트에는 UML 다이어그램과 같은 도식 사양에 대한 접근성이 다소 부족하지만 자동화된 도구를 사용한 유닛 테스트에서 생성될 수 있습니다.대부분의 현대 언어에는 무료 도구(일반적으로 IDE의 확장으로 사용 가능)가 있습니다.xUnit 프레임워크에 기반한 도구와 같은 무료 도구는 사용자가 사용할 수 있도록 뷰의 그래픽 렌더링을 다른 시스템에 아웃소싱합니다.

적용들

익스트림 프로그래밍

유닛 테스트는 자동화된 유닛 테스트 프레임워크에 의존하는 익스트림 프로그래밍의 기반입니다.이 자동화된 유닛 테스트 프레임워크는 서드파티(: xUnit)가 될 수도 있고 개발 그룹 내에서 생성될 수도 있습니다.

익스트림 프로그래밍에서는 테스트 주도형 개발을 위해 유닛 테스트 생성을 사용합니다.개발자는 소프트웨어 요구 사항 또는 결함을 노출하는 단위 테스트를 작성합니다.요건이 아직 구현되지 않았거나 의도적으로 기존 코드의 결함을 노출했기 때문에 이 테스트는 실패합니다.그런 다음 개발자는 다른 테스트와 함께 테스트를 통과하기 위한 가장 간단한 코드를 작성합니다.

시스템 내의 대부분의 코드는 유닛 테스트이지만 반드시 코드를 통과하는 모든 경로는 아닙니다.익스트림 프로그래밍에서는 기존의 "모든 실행 경로 테스트" 방식에서 "가능한 모든 것을 테스트"하는 전략이 필요합니다.이로 인해 개발자는 기존 방식보다 테스트 횟수가 적지만, 이는 문제가 되지 않으며, 모든 실행 경로가 완전히 [citation needed]테스트될 정도로 체계적으로 적용된 경우가 거의 없기 때문에 사실을 다시 기술한 것입니다.Extreme Programming은 테스트가 거의 완전하지 않다는 것을 인식하고(많은 경우 비용이 너무 많이 들고 시간이 오래 걸리기 때문에) 제한된 리소스에 효과적으로 집중하는 방법에 대한 지침을 제공합니다.

결정적으로 테스트 코드는 모든 중복을 제거하여 구현 코드와 동일한 품질로 유지된다는 점에서 1등급 프로젝트 아티팩트로 간주됩니다.개발자는 유닛 테스트 코드를 테스트하는 코드와 함께 코드 저장소에 배포합니다.Extreme Programming의 철저한 유닛 테스트를 통해 코드 개발 및 리팩터링, 심플한 코드 통합, 정확한 문서 작성, 모듈러 설계 등 위에서 언급한 이점을 얻을 수 있습니다.이러한 단위 검정은 회귀 검정의 한 형태로 지속적으로 실행됩니다.

유닛 테스트는 Emergent Design의 개념에도 매우 중요합니다.긴급설계는 리팩터링에 크게 의존하기 때문에 유닛 테스트는 필수 [19]컴포넌트입니다.

유닛 테스트 프레임워크

유닛 테스트 프레임워크는 대부분의 경우 컴파일러 스위트의 일부로 배포되지 않는 서드파티 제품입니다.다양한 언어로 개발되어 유닛 테스트 프로세스를 단순화할 수 있습니다.

일반적으로 테스트 대상 장치를 실행하고 어설션, 예외 처리 또는 기타 제어 흐름 메커니즘을 사용하여 장애를 시그널링하는 클라이언트 코드를 작성함으로써 특정 프레임워크의 지원 없이 장치 테스트를 수행할 수 있습니다.프레임워크가 없는 단위 테스트는 단위 테스트 채택을 위한 진입 장벽이 있다는 점에서 가치가 있다. 단위 테스트가 거의 없는 것이 없는 것보다 낫다. 반면, 일단 프레임워크가 구축되면 단위 테스트를 추가하는 것이 비교적 [20]쉬워진다.일부 프레임워크에서는 많은 고급 장치 테스트 기능이 없거나 수동으로 코딩해야 합니다.

언어 레벨 유닛 테스트 지원

일부 프로그래밍 언어는 장치 테스트를 직접 지원합니다.이러한 문법은 라이브러리(서드파티 또는 표준)를 Import하지 않고 유닛테스트를 직접 선언할 수 있도록 합니다.또한 유닛 테스트의 부울 조건은 유닛 이외의 테스트코드에서 사용되는 부울식과 같은 구문으로 표현될 수 있습니다.예를 들어 다음과 같습니다.if그리고.while진술들.

유닛 테스트를 지원하는 언어는 다음과 같습니다.

일부 언어에는 유닛 테스트 지원이 내장되어 있지 않지만 유닛 테스트 라이브러리 또는 프레임워크가 확립되어 있습니다.이러한 언어는 다음과 같습니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ a b Kolawa, Adam; Huizinga, Dorota (2007). Automated Defect Prevention: Best Practices in Software Management. Wiley-IEEE Computer Society Press. p. 75. ISBN 978-0-470-04212-0.
  2. ^ Gulati, Shekhar (2017). Java Unit Testing with JUnit 5 : Test Driven Development with JUnit 5. Rahul Sharma. Berkeley, CA: Apress. p. 8. ISBN 978-1-4842-3015-2. OCLC 1012347252.
  3. ^ Winters, Titus (2020). Software engineering at Google : lessons learned from programming over time. Tom Manshreck, Hyrum Wright (1st ed.). Sebastopol, CA. ISBN 978-1-4920-8274-3. OCLC 1144086840.
  4. ^ a b Hamill, Paul (2004). Unit Test Frameworks: Tools for High-Quality Software Development. O'Reilly Media, Inc. ISBN 9780596552817.
  5. ^ Xie, Tao. "Towards a Framework for Differential Unit Testing of Object-Oriented Programs" (PDF). Retrieved 23 July 2012.
  6. ^ Fowler, Martin (2 January 2007). "Mocks aren't Stubs". Retrieved 1 April 2008.
  7. ^ "Getting Started with xUnit.net (desktop)".
  8. ^ "Theories". GitHub.
  9. ^ "Parameterized tests". GitHub.
  10. ^ Boehm, Barry W.; Papaccio, Philip N. (October 1988). "Understanding and Controlling Software Costs" (PDF). IEEE Transactions on Software Engineering. 14 (10): 1462–1477. doi:10.1109/32.6191. Retrieved 13 May 2016.
  11. ^ "Test Early and Often". Microsoft.
  12. ^ "Prove It Works: Using the Unit Test Framework for Software Testing and Validation". National Instruments. 21 August 2017.
  13. ^ Cramblitt, Bob (20 September 2007). "Alberto Savoia sings the praises of software testing". Retrieved 29 November 2007.
  14. ^ Brooks, Frederick J. (1995) [1975]. The Mythical Man-Month. Addison-Wesley. p. 64. ISBN 978-0-201-83595-3.
  15. ^ Kolawa, Adam (1 July 2009). "Unit Testing Best Practices". Retrieved 23 July 2012.
  16. ^ daVeiga, Nada (6 February 2008). "Change Code Without Fear: Utilize a regression safety net". Retrieved 8 February 2008.
  17. ^ Kucharski, Marek (23 November 2011). "Making Unit Testing Practical for Embedded Development". Retrieved 20 July 2020.
  18. ^ http://wiki.c2.com/ ® Unit Tests And Databases
  19. ^ "Agile Emergent Design". Agile Sherpa. 3 August 2010. Archived from the original on 22 March 2012. Retrieved 8 May 2012.
  20. ^ Bullseye Testing Technology (2006–2008). "Intermediate Coverage Goals". Retrieved 24 March 2009.
  21. ^ "Crystal Spec". crystal-lang.org. Retrieved 18 September 2017.
  22. ^ "Unit Tests - D Programming Language". D Programming Language. D Language Foundation. Retrieved 5 August 2017.
  23. ^ "testing - The Go Programming Language". golang.org. Retrieved 3 December 2013.
  24. ^ "Unit Testing · The Julia Language". docs.julialang.org. Retrieved 15 June 2022.
  25. ^ Python Documentation (2016). "unittest -- Unit testing framework". Retrieved 18 April 2016.
  26. ^ Welsh, Noel; Culpepper, Ryan. "RackUnit: Unit Testing". PLT Design Inc. Retrieved 26 February 2019.
  27. ^ Welsh, Noel; Culpepper, Ryan. "RackUnit Unit Testing package part of Racket main distribution". PLT Design Inc. Retrieved 26 February 2019.
  28. ^ "Minitest (Ruby 2.0)". Ruby-Doc.org.
  29. ^ The Rust Project Developers (2011–2014). "The Rust Testing Guide (Rust 0.12.0-pre-nightly)". Retrieved 12 August 2014.
  30. ^ Sierra, Stuart. "API for clojure.test - Clojure v1.6 (stable)". Retrieved 11 February 2015.
  31. ^ "Pester Framework". GitHub. Retrieved 28 January 2016.

추가 정보

  • Feathers, Michael C. (2005). Working Effectively with Legacy Code. Upper Saddle River, NJ: Prentice Hall Professional Technical Reference. ISBN 978-0131177055.

외부 링크