SW Engineering & Testing (11) - Test Driven Development & JUnit

Charlie·2026년 5월 19일

SE&Testing

목록 보기
12/13

1. Other SW Testing Techniques

TDD 외에도 5가지의 소프트웨어 테스팅 기법에 대해서 존재한다.
(이쪽이 시험에 잘 나온다고 말씀하심)

1) Random Testing(무작위 테스팅)

명세서(Specifications) 없이 무작위로 독립적인 입력값을 생성하여 수행하는 블랙박스 테스팅 기법으로, 주로 예외(Exceptions)가 발생하는지 확인하는 데 사용된다.

2) Mutation Testing(돌연변이 테스팅)

새로운 소프트웨어 테스트를 설계하거나 기존 테스트 스위트(Test Suites)의 품질을 평가하기 위해 사용된다. 의도적으로 결함을 삽입한 '돌연변이(Mutant)'를 기존 테스트가 얼마나 잘 탐지하는지(탐지율)를 측정하는 방식으로 테스팅을 진행하며, 이 때 '돌연변이(Mutant)'는 주로 구문 삭제/복제, 불리언 식 변경, 산술/관계 연산자 변경, 동일 범위 내 변수 교체 등의 '돌연변이 연산자'를 사용한다.
.

3) Concolic Testing(콘콜릭 테스팅)

구체적 실행과 심볼릭(Symbolic) 실행을 결합한 의미로 기존 무작위 테스팅의 한계를 극복하기 위한 화이트박스 테스팅 기법이다. 코드 커버리지를 극대화할 목적으로 심볼릭 실행과 정리 증명기(Theorem prover)를 사용하여 Uncovered path를 찾고 테스트 입력값을 자동으로 생성한다.

4) Regression Testing(회귀 테스팅)

패치, 기능 향상, 환경 설정 변경 등이 발생한 후 새로운 버그가 나타나지 않았는지 확인하는 테스트이다. 이 테스팅 기법은 전제가 존재하는데, 변경 사항이 이전에 잘 동작하던 코드에 새로운 결함을 도입하지 않았음을 보장해야 한다.

5) Conformance Testing(적합성 테스팅)

제품이나 시스템이 규정된 요구사항 명세, 계약 또는 규제를 제대로 준수하고 있는지 판단하는 테스트이다.

2. Test-Driven Development(TDD)

1) Background

보통 프로그래머들은 테스트를 지루한 작업으로 여기거나 다른 부서의 역할로 미루는 경향이 있다. 개발하는 것에 의미를 크게 두고 Product를 만들고 나면 유지보수에 소홀하기 쉽다. 그러다보니 여러번 테스트를 반복할수록 꼼꼼함이 떨어지는 상황이 빈번히 발생한다.

이러한 상황을 해결하기 위해 등장한 방법론이 TDD 방법론이다.

2) TDD(Test-Driven Development)란?

코드를 작성하기 전에 테스트 코드를 먼저 작성하고, 이 테스트를 통과하는 것을 개발의 핵심 원동력으로 삼아 테스트와 코드 개발을 교차(Inter-leave)로 진행하는 개발 방식.

TDD는 도구의 지원을 받아 개발자가 코드 변경 시마다 반복 가능한 테스트를 유지하고 선택적으로 실행할 수 있도록 장려하기 위해 등장했다. 엄밀히는 애자일 방법론인 익스트림 프로그래밍(XP)의 일부로 도입되었지만, 계획 주도 개발 프로세스에서도 활용할 수 있다.

3) Process

TDD는 아래의 프로세스를 거친다. 일종의 사이클을 가지고 테스트를 수행하고 테스트가 실패하면 해당 기능을 지속적으로 빌드업하고 이후 테스트가 실행 완료될 경우 다음 기능 구현으로 넘어가는 방식으로 진행된다. 일련의 절차는 아래와 같다.

1. 몇 줄의 코드로 구현할 수 있는 작은 기능 단위(Increment)를 식별한다.
2. 해당 기능을 위한 자동화된 테스트를 작성한다.
3. 모든 테스트를 실행. 아직 실제 코드가 없으므로 새로운 테스트는 실패한다.
4. 테스트를 통과하기 위한 실제 기능 코드를 작성한다.
5. 다시 테스트를 실행하여 모든 테스트가 성공하면 다음 기능 구현으로 넘어간다.

4) Benefit

TDD는 좋은 테스팅 기법이다. 고로 여러 장점을 가지는데 아래의 4가지의 장점을 중심으로 생각해볼 수 있다.

1) 코드 커버리지
작성된 모든 코드는 최소 하나 이상의 연관된 테스트를 가지게 된다는 의미이다.
2) 회귀 테스트가 진행
프로그램이 개발됨에 따라 회귀 테스트 스위트가 점진적으로 구축되어 변경으로 인한 오류를 방지한다.
3) 디버깅 간소화
만약 테스트를 실패한다하더라도, 직전에 작성한 새로 추가된 코드에 문제가 있음이 명확하므로 디버깅이 간단하다.
4) 시스템 문서화의 역할을 수행
작성된 테스트 자체가 코드가 무엇을 해야하는지 설명하는 일종의 Document(문서)의 역할을 수행한다.

5) Apply

TDD는 테스트 케이스를 언제 만들 것인지에 따라 '기존 개발 방법(전체 개발 후 전체 테스트)', '모듈별 테스트', '모듈별 TDD', '전체 TDD' 등 다양한 전략으로 접근할 수 있다.

3. JUnit의 개념 및 활용

1) Introduction

켄트 벡(Kent Beck)이 90년대 중반 Smalltalk용으로 개발한 xUnit을 바탕으로, 켄트 벡과 에릭 감마가 비행기 안에서 공동 개발한 자바 TDD의 표준 도구이다. JUnit은 기존 프로그램을 건드리지 않고 테스트 수행이 가능하며 사용자가 결과값을 일일이 눈으로 확인하지 않아도 된다. xUnit 툴은 어떤 언어를 사용하느냐에 따라 다양한 방식으로 개발될 수 있다.

2) O-O Program

void main() 함수는 프로그램 수행의 시작 함수로 Java Application은 main() 내부에서 모든 제어를 담당한다. O-O program은 기존 프로그램을 건드리지 않고 테스트 수행이 가능하다. 또한 사용자가 결과값을 확인하지 않아도 된다.

아래와 같은 방식으로 Test Case를 수행한다.

테스트는 Precondition(사전 조건) 설정 ➔ 해당 코드 수행 ➔ 결과값 확인(Assert)의 흐름으로 진행된다. 결과를 검증하기 위해 assertEquals, assertFalse, assertTrue, Assert(Not)Null, Assert(Not)Same 등 다양한 Assert 메서드를 제공한다.

3) Eclipse 연동하기

그럼 Eclipse로 실습을 해보자.

Eclipse에서 프로젝트를 생성할 때 테스트 클래스는 반드시 일반 클래스가 아닌 "JUnit Test Case" 형태로 만들어야 한다. 또한 org.junit.Assert.* 및 org.junit.Test를 올바르게 import 하는 것을 반드시 기억해야한다.

실행 결과는 녹색 막대(성공) 또는 붉은 막대(실패)로 직관적으로 표시된다.

Fixture

@Before 어노테이션을 사용하여 각 테스트 전에 필요한 객체를 초기화(setUp) 하고, @After를 사용하여 테스트 종료 후 자원을 정리(tearDown)하는 일관된 테스트 환경을 구성할 수 있다.

Timeout & @Ignore

특정 시간 내에 로직이 수행되는지 검사하려면 @Test(timeout=130)과 같이 시간을 지정하고, 실행을 잠시 보류하려면 @Ignore를 사용한다. 만약 예상되는 예외를 검증하려면 @Test(expected=Exception)을 사용한다.

JUnit Annotation

JUnit과 관련된 Annotation을 정리해보면 아래와 같다.

JUnit 4 vs JUnit 5

JUnit 4에서 JUnit 5로 넘어가며 어노테이션 이름이 변경되었습니다. @Before는 @BeforeEach로, @After는 @AfterEach로, 전체 수행용인 @BeforeClass/@AfterClass는 @BeforeAll/@AfterAll로, 비활성화를 뜻하는 @Ignore는 @Disabled로 명칭이 바뀌었다.

JUnit vs TestNG

JUnit은 주로 단위 테스트에 초점이 맞춰져 있고 병렬 실행이나 그룹화에 제한적인 반면 TestNG는 단위, 통합, 대규모 테스트를 모두 아우르며 병렬 실행, 강력한 그룹화, XML 설정, 데이터 기반 테스트 등 훨씬 강력한 부가 기능을 제공한다.

4. 단위 테스팅(Unit Testing) 실습

EclEmma (자바 Coverage 도구): Eclipse Marketplace에서 설치 가능하며, Coverage As ➔ JUnit Test 모드로 테스트를 실행하면 내가 작성한 테스트 코드가 실제 프로덕션 코드의 몇 퍼센트를 실행(커버)했는지 시각적으로 확인할 수 있습니다
.
GTest (Google Test): Visual Studio 환경에서 C++ 코드를 테스트할 때 사용하는 유닛 테스트 라이브러리입니다
. TEST(TestCaseName, TestName) 형식의 매크로로 테스트를 정의하고, 값을 비교할 때 EXPECT_EQ, EXPECT_TRUE 등의 매크로를 사용합니다
.
Triangle Problem 실습: TDD의 구체적 사례로, 세 변의 길이를 입력받아 정삼각형(Equilateral), 이등변삼각형(Isosceles), 일반 삼각형(Scalene), 삼각형 아님(NotTriangle), 입력 오류(InputValidation)를 판별하는 프로그램을 작성합니다
. 점진적으로 실패하는 테스트 코드를 먼저 만들고 코드를 구현해나가는 과정이 GTest 코드로 상세히 예시되어 있습니다
.

profile
찬찬히 써내려가는 개발일지

0개의 댓글