yoon-jj의 블로그

TDD 스터디 본문

개발

TDD 스터디

yoon-jj 2022. 7. 17. 21:36

회사에서 이제부터 새로 진행하는 프로젝트에 TDD를 적용하기로 했다.

그래서 열리게 된 TDD 스터디

스터디는 놓칠수없지!

 

짝프로그래밍 중

+ 블로그의 글은 공부한 내용을 간략히 정리하는 느낌으로 적었기 때문에 JUnit, AssertJ에 사용법은 따로 작성하지 않았습니다.


테스트?

테스트 주도 개발이라는 말에 앞서 '테스트'에 대해 알아보자면 테스트의 뜻은?

 

Test

말 그대로 테스트다. 개발에서의 테스트는 시험보다는 '검사'에 더 가까울거같다.

 

테스트는 여러 분류로 나눌 수 있다.

블랙박스 테스트 & 화이트박스 테스트

만약 내부 동작을 확인할 수 있는지 여부로 나누면, 내부 작동을 볼 수 없다면 블랙 박스 테스트와 내부 작동을 볼 수 있다면 화이트 박스 테스트라 한다.

개발자는 본인이 작성한 코드를 볼 수 있는 화이트 박스 테스트를 진행하게된다.

 

https://itwiki.kr/w/소프트웨어_테스트

그리고 개발 단계별로 분류하면 단위 테스트, 통합 테스트 등이 있다.

 

 

왜 테스트 코드를 작성할까?

일이 너무 바쁘다면.. 시간이 없어 개발만 하고 테스트는 작성하지 못한채 다음 단계로 넘어가게된다.

코드 작성 후에는 프로그램에 문제가 있는지 확인하기위해 디버깅을 해야하는데, 테스트 코드를 작성하지 않는다면 어느 부분에서 문제가 생겼는지 확인이 힘들다.

 

하지만 테스트 코드를 작성했다면?!

작성한 코드에 대해 빠르게 검증할 수 있고, 어느 부분에서 문제가 생겼는지 쉽게 알 수 있다.그래서 디버깅 시간을 줄일 수 있게된다.

디버깅 시간을 줄이면 전체적인 개발 시간도 줄어들어 생산성을 높일 수 있다.

또 테스트를 진행하면 제품의 신뢰성을 평가하기위한 결과로 사용할 수도 있다.

 

테스트를 자동화시키면 수동 테스트보다 잘못될 확률이 낮고, 테스트를 자주 실행해볼 수 있어서 문제를 초기에 발견하기도 쉽다.

 

그러면 이렇게 좋은 테스트 코드는 어떻게 작성하면 될까?

 

 

테스트 코드 작성 순서

1. 조건
    테스트에 필요한 데이터와 객체(Fixture)를 준비한다.
2. 실행
    설정된 fixture를 이용해 테스트를 수행한다.
3. 검증
    원하는대로 수행되었는지 검증한다.

 

작성 순서는 위와 같은데 이건 실제로 해보면 알게된다. 

더보기

Fast 테스트를 작성할 때는 빠르게

Isolated / Independent 테스트는 독립적으로 (다른 테스트에 영향을 받으면 안된다!)

Repeatable 반복적으로 실행해도 계속 동일한 결과를 받기

Self-validating 테스트 스스로 증명이 되어야한다.

Timely / Through 시기 적절하게 테스트 작성하기!

 

이제 TDD를 알아보자.


TDD??

실패하는 테스트를 만들고, 그 테스트가 통과하는 제품을 만들면 결국 원하는 기능이 동작하게 된다.

TDD는 'Test Driven Development'의 약자로 번역하면 '테스트 주도 개발'이다.

테스트를 먼저 작성한 후 기능 개발을 진행하는 방식인데 왜 이렇게 해야할까?

 

테스트 코드를 먼저 작성하게되면 무엇을 테스트 할 지 결정하게되고, 목적을 명확히 할 수 있다.

그리고 원하는 기능을 추가하기 위해 무엇이 필요한지 고민하게된다.

고민하다보면 각 메서드의 기능에 대해 구조화 시킬 수 있게되고, 인터페이스에 집중할 수 있게된다.

또 위에서 말한것처럼 테스트를 진행하면 디버깅 시간을 줄일 수 있고, 추가로 리팩터링 시 오류를 잡는데 도와주기도 한다.

마지막으로 코딩 완료 시점을 알 수 있다는 장점도 있다. 테스트를 모두 통과한 시점이 바로 완료 시점이다.

 

 

TDD Cycle

1. 요구사항을 정의한다.
2. 실패하는 테스트 코드를 작성한다. (Red)
3. 테스트를 통과하게끔 실제 코드를 작성한다. (Green)
4. 결과 코드를 최대한 깔끔하게 리팩터링한다. (Blue)

 

1번 요구사항 작성을 완료했다면 2번부터 4번까지의 과정을 여러번 반복하면 된다.

 

그러면 이제 실제로 TDD를 시도해보자.


스터디에서는 간단하게 계산기를 만들었다.

TDD Cycle을 이용하여 진행해보면 아래와 같다.

 

1. 요구사항 정의하기

사칙연산이 가능한 계산기를 만든다고 해보자.

그러면 나올 수 있는 요구사항은 간단히 아래의 4가지이다.

 

1. 두 수를 입력받아 그 합을 반환한다.

2.두 수를 입력받아 그 차을 반환한다. 

3. 두 수를 입력받아 그 곱을 반환한다.

4. 두 수를 입력받아 그 몫을 반환한다. 대신 0으로 나누면 null이 나오도록 한다. (일단 나머지는 생각하지 않는다고 치자..)

 

위 요구사항 중 4번을 해보자.

 

2. Red 실패하는 테스트 코드를 작성한다.

// TDD 규칙1. 테스트 코드를 보고 어떤 일을 하는지 알 수 있도록 설명을 적어준다.
@DisplayName("두 수를 입력받아 몫을 리턴한다.")
@Test
void divide() {
    // 조건 - 테스트에 필요한 데이터와 객체를 준비한다.
    // 이 부분은 다른 테스트에서도 공통으로 사용하기 때문에 BeforeEach로 빼서 사용할 수 있다.
    Calculator calculator = new Calculator();
    
    // 실행 - 설정된 fixture를 이용해 테스트를 수행한다.
    int result = calculator.divide(4, 2);

    // 검증 - 원하는대로 수행되었는지 검증한다.
    assertThat(result).isEqualTo(2);
}

실패하는 테스트를 작성해주었다.

작성할 때는 테스트 코드 작성 순서에 따라 '조건 - 실행 - 검증' 순으로 작성해주었다. (given, when, then 이라고도 한다.)

위의 테스트는 Calculator가 실제로 존재하지 않기 때문에 실패하게된다.

 

3. Green 테스트를 통과하게끔 실제 코드를 작성한다.

public class Calculator {
    public int divide(int x, int y) {
        return x / y;
    }
}

실제 코드를 작성하여 통과하도록 해주었다.

이제 제대로 동작하는지 확인하기 위해 다른 실패 테스트를 만들어주자.

 

4. 2번으로 되돌아가서 실패하는 테스트 코드를 더 작성한다.

@DisplayName("두 수를 0으로 나누면 null이 반환된다.")
@Test
void divideZero() {
    Calculator calculator = new Calculator();
    
    int result = calculator.divide(4, 0);

    assertNull(result);
}

위의 테스트는 실패하게 되어있다.

왜냐하면 0으로 나누면 Exception in thread "main" java.lang.ArithmeticException: / by zero 예외가 발생하기 때문이다.

위의 테스트도 성공하도록 해주자.

 

5. 3번으로 가서 테스트가 성공하게 실제 코드를 수정해주자.

public class Calculator {
    public int divide(int x, int y) {
        return y == 0 ? null : x / y;
    }
}

요구사항 4번을 완료했다.

 

계산기는 내용이 간단하기 때문에 리팩터링 할 것이 크게 없지만, 다른 요구사항도 위와 같은 방법에 리팩터링까지 곁들이면 모든 개발이 완료된다.

 

(실제로 작성했던 코드는 깃허브에 있고, 스터디에서는 나눗셈은 제외하고 진행해서 블로그 글 쓸 때 작성해 보았습니다. )


 

적응을 하기 전까지 귀찮은 방법처럼 보일 수 있지만 적응하고나면 꽤 편하다.

만약 테스트 코드를 먼저 작성하지 못했다고 하더라도 개발이 끝나고 테스트 코드는 꼭 작성해보자.

 

실제로 회사에서는 깃허브 액션에서 PR 시 테스트 코드가 작동하도록 해두어서, 테스트를 깜빡하고 PR을 올렸을 때도 자동으로 테스트를 거치도록 설정해두었다. 그 결과 기존 코드를 수정했을 때 문제가 생긴 것을 미리미리 확인할 수 있었다.

물론 이후 QA에서 발견했겠지만 만약 제대로 확인되지 않고 배포되었다면..? 롤백했겠지뭐..

http://gunshowcomic.com/648


 

확실히 혼자 공부할때보다 다같이 공부하는게 더 재밌긴하다.

 

대신 스터디의 문제는 모르는 사람들끼리 모여서 하게되면 이게 맞는건지..틀린건지..알수가 없고..

그래서 어딜 어떻게 공부해야하는지, 맞는 길로 가는건지 알 수가 없어서 답답하다는건데,

이번 스터디는 TDD를 알고계시는 분이 주도해서 시작했던거라 답답함이 덜했다.

이 블로그를 존재도 모르시겠지만 빌려 주최해주신 D께 감사의 인사를 전합니다. 🕺

 

+ 스터디의 자세한 내용은 노션에 정리되어있습니다.

 

Comments