Be-Developer

UnitTesting 06 단위 테스트 스타일

06 단위테스트 스타일

단위테스트의 세가지 스타일

출력기반 테스트

: SUT에 입력을 넣고 생성되는 출력을 점검 = 함수형

  • 부작용이 없는 코드 선호를 강조하는 프로그래밍 방식인 함수형 프로그래밍에 뿌리를 두고있다.

    상태기반 테스트

    : 작업이 완료된 후 시스템 상태를 확인하는것 (외부 의존성의 상태, DB, FileSystem ,sut의 상태)

    통신기반 테스트

    : mock을 사용하여 SUT와 협력자간의 통신을 검증.

    스타일 비교

    | - | 출력기반|상태기반|통신기반| |–|–|–|–| |리팩터링 내성을 지키기 위한 노력| 낮음|중간|중간| |유지비|낮음|중간|높음|

  • 항상 다른것보다 출력기반 테스트를 선호하라.

함수형 아키텍처 이해

  • 수학적 함수를 사용한 프로그래밍, 숨은 입출력이 없다.
  • 수학적 함수 = 메서드 명, 인수, 반환타입으로 구성된 메서드 시그니처에 명시된다.
  • 호출 횟수에 상관없이 주어진 입력에 동일한 출력을 생성해야한다.

    숨은 입출력

  • 부작용 : 메서드 시그니처에 표시되지않는 출력, 상태변경 혹은 파일업데이트를 하는 부작용이 발생.
  • 예외 : 예외를 던지면 시그니처에 설정된 계약을 우회하는 경로를 만든다. 어디서든 발생할수있으므로 메서드 시그니처가 전달하지않는 출력을 추가한다.
  • 내외부 상태에 대한 참조 : DB에서 데이터 질의, 정적속성을 노출시키는 메서드, 변경가능 필드 참조 등 메서드 시그니처에 없는 실행흐름에 대한 입력.

    함수형 아키텍처란

    부작용을 완전 제거하는것이 아니라, 비즈니스로직을 처리하는 코드와 부작용을 일으키는 코드를 분리하는것.

  • 결정을 내리는 코드 (함수형 코더) : 부작용이 필요없고, 수학적 함수로 작성 가능.
  • 결정에 따라 작용하는 코드 (가변 셸): 수학적 함수로 나온 결정을 db변경이나 메시지와같이 가시적인 부분으로 변환한다.
  • 객체지향 프로그래밍은 작동부분을 캡슐화해 코드를 이해할수있게 하고, 함수형 프로그래밍은 작동 부분을 최소화해 코드를 이해할 수 있게 한다.

    함수형 아키텍처와 육각형 아키텍처 비교

  • 육각형 아키텍처는 도메인계층과 애플리케이션 계층을 구별한다 = 결정과 실행을 분리한다.
  • 의존성간의 단방향 흐름, 도메인계층은 애플리케이션 계층에 의존할 수 없다.
  • 함수형 아키텍처의 모든 부작용은 셸이 처리하지만, 육각형 아키텍처는 계층의 경계를 넘지않는 한 부작용은 괜찮다.
  • 함수형 아키텍처는 육각형 아키텍처의 하위 집합이다.

    함수형 아키텍처와 출력 기반 테스트로의 전환

  • 테스트를 파일시스템에서 분리하기위한 mock 사용
  • 함수형 아키텍처로 리팩터링하기
    • ASIS : 매서드 내에서 결정, 파일 업데이트까지 수행
    • TOBE : 메서드 내에서 FileUpdate라는 (명령) 객체 반환, 가변셸에서 FileUpdate를받아 업데이트 수행. 코어와 셸 사이 연결부는 service 가 수행.

      함수형 아키텍처의 단점

  • 성능 단점
    • 출력기반 테스트는 mock을 사용하지않고도 빠르지만, 그로인해 외부 의존성을 더 많이호출하고 성능이 떨어진다.(?)
      • 성능 : 외부 의존성에 대한 호출 수
  • 코드 베이스 크기 증가
    • 궁극적으로는 코드 복잡도가 낮아지고 유지보수성이 향상되지만, 초기엔 코드가 더 필요하다.