Group Study (2021-2022)/Clean Code

[클린코드 북리뷰 스터디] 4주차 - 경계와 단위 테스트

z.zzz 2022. 6. 20. 17:01

8장. 경계

목표 : 소프트웨어 경계를 깔끔하게 처리하는 기법을 살펴보기

 

1. 경계란

우리 코드와 외부 코드의 경계를 의미함
외부 코드 : 외부 시스템과 호출하거나 단순히 외부에서 만들어진 코드
우리 코드와 외부 코드를 깔끔하게 통합시키기 위해 경계를 잘 지어야 함

2. 경계 짓기(1) - 우리 코드를 보호하기

캡술화
객체의 실제 구현을 외부로부터 감춤 (tmi 하지 않아야 한다!)

캡슐화

캡슐화의 장점
캡슐화로 외부 코드를 감추면 private하게 데이터 관리 가능
→ 원하는 기능만 공개할 수 있다

캡슐화 예제

public class Sensors {
	private Map Sensors = new HashMap();
    
    public Sensor getById(String id) {
    	return (Sensor) sensors.get(id);
       }
}

경계 인터페이스인 Map을 Sensor 안으로 숨김
→ Map 인터페이스가 변해도 나머지 프로그램엔 영향 X
→ Sensors 클래스는 프로그램에 필요한 인터페이스만 제공하기 때문에 나머지 프로그램이 설계 규칙과 비즈니스 규칙을 따르도록 강제할 수 있음

3. 경계 짓기(2) - 외부 코드와 호환하기

Adapter
외부코드를 호출할 때, 우리가 정의한 인터페이스대로 호출하기 위해 우리 코드와 외부 코드 중간의 호환용 코드

어댑터 패턴

 

4. 외부 라이브러리 테스트 하기 - Learning Test

Learning Test를 작성해 라이브러리를 테스트
Learning Test 작성의 장점
· 외부 코드를 배우고, 안정성도 미리 검증할 수 있다
· 외부 코드의 버전이 변경됐을 때, 우리 코드와 호환되는지 확인할 수 있다(!)
· 실무에선 작성해두면 좋지만, 항상 작성하진 않음. 그러나 여유가 있다면 작성하는 게 좋다

정리

1. 통제가 불가능한 외부 패키지에 의존하는 것보단 통제가 가능한 우리 코드에 의존할 것
2. 외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리할 것
3. 새로운 클래스로 경계를 감싸거나 ADAPTER 패턴을 사용해 우리가 원하는 인터페이스를 패키지가 제공하는 인터페이스로 변환할 것

 


9장. 단위 테스트

목표 : 제대로 된 테스트 케이스를 작성하는 방법 익히기


1. 테스트 코드의 중요성

테스트 코드는...
· 반드시 존재해야 한다
· 테스트 케이스는 변경이 쉽도록 한다
· 지저분하다면 테스트를 안하니만 못하다
· 실제 코드 못지 않게 중요하며 실제 코드만큼 깨끗하게 짜야한다

테스트의 중요성 in Effective Unit Test
테스트를 작성해서 얻게 되는 가장 큰 수확
 - 테스트 자체(X)
 - 작성 과정에서 얻는 깨달음(O)

깨끗한 테스트 코드
· 깨끗한 테스트 코드를 만드려면 가독성이 중요
· 가독성을 높이기 위해선 명료성, 단순성, 풍부한 표현력이 필요

테스트는 자동화되어야 한다
실제 코드를 점검하는 자동화된 단위 테스트는 설계와 아키텍처를 최대한 깨끗하게 보존하는 열쇠

TDD 법칙 세 가지
1. 실패하는 단위 테스트 작성할 때까지 실제 코드를 작성하지 않는다
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다
3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다
※ 주의 : 실제 코드와 맞먹을 정도로 방대한 테스트 코드는 심각한 관리 문제를 유발함

2. 테스트의 종류

Test Pyramid

테스트 피라미드

· Unit Test : 프로그램 내부의 개별 컴포넌트의 동작을 테스트함
· Integration Test : 프로그램 내부의 개별 컴포넌트들을 합쳐서 동작을 테스트함
· E2E Test : End to End Test. 실제 유저의 시나리오대로 네트워크를 통해 서버의 Endpoint를 호출해 테스트함 
✔ 구글의 제안: 70% Unit Test, 20% Integration Test, 10% End to End Test

3. Unit Test 작성

테스트 라이브러리를 이용하자
실무에선 JUnit5 + mockito를 가장 많이 사용함

Test Double
테스트에서 원본 객체를 대신하는 객체

Test Double 종류
· Stub : 상태 검증
· Spy : Stub 역할 + 호출 정보 기록
· Mock : 행위 검증

given-when-then 패턴을 사용하자
· given : 테스트에 대한 pre-condition
· when : 테스트하고 싶은 동작 호출
· then : 테스트 결과 확인

4. FIRST 원칙

깨끗한 테스트는 다음 다섯 가지 규칙을 따름
· Fast : 테스트는 빨리 돌아야 함 (느리면 자주 돌릴 엄두를 못 냄)
· Independent : 각 테스트는 서로 의존하면 안 됨 (테스트가 서로에게 의존하면 연쇄적인 실패가 발생할 때 실패의 원인을 진단하기 어려워짐)
· Repeatable : 테스트는 어떤 환경에서도 반복 가능해야 함. 테스트가 돌아가지 않는 환경이 있어선 안 됨
· Self-Validating : 테스트는 부울 값(성공/실패)으로 결과를 내야 함
· Timely : 테스트는 적시에 작성해야 함. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현함

5. 테스트당 개념 하나

잡다한 개념을 연속으로 테스트하는 긴 함수는 피할 것
· 개념당 assert문 수를 최소로 줄여라
· 테스트 함수 하나는 개념 하나만 테스트하라

정리

· 테스트 코드는 지속적으로 깨끗하게 관리해야 한다
· 테스트 API를 구현해 도메인 특화 언어를 만들자