테스트라는 딜레마

지훈진·2021년 9월 13일
0

BetterProgrammer

목록 보기
7/17
post-thumbnail

11장. 테스트하기

자신의 코드는 자신이 테스트해야 한다. 생각할 필요도 없는 당연한 일이다.

당연해서 부연 설명할 필요도 없다.

품질은 그것을 위해 큰 대가를 치를 용의가 있는 자들에게만 공짜이다.

<피플웨어>의 한 구절이다. 심혈을 기울인다 하더라도 인간은 실수할 수 밖에 없다. 다음은 나의 오늘 실수이다.

// X나 구린 코드
if (value == null) {
    throw new NotFoundException();
}

// 끝내주는 코드
Optional.of(value).orElseThrow(() -> new NotFoundException());

자바를 자주 하시는 분들은 알겠지만 위의 코드는 NPE가 발생한다. (나는 자바를 최근에 다시 하는중...)

// 의도한대로 동작하는 진짜 끝내주는 코드
Optional.ofNullable(value).orElseThrow(() -> new NotFoundException());

왜 굳이 ofofNullable을 상세히 구분하는진 잘 모르겠지만, 자바를 접한지 얼마 되지 않았다면, 잘했다고 착각하고 QA에게 테스트를 넘겼다가 빠꾸당하기 딱 좋다. 그런데 이게 테스트 환경에 배포하고 QA가 테스트하다가 발견되어야 할 수준의 코드인가? 두가지 유닛 테스트면 검증할수 있다. value가 Value 클래스 객체인 경우, null 인 경우. 명확하다.

더 열심히 일하려 하기보다 더 영리하게 일하라.

테스트 코드를 작성하는 것이 비효율적이라고 생각한 적이 있다. 아이러니하게도 당시엔 컴파일과정도 없는 Ruby on Rails 로 개발하고 있었다. 이해할 수 없는 기존의 잘못된 테스트 케이스에 의해 지쳐버린 상태였다. "유닛 테스트를 포기하고 본 코드를 집중해서 똑바로 제대로 짜자." 라고 생각했고, 실제로 개발속도가 빨라졌다. 하지만 이것은 나만의 이야기고(하지만 정말 그랬었을까? 스스로에게 의문이 들긴 한다.) 나의 생각에 공감하지 않은 개발자들은 테스트없이 이전과 똑같이 개발을 했다. 과연 개발 프로세스는 효율적으로 바뀌었을까? 내 생각이 영리했었는지 한번 생각해보면 좋겠다.

좋은 테스트의 특징 - 특별한 머신 설정이 필요 없다

테스트는 온전히 어플리케이션 하나만으로 동작해야한다. DB나 Cache등에 대한 Mocking 전략이 반드시 필요하다. 이것이 중요한 이유가 하나 더 있다. 싱글 인스턴스로 서비스 하던 어플리케이션에 트래픽이 증가해 멀티 인스턴스로 서비스를 해야하는 상황을 생각해보자. 이전에 쓰고 있던 캐시 전략이 로컬 디스크였다면 레디스나 다른 캐시서버로 바꿔야 한다. (인스턴스간의 캐시 싱크가 안맞아 클라이언트가 바라보는 데이터가 꼬이게 된다.) 이때, 기존 코드가 로컬 캐시에 의존적이라면, 기존 코드를 모두 수정해야 한다. 하지만 캐시 클래스가 있고 그 클래스를 레디스 캐시 클래스로 바꿔 끼워 넣을 수 있다면? 기존 코드를 변경할 필요 없이 신규 캐시 클래스를 구현하고 기존의 로컬 캐시 클래스를 주입하는 곳에 갈아끼우기만 하면 된다. 즉 테스트를 하면서 객체지향 원칙중 하나인 OCP 까지 지킬수 있다. 특히 최근의 MSA 환경은 모킹이 더욱 중요할 것으로 생각한다.

나쁜 테스트의 특징 - 화이트박스식 테스트

내부 구현을 알고 테스트를 짤 수도 있다. 그 즉슨 내부 구현이 바뀌면 테스트 코드를 모두 수정해야한다는 이야기이다. 아까의 로컬 캐시를 레디스 캐시로 바꾸는 것을 예로 들어보자. 클라이언트에서 캐시를 로컬을 쓰든 레디스를 쓰든 멤캐시를 쓰든 무슨 상관인가? 테스트는 인풋과 아웃풋으로만 이루어지면 된다.

구현 코드만큼이나 테스트 코드를 주의 깊게 살펴봐야 한다.

테스트 코드를 작성할 만큼 중요한 코드이다. 당연히 중요하고 주의 깊게 봐야한다.

profile
집사없는 개발 고양이

0개의 댓글