본문 바로가기
독서 감상문/JUnit in Action

테스트 가능한 코드 작성하기

by 프람6 2024. 5. 4.

작성자: 프람
작성일시: 2024_05_02
내용: JUnit in Action: 단위 테스트의 모든 것 5.2

테스트 가능한 코드 작성하기

 


공개 API는 계약이다.

극단적으로 말하자면, 공개 (public) API(메서드)의 시그니처는 절대 변경하지 않아야합니다.
아무리 IntellJ, Eclipse 와 같은 IDE 도구를 통해 바꾼다 하더라도, 사이드 이펙트가 존재하기 마련입니다.
우리 함께 최대한 지양해보아요🤗


종속성을 줄여라

의존성 주입을 통해 종속성을 줄입시다.

 

문제의 코드 🤮

class Vehicle {
    private Driver d = new Driver();
    private boolean hasDriver = true;

    private void setHasDriver(boolean hasDriver) {
        this.driver = hasDriver;
    }
}

 

편안한 코드🤗

class Vehicle {
    Driver d;
    boolean hasDriver = true;

    Vehicle(Driver d) {
        this.d = d;
    }
}

생성자는 간단하게 만들어라

생성자에 불필요한 로직을 두지 않는 것은 물론, 최소화합시다.
생성하는 곳에도 불필요한 로직이 있다면?? 생성하는 것 자체의 테스트도 매우 복잡해지겠죠??


디미터의 법칙을 따르라

불필요한 정보까지 파라미터로 넘기지 말아야합니다.
불필요한 목 객체 생성해야할 수 도 있읍니다.

 

문제의 코드 🤮

class Car {
    private Driver driver;
    Car(Context context) {
        this.driver = context.getDriver();
    }
}

 

편안한 코드🤗

class Car {
    Car(Driver driver) {
        this.driver = driver;
    }
}

숨겨진 종속성을 없애라

문제의 코드를 보면 Reservation의 reserve메서드를 호출하기 전에 선행 조건으로 DBManager의 initDatabase 메서드를 호출해야합니다.

이러게 사전 조건이 존재하는 단위는 문서화를 해놓치 않으면 쉽게 놓치기 마련이겠죠?

 

문제의 코드 🤮

public void reserve() {
    DBManager manager = new DBManager();
    manager.initDatabase();
    Reservation r = new Reservation();
    r.reserve();
}

이 역시 코드로 의존성이 주입하도록 표현하여 혼란의 여지를 없애 줍시다.

 

편안한 코드🤗

public void reserve() {
    DBManager manager = new DBManager();
    manager.initDatabase();
    Reservation r= new Reservation(manager);
    r.reserve();
}

싱글턴 지양

싱글턴 패턴이 있다는 것은 해당 인스턴스 자체가 전역적으로 사용될 수 있다는 것인데, 명백한 취약점으로 남는다것이죠 😭


제넥릭 메서드를 애용하라

팩토리 메서드는 구현에 따라 컴파일 타임에 타입이 정해지기 때문에 유연한 테스트가 되기 어렵습니다.

따라서 다형성을 이용하지 못한다는 것이죠 ..


상속보다 컴포지션을 활용하라

런타임에는 상속 관계를 변경할 수 가 없습니다.

따라서 보다 유연한 테스트 작성을 위해서는 컴포지션이 더 좋은 전략이겠죠?


조건 분기보다 다형성을 활용하라

이것은 테스트 코드 작성에도 어려움이 이겠지만
아래의 문제의 코드 예시처럼 프로덕션 코드를 작성하게 된다면,

OCP, SRP를 위배하며, 유지보수성을 떨어드리겠죠?? 지향합시🤗

문제의 코드 🤮

public class DocumentPrinter() {
    // 생략...
    public void printDocument() {
        switch (document.getDocumentType()) {
            case Documents.WORD_DOCUMENT:
            printWORDDocument();
            break;
            case Documents.PDF_DOCUMENT:
            printPDFDocument();
            break;
            // 생략...
        }
    }
    // 생략...
}

정리

테스트 코드 유지보수성를 위한 전략

  • 공개 API는 계약이다. (공개 메서드 시그니처 함부로 바꾸지 말라는 뜻 )
  • 종속성을 줄여라. (런타임 유연성도 한스푼)
  • 생성는 간단하게 만들어라
  • 디미터 법칙을 따르라

테스트 베타성을 보장하기 위한 전략

  • 숨겨진 종속성과 전역 상태를 피하라
  • 싱글턴 패턴 지양

런타임 유연성을 위한 전략

  • 제너릭 메서드를 애용하라
  • 상속보다 컴포지션을 활용하라
  • 조건 분기보다 다형성을 활용하라

'독서 감상문 > JUnit in Action' 카테고리의 다른 글

소프트웨어 테스트 종류  (0) 2024.05.04