Practical Testing: 실용적인 테스트 가이드대시보드

이진호·2023년 5월 1일
0

logs

목록 보기
1/4
post-thumbnail

단위 테스트

테스트는 왜 필요할까?

테스트 코드를 작성하지 않는다면

  • 변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 한다.
  • 변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야 한다.
  • 빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.

테스트 코드가 병목이 된다면

  • 프로덕션 코드의 안정성을 제공하기 힘들어진다.
  • 테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.
  • 잘못된 검증이 이루어질 가능성이 생긴다.

올바른 테스트 코드는

  • 자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.
  • 소프트웨어의 빠른 변화를 지원한다.
  • 팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.
  • 가까이 보면 느리지만, 멀리 보면 가장 빠르다.

JUnit5로 테스트하기

단위 테스트

  • 작은 코드 단위를 독립적으로 검증하는 테스트
    • 클래스 or 메서드
  • 검증 속도가 빠르고, 안정적인다.

Junit 5

  • 단위 테스트를 위한 테스트 프레임워크
  • XUnit - Kent Beck
    • SUnit(Smalltask), Junit(Java), Nunit(.NET), ...

AssertJ

  • 테스트 코드 작성을 원활하게 돕는 테스트 라이브러리
  • 풍부한 API, 메서드 체이닝 지원

테스트 케이스 세분화하기

  • 해피 케이스
  • 예외 케이스

경계값 테스트 - 범위(이상, 이하, 초과, 미만), 구간, 날짜 등

테스트하기 어려운 영역을 분리하기

  • 테스트하기 어려운 영역을 구분하고 분리하기
  • 외부로 분리할수록 테스트 가능한 코드는 많아진다.

테스트하기 어려운 영역

  • 관측할 때마다 다른 값에 의존하는 코드
    • 현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등
  • 외부 세계에 영향을 주는 코드
    • 표준 출력, 메시지 발송, 데이터베이스에 기록하기 등

순수함수 (pure functions)

  • 같은 입력에는 항상 같은 결과
  • 외부 세상과 단절된 형태
  • 테스트하기 쉬운 코드

TDD: Test Driven Development

  • 프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론

RED, GREEN, REFACTOR

  • RED: 실패하는 테스트 작성
  • GREEN: 테스트 통과 최소한의 코딩
  • REFACTOR: 구현 코드 개선 테스트 통과 유지

선 기능 구현, 후 테스트 작성

  • 테스트 자체의 누락 가능성
  • 특정 테스트 케이스(해피 케이스)만 검증할 가능성
  • 잘못된 구현을 다소 늦게 발견할 가능성

선 테스트 작성, 후 기능 구현

  • 복잡도(유연하며 유지보수가 쉬운)가 낮은, 테스트 가능한 코드로 구현할 수 있게 한다.
  • 쉽게 발견하기 어려운 엣지(Edge) 케이스를 놓치지 않게 해준다.
  • 구현에 대한 빠른 피드백을 받을 수 있다.
  • 과감한 리팩토링이 가능해진다.

TDD: 관점의 변화

  • 테스트는 구현부 검증을 위한 보조 수단 -> 테스트와 상호 작용하며 발전하는 구현부
  • 클라이언트 관점에서의 피드백을 주는 Test Driven

테스트는 []다.

테스트는 문서다.

  • 프로덕션 기능을 설명하는 테스트 코드 문서
  • 다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완
  • 어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.

우리는 항상 팀으로 일한다.

DisplayName을 섬세하게

-> 음료 1개 추가 테스트 <- "~테스트" 지양하기
-> 음료를 1개 추가할 수 있다.
-> 음료를 1개 추가하면 주문 목록에 담긴다.
  • 명사의 나열보다 문장으로 - A이면 B이다. A이면 B가 아니고 C다.
  • 테스트 행위에 대한 결과까지 기술하기
-> 특정 시간 이전에 주문을 생성하면 실패한다.
-> 영업 시작 시간 이전에는 주문을 생성할 수 없다.
  • 도메인 용어를 사용하여 한층 추상화된 내용을 담기
    • 메서드 자체의 관점보다 도메인 정책 관점으로
  • 테스트의 현상을 중점으로 기술하지 말 것

Spring & JPA 기반 테스트

레이어드 아키텍처(Layered Architecture)와 테스트

Layered Architecture

  • Presentation Layer
  • Business Layer
  • Persistence Layer

테스트 하기 복잡해 보인다?

통합 테스트(Integration test)

  • 여러 모듈이 협력하는 기능을 통합적으로 검증하는 테스트
  • 일반적으로 작은 범위의 단위 테스트만으로는 기느으 전체의 신뢰성을 보장할 수 없다.
  • 풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트

Spring / JPA 훑어보기 & 기본 엔티티 설계

Library vs Framework

  • Library는 내 코드가 주체가 되는 능동적 환경.
  • Framework 내 코드가 프레임 안에서 역할을 하게 되는 수동적 환경.

Spring

  • IoC(Inversion of Control)
  • DI(Dependency Injection)
  • AOP(Aspect Oriented Programming)

ORM(Object-Relational Mapping)

  • 객체 지향 패러다임과 관계형 DB 패러다임의 불일치
  • 이전에는 개발자가 객체의 데이터를 한땀한땀 매핑하여 DB에 저장 및 조회(CRUD)
  • ORM을 사용함으로써 개발자는 단순 작업을 줄이고, 비즈니스 로직에 집중할 수 있다.

JPA(Java Persistence API)

  • Java 진영의 ORM 기술 표준
  • 인터페이스이고, 여러 구현체가 있지만 보통 Hibernate를 많이 사용한다.
  • 반복적인 CRUD SQL을 생성 및 실행해주고, 여러 부가 기능을 제공한다.
  • 편리하지만 쿼리를 직접 작성하지 않기 때문에, 어떤 식으로 쿼리가 만들어지고 실행되는지 명확하게 이해하고 있어야 한다.
  • Spring 진영에서는 JPA를 한번 더 추상화한 Spring Data JPA 제공
  • QueryDSL과 조합하여 많이 사용한다. (타입체크, 동적쿼리)
  • @Entity, @Id, @Column
  • @ManyToOne, @OneToMany, @OneToOne, @ManyToMany(일대다 - 다대일 관계로 풀어서 사용)

엔티티 설계

  • Order
  • OrderProduct
  • Product

출처

0개의 댓글