Dev/TDD

Junit In Action - TDD를 위한 테스트 원칙, 도구 및 활용 Review - Junit 5 아키텍처 개요 ( Junit4와 어떻게 달라졌을까? )

린네의 2024. 6. 14. 17:59

 

소프트웨어 아키텍처의 개념과 중요성

 

소프트웨어 아키텍처란 소프트웨어 시스템의 기본 구조를 말한다. Junit 5의 아키텍처 또한 Junit4의 단점을 극복하기 위해 만들어졌다. 아키텍처가 전체 시스템에 미치는 중대한 영향을 이해하기 위해 간단한 두 가지 이야기를 소개한다.

 

( 책 리뷰하면서 핵심만 추리는게 좋다고 생각했는데 찰떡인 비유라 글을 남겨 놓고 싶어서 포함하게 되었다. Junit5의 구조 내용은 하단에 기재했으니 참고 바란다. )

 

 

  • 첫 번째 이야기 : 전화번호부

전화번호부를 만들어 출간하는 두 회사가 있다.

 

 

 

A, B회사 모두 비슷한 규격과 가격을 가진 전화번호부를 출간했다. 고객들은 두 제품을 모두 같은 가격에 구매 해서 사용했기 때문에 어떤 전화번호부가 더 좋은지에 대해 알 수 없었다. 그러던 어느 날, A 회사가 아이디어를 냈다. 

 

"내용은 동일하게 유지하되, 경쟁사(B)보다 작게 만들어서 출간해 보자"

 

이 아이디어는  일반적으로 책상 위에 여러 책을 올려야 한다면, 작은 책이 상대적으로 위에 올라오게 정리하는 것에서 출발했다. 이후 두 회사의 제품을 모두 가진 고객이더라도, 습관적으로 더 작기 때문에 위에 올라오게 정리된 A 전화번호부만 사용한다는 사실을 깨달았다.  굳이 B회사 제품을 구매할 필요가 없게 된 것이다. 

 

이것이 Junit4와 Junit5의 아키텍처가 달라진 점이다. 작은 것이 더 나을 수 있다.

 

 

  • 두 번째 이야기 : 운동화 제조 업체

한 회사가 생산 비용이 낮은 지역에서 운동화를 제조하기 시작했다. 생산 비용을 줄일 수 있을 것이라 기대했지만, 운동화 도난사건이 잦아 예상하지 못한 손실이 매우 컸다. 보안 인력을 고용하기에는 배보다 배꼽이 더 큰 상황이었다.  이 문제를 해결하기 위한 솔루션으로, 운동화 제조 업체의 분석가들은 왼쪽 신발과 오른쪽 신발을 서로 다른 공장에서 생산할 수 있도록 조치했다.

 

결과적으로 운동화 절도는 급격하게 감소했다.

 

이것은 모듈화의 장점을 보여준다. 특정한 기능이 필요하다면 이를 구현한 모듈을 사용하면 된다. 테스트에서도 전체 테스트 프레임워크를 불러오는 대신 특정 모듈만을 사용한다면 시간과 메모리를 절약할 수 있다.

 

 

 

Junit4 아키텍처와 특징

Junit4는 모놀리식 아키텍처를 가지고 있다. 즉, Junit4의 모든 기능은 jar파일 한 개 안에 들어 있다. 개발자가 Junit4를 원한다면 클래스 패스에 단일 jar파일만 추가하면 된다는 뜻이다.

 

Junit4는 단일 jar파일로 동작이 가능하지만 Junit4의 기능을 조금 더 확장해서 사용하는 경우가 일반적이다.  확장을 위해서는 Junit4 runner라는 리플렉션을 사용하면 됐었다.  리플렉션은 캡슐화를 저해한다. 하지만 이것은 확장성을 위한 유일한 방법이었고 이런 문제점은 이것은 Junit5가 만들어진 이유가 되었다.

 

확장해서 만든 클래스는 @RunWith(CustomTestRunner.class)와 같은 꼴로 사용할 수 있었다.

 

Junit4에서 테스트 메서드가 실행되기 전후에 다른 작업을 수행할 때는 @Rule을 사용했다.  Junit4 rule은 테스트 메서드에서 사용하거나 구성할 수 있는 객체를 만든다는 점에서 테스트를 유연하게 할 수 있다. 

 

 혹은 테스트를 실행하기 전에 특정 프로세스를 시작하고 테스트가 끝난 다음 중지하거나, 테스트를 실행하기 전에 데이터베이스에 커넥션을 얻고 테스트가 끝난 다음 커넥션을 반납할 수 있다. 이것은 제공되는 TestRule 인터페이스를 구현하여 apply 함수를 @Overrride 함으로써 응용 가능하다.

 

Junit 4 rule의 일반적인 유즈케이스로는 테스트를 실행하기 전에 자원을 할당하고 테스트가 끝난 이후 자원을 반납하는 것, 테스트를 실행하기 전에 특정 프로세스를 시작한 이후 테스트가 끝난 다음에는 프로세스를 끝내는 것, 테스트를 실행하기 전에 데이터 베이스 커넥션을 얻고 테스트가 끝난 다음에는 커넥션을 반납하는 것 등이 있다.

 

Junit4가 IDE나 빌드 도구 같은 많은 소프트웨어에서 사용되게 되면서, Junit4가 가진 모놀리식 아키텍처는 점점 단점을 드러냈다. Junit4가 제공하는 API는 충분히 유연하지 못했고, 이것은 IDE나 빌드도구와의 결합성을 증가시켰다. 따라서 더 작고 모듈화 된 Junit에 대한 요구가 생겨났고, Junit5가 등장하는 배경이 됐다.

 

 

 

Junit5 아키텍처

Junit5는 하나의 jar 파일로 되어있던 Junit4를 다양한 빌드 도구와 IDE를 사용하는 프로그램적 클라이언트와 상호작용할 수 있게 설계되어야 했다.  크게 세 분류로 분리되었는데 분류 기준은 다음과 같다.

 

  • 개발자가 주로 사용하는 테스트를 작성하기 위한 API 
  • 테스트를 발견하고 실행하는 데 사용하는 메커니즘 
  • IDE나 빌드 도구와 쉽게 상호작용하고 테스트를 구동할 수 있는 API

 

이 기준은 발전되어 실제적으로 다음 세 가지 모듈로 나뉘었다.

 

  • Junit Platform : JVM 위에서 테스트 프레임워크를 구동하기 위한 기반이 되는 플랫폼이다. 또한 콘솔, IDE, 빌드 도구에서 테스트를 구동할 수 있는 API도 제공한다.
  • Junit Jupiter : JUnit5에서 테스트와 extenstion을 만들 수 있도록 프로그래밍 모델과 확장 모델을 결합한 것이다. 
  • Junit Vintage : JUnit5 Platform에서 Junit3이나 Junit4 기반의 테스트를 실행하기 위한 테스트 엔진으로, 하위 호환성을 보장한다.

 

 

[출처] Junit in Action 3판 - TDD를 위한 테스트 원칙, 도구와 활용