본문 바로가기
source-code/software

소프트웨어 장인 정신 이야기 (3)

by mattew4483 2024. 5. 20.
728x90
반응형

4장. 테스트 설계

데이터베이스 테스트하기

데이터베이스를 테스트할 때 첫 번째 규칙은 다음과 같다. 데이터베이스를 테스트하지 말라.
(...) 두 번째 규칙은 다음과 같다. 데이터베이스를 비즈니스 규칙과 분리하라.

 

결국 핵심은, 비즈니스 규칙과 그 이외의 요소들을 명확히 분리 하는 것!

 

이를 위해 인터페이스(예제에서는 Gateway)를 만들어

해당 인터페이스를 구현하는 클래스가 실제 데이터베이스에서 필요한 기능을 수행하도록 작성해야 한다.

 

이를 통해 인터페이스 경계 너머(비즈니스 로직)에서는

SQL도, ORL 프레임워크도, 데이터베이스 API도, 데이터베이스 스키마도 알 필요가 없으며,

오직 의존 중인 인터페이스가 정의한 결괏값(비즈니스 객체)에만 신경 쓸 수 있게 된다.

→ 비즈니스 로직을 테스트할 때는, 스텁이나 스파이로 해당 클래스를 대체해 사용하면 되겠다!

 

GUI 테스트하기

GUI 테스트의 규칙은 다음과 같다.
1. GUI를 테스트하지 말라.
2. 모든 것을 테스트하라. GUI만 빼고.
3. GUI는 여러분 생각보다 작다.

 

C.마틴은 GUI 테스트에 대해 다음과 같은 원칙들을 제시한다.

 

  1. 프레젠터는 화면 또는 창에 표시되는 데이터를 꾸미고 배치하는 일을 담당한다
    • 프레젠터는 세세한 서식과 배치를 모두 처리해서 문자열과 플래그로 채운 간단한 자료 구조를 생성한다
    • GUI는 이 자료 구조를 사용해 화면에 보낼 명령어들을 만든다
    • 프레젠터가 만드는 자료 구조를 보통 뷰 모델이라고 부른다
  2. 인터랙터는 화면에 표시할 데이터가 무엇인지 프레젠터에 알려주어야 한다
    • 고수준 인터랙터는 저수준 프레젠터의 구현에 의존하지 않는다 (인터페이스에 의존할 뿐)
    • 프레젠터 자리에 스파이를 사용해 인터랙터를 테스트할 수 있으며, 프레젠터 테스트 역시 결과로 나오는 뷰 모델을 검사하면 된다
  3. 자동화 단위 테스트로 쉽게 테스트할 수 없는 유일한 요소는 GUI 자체다
    • GUI를 매우 작게 만들어야 한다
    • GUI는 매우 자주 바뀌는 모듈일 가능성이 높으므로, 테스트 역시 오래 살아남기 힘들다

 

이러한 원칙들을, 이전보다 훨씬 고도화되고 복잡해진 프론트엔드 개발에 어떻게 적용할 수 있을까?

프론트엔드 테스트 코드를 엄청나게 많이 작성해 본 것은 아니지만, 지금까지의 경험에 비추어 봤을 때는...

  1. 하나의 페이지 보다, 페이지를 구성하고 있는 컴포넌트들에 대한 단위 테스트를 작성한다
    • 하나의 컴포넌트는 하나의 역할만 수행할 수 있도록 한다
    • 컴포넌트 간 응집도를 높이고, 결합도를 낮추기 위해 노력한다 (결합도가 높아지는 순간 테스트는 물 건너간다)
  2. 비즈니스 로직과 view 로직을 분리한다
    • 도메인 객체는 별도 모듈로 분리한다 
    • 도메인 객체의 동작은, 해당 객체의 단위 테스트에서 검증한다
    • view로직은 너무 간단해서 테스트할 필요가 없게 작성됨을 목표로 한다
  3. 무엇을 테스트하지 않을지 판단한다
    • 해당 페이지에서 보이는 모든 요소들에 대한 테스트 코드를 작성하는 것은 불가능하며, 무의미하다
    • 요구사항을 분석해, 변하지 않을 요소들을 찾아낸 뒤, 해당 요소들에 대한 테스트 코드를 작성한다

 

구체성 대 일반성

테스트가 구체적이 될수록 코드는 일반적이 된다.
(...)
새로운 테스트 케이스를 추가할 때마다 테스트 묶음은 점점 더 구체적이 된다. 반면에 프로그래머는 테스트 대상인 모듈 그룹을 반대 방향으로 향하게 만들어야 한다. 모듈 그룹은 점점 더 일반적이 되어야 한다.
(...) 
테스트는 제약 조건과 명세를 순차적으로 나열한 목록 형태로 커진다. 반면에 제품 코드는 다채로운 논리나 동작을 한데 모은 모습이 되는데, 이런 논리나 동작은 애플리케이션을 운용하는 근본적인 추상화에 초점을 두고 조직된다.

 

(특히 프론트엔드에서) 테스트 코드가 무의미하게 느껴지는 경우가 많은 이유는...

뭐만 하면 테스트가 실패하기 때문이다! (이전의 내가 그랬다)

 

하지만 명심. 이는 내가 무너지기 쉬운 테스트 코드를 작성했기 때문이며,

대부분의 경우 테스트와 제품 코드 간의 지나친 결합으로 인해 발생한다.

 

테스트 주도 개발의 빨강 → 초록 → 리팩터링 의 흐름에서

빨강 단계에서는 추가만, 초록 단계에서는 변환이, 리팩터링 단계에서는 복구 가 발생한다.

 

그리고 이 때 변환 단계에서 코드를 조금 바꿈으로써 동작을 바꿈과 동시에, 해법을 일반화하는 과정이 진행된다.

→ 코드를 매우 구체적인 상태에서 살짝 더 일반적인 상태로 옮기며,

이를 통해 제품 코드가 이전보다 더 다양한 제약 조건을 처리할 수 있게 되는 것!

728x90
반응형