워밍업 클럽 2기 BE 클린코드&테스트코드 3주차 발자국
Practical Testing: 실용적인 테스트 가이드 수강 후 작성한 3주차 발자국입니다.
3주차 강의 정리
테스트를 작성하는 역량
주니어 개발자에게 가장 기대하는 요소 중 하나
채용 시 구현 과제 등에서 테스트 작성 여부, 테스트 코드 구현 방식을 확인
소프트웨어 품질을 보증하는 방법으로, 그 중요성을 알고있는지를 확인
무엇을 학습?
테스트 코드가 필요한 이유
좋은 테스트 코드란 무엇일까?
실제 실무에서 진행하는 방식 그대로 테스트를 작성해가면서 API를 설계하고 개발하는 방법
정답은 없지만 오답은 있다! 구체적인 이유에 근거한 상세한 테스트 작성 팁
테스트를 왜 해야하는가?
내가 개발한 기능이 내가 의도한대로 정상 동작하는지 확인되어야한다.
이걸 사람이 수동으로 검증하는게 아니라 자동화시키자는것
개발한 소프트웨어의 신뢰성을 높일수있다
테스트 코드가 엉망, 복잡함
→ 부작용
→ 잘짜야한다…
테스트 코드를 작성하지 않는다면
변화가 생기는 매순간마다 발생할 수 있는 모든 case를 고려해야한다.
변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야한다.
빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.
테스트 코드가 병목이 된다면
프로덕션 코드의 안정성을 제공하기 힘들어진다.
테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.
잘못된 검증이 이루어질 가능성이 생긴다.
올바른 테스트 코드는
자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.
소프트 웨어의 빠른 변화를 지원한다.
팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.
가까이 보면 느리지만, 멀리보면 가장 빠르다
단위테스트 (Unit test)
작은 코드단위를 독립적으로 검증하는 테스트 (클래스, 메서드)
검증 속도가 빠르고, 안정적이다.
JUnit 5
단위 테스트를 위한 테스트 프레임워크
XUnit - Kent Beck
AssertJ
테스트 코드 작성을 원활하게 돕는 테스트 라이브러리
풍부한 API, 메서드 체이닝 지원
테스트 케이스 세분화하기
질문하기 : 암묵적이거나 아직 드러나지 않은 요구사항이 있는가?
해피케이스
예외케이스 - 음료 수량은 음수로 입력한다면, 0을 입력한다면
경계값 테스트 (범위, 구간, 날짜 등)
경계값이 존재한다면 테스트는 항상 경계값에서 테스트 하는게 좋다.
예를들어 3이상일때 A라는 조건을 만족해야한다. 는 요구사항이 있다면 해피케이스 테스트는 3으로 하는것이 좋다. 4나 5보다.. 예외케이스는 2로 하는게 좋다.
테스트하기 어려운 영역을 구분하고 분리하기
관측할 때마다 다른 값에 의존하는 코드
현재 날짜/시간, 랜덤값, 전역 변수/함수, 사용자 입력 등
외부 세계에 영향을 주는 코드
표준 출력, 메시지 발송, 데이터 베이스에 기록하기 등
@Data, @Setter, @AllArgsConstructor 지양
TDD : Test Driven Development
프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론
red - green - refactor
실패하는 테스트 작성해서 빨간불보기
테스트 통과하는 최소한의 코딩해서 초록불보기
초록불을 유지하면서 리팩토링 구현코드 개선
TDD의 핵심가치 → 피드백
내가 작성하는 코드에 대해서 빠르게 피드백을 받을 수 있다는 장점
기존의 선 기능 구현 후 테스트 작성하는 방식
테스트 자체의 누락 가능성
특정 테스트 케이스만 검증할 가능성 (해피케이스만..)
잘못된 구현을 다소 늦게 발견한 가능성
선 테스트 작성 후 기능 구현
복잡도가 낮은 테스트 가능한 코드로 구현할 수 있게 한다.
쉽게 발견하기 어려운 엣지 케이스를 놓치지 않게 해준다.
구현에 대한 빠른 피드백을 받을 수 있다.
과감한 리팩토링이 가능해진다.
테스트는 문서다
프로덕션 기능을 설명하는 테스트 코드 문서
다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완
어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.
DisplayName을 섬세하게
테스트 메서드가 어떤 역할을 하는지 이름 지을 수 있다.
ex)
음료 1개 추가 테스트
→ 음료를 1개 추가할 수 있다
명사의 나열보다 문장으로 작성하기
~테스트 지양하기
음료를 1개 추가할 수 있다
→ 음료를 1개 추가하면 주문 목록에 담긴다.
테스트 행위에 대한 결과까지 기술하기
특정 시간 이전에 주문을 생성하면 실패한다
→ 영업 시작 시간 이전에는 주문을 생성할 수 없다.
도메인 용어를 사용하여 한층 추상화된 내용을 담기
메서드 자체의 관점보다 도메인 정책 관점으로
테스트의 현상을 중점으로 기술하지 말 것
성공한다 실패한다는 피하기
BDD: Behavior Driven Development
TDD에서 파생된 개발 방법
함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트 케이스 자체에 집중하여 테스트한다.
개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 추상화 수준을 권장
Given / When / Then
Given : 시나리오 진행에 필요한 모든 준비 과정 (객체, 값, 상태 등)
When : 시나리오 행동 진행
Then : 시나리오 진행에 대한 결과 명시, 검증
어떤 환경에서(given)
어떤 행동을 진행했을 때(when)
어떤 상태 변화가 일어난다.(then)
→ DisplayName에 명확하게 작성할 수 있다.
Spring & JPA 기반 테스트
Layered Architecture 레이어드 아키텍쳐
스프링 MVC 기반에서 가장 많이 사용되는 아키텍쳐
왜 레이어를 구분하는가? → 관심사의 분리
사용자의 요청이 왔을때 각 레이어별로 역할을 할당
테스트 하기 복잡해보인다는 생각이 들 수 있다.
여러 객체가 협력해서 하나의 기능을 동작하게 하는 경우는 어떻게 테스트 할 것인가, 단위 테스트만으로는 커버 못함
→ 통합 테스트가 필요하다 (Integration test)
여러 모듈이 협력하는 기능을 통합적으로 검증하는 테스트
일반적으로 작은 범위의 단위 테스트만으로는 기능 전체의 신뢰성을 보장할 수 없다.
풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트
Spring / JPA
Spring
Library vs Framework
라이브러리는 내 코드가 주체가 돼서 필요한 기능이 있다면 외부에서 끌어와서 사용. 외부에서 끌어오는걸 라이브러리라고 표현한다.
프레임워크는 이미 프레임이 있는것. 동작할 수있는 환경이 있음, 내 코드가 수동적으로 환경에 들어가서 동작
스프링은 프레임워크로써 제공하는 환경이 있고 그거에 맞춰서 코드를 작성하면 동작하는 구조
스프링 3대 개념
IoC (Inversion of Control)
객체에 대한 생명주기 관리는 제 3자가 하는것,, 제어의 역전이 일어남.
DI (Dependency Injection)
컨테이너라는 제 3자가 주입해준 객체를 사용한다.
AOP (Aspect Oriented Programming)
비즈니스 흐름과 관련없는 부분을 관점이라는 용어로 부르고
JPA (Java Persistence API)
ORM (Object-Relational Mapping)
orm 의 한 종류로 jpa가 존재함
ORM
객체 지향 패러다임과 관계형 DB 패러다임의 불일치
이전에는 개발자가 객체의 데이터를 한땀한땀 매칭하여 DB에 저장 및 조회
ORM을 사용함으로써 개발자는 단순 작업을 줄이고, 비즈니스 로직에 집중할 수 있다.
JPA
Java 진영의 ORM 기술 표준
인터페이스이고 여러 구현체가 있지만 보통 Hibernate를 많이 사용한다.
반복적인 CRUD SQL을 생성 및 실행해주고, 여러 부가 기능들을 제공한다.
편리하지만 쿼리를 직접 작성하지 않기 때문에 어떤 식으로 쿼리가 만들어지고 실행되는지 명확하게 이해하고 있어야 한다.
Spring 진영에서는 JPA를 한번 더 추상화한 Spring Data JPA 제공
QueryDSL과 조합하여 많이 사용한다. (타입체크, 동적쿼리)
JPA에서 주고 사용되는 어노테이션들
@Entity, @Id, @Column
@ManyToOne, @OneToMany, @OneToOne, @ManyToMany
3주차 회고
이번주엔 테스트 코드에 대해 학습했는데 개발자로 취업하고 테스트 코드를 제대로 작성해본 것은 처음이었다. 지금 회사에서는 테스트코드를 작성하지 않는다. IT관련 미디어에서 테스트 코드 작성해야한다. TDD 해야한다. 이런 말을 많이 하는데 회사에선 안하니까 계속 묵혀두기만 했었다. 입사 처음엔 테스트 코드에 대한 필요성을 잘 못느끼다가 요즘 들어서는 점점 느끼고 있고 공부의 필요성을 느꼈다. 기존에 있었던 기능에 대해서 코드를 수정하면 기존에 잘 돌아가던 기능도 에러가 발생할까 걱정되었고, 코드를 다 작성하고도 혹시나 내가 못찾은 버그는 없을까 불안한 마음이 생겼었다. 또 테스트 시 입력해야 할 항목이 많은 경우는 하나하나 선택하고 테스트 해봐야 하는게 정말 불편했다. 지금은 수동으로 하나하나 테스트 하고 있긴 한데 적합한 방법은 아닌 것 같다는 생각이 계속 들고 있다. 이번 테스트코드 과정을 통해 지금까지 회피하고 묵혀뒀던것들을 어느 정도라도 해소할 수 있었으면 좋겠다.
댓글을 작성해보세요.