안녕하세요 ^-^
또 다시 찾아온 클린코드 포스팅 시간입니다!
이제는 조금씩 클린코드에 대한 개념이 잡혀가고 있으신가요?
아직도 생소하신 분들을 위해서
링크들을 정리해 놓았으니
참고해주세요~!
다양한 주제가 있겠지만, 오늘은 Test Code 에 대해서 작성해볼까 합니다!!
시작해볼게요~!
Test Code
* 테스트 코드가 뭘까요?
또 또 또
알고리즘 문제를 예시로 들어볼게요.
우리가 백준에서 알고리즘 문제를 풀 때, 어떠한 중요 요소들이 있나요?
여러 가지 것들이 있겠지만, 아래와 같은 요소들이 제일 중요한 것 같습니다.
- 입력 예제
- 출력 예제
- 제출 현황
입력 예제는 흔히 말하는 Input
출력 예제는 Output
제출 현황은 내가 작성한 소스 코드의 메모리, 실행 시간 등을 담고 있습니다
결국에 제일 중요한 것은
Input으로 어떠한 데이터가 소스 코드로 들어갔을 때
내가 기대한 기대값의 Output이 나와야 되는 거에요!
이것은 실무에서도 똑같이 적용됩니다.
보통 실제 배포되는 Code를 Production Code라 칭하는데요
내가 생각한 로직을 Production Code에 작성하고, 이를 검증 받는 것이 Test Code라고 생각하면 쉬울 것 같습니다
예시를 또 금방 가져올게요~~
다음과 같은 Production Code가 있을 때,
package strategy;
class Scissor implements RockScissorPaper {
@Override
public String submit() {
return "Scissor";
}
}
Test Code는 다음과 같이 작성합니다!!
package strategy;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ScissorTest {
@Test
void 가위를_제대로_내는지_테스트() {
assertThat(new Scissor().submit()).isEqualTo("Scissor");
}
}
조금은 이해가 명확해지셨나요?
그러면 바로 다음 법칙으로 넘어갈게요~!
TDD(Test Driven Development)
TDD라 읽고 테스트 주도 개발 이라 읽는다.
앞에서 이제 Test Code에 대한 전반적인 내용을 기술하였는데요,
그럼 이 테스트 코드를 어떻게 개발에 적용해야 할까요?
우리가 계산기를 개발하고 싶다고 합시다.
계산기에는 2개의 숫자와 1개의 연산자가 Input으로 들어가겠죠?
들어간 Input 데이터를 바탕으로 하나의 Output이 나오게 되는데
Test Code를 작성해서 내가 생각한 시나리오대로 흘러가는지 작성하는 방식으로 구현하시면 됩니다!
이러한 원리를 적용해서 개발하는 방식이 바로
TDD(테스트 주도 개발) 입니다.
테스트 주도 개발은
- Test Code를 먼저 작성합니다
- 컴파일만 되게 Proudction Code를 수정하고
- 실패하는 Test Case에 대하여 Production Code를 리팩토링합니다
와 같은 Cycle을 가지고 있습니다!
여기서 가장 중요한 항목은
Test Code를 먼저 작성한다
꼭 꼭 지키셔야 합니다~!
자세한 리팩토링 과정은 이 본문에도 나와 있습니다!
테스트 하나당 assert 하나
여러개의 함수안에
여러 assert문을 넣으면 어떻게 될까요?
간단한 예시를 하나 가져왔어요
DoublyLinkedList를 테스트하는 코드인데요
@Test
void 제대로_순서대로_삽입되는지_테스트() {
/* Given */
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
/* When */
doublyLinkedList.pushSequence(3);
doublyLinkedList.pushSequence(2);
doublyLinkedList.pushSequence(8);
doublyLinkedList.pushSequence(1);
/* Then */
assertThat(doublyLinkedList.toString()).isEqualTo("1 2 3 8 ");
doublyLinkedList.pushBack(4);
assertThat(doublyLinkedList.toString()).isEqualTo("1 2 3 8 4 ");
doublyLinkedList.deleteNode(3);
assertThat(doublyLinkedList.toString()).isEqualTo("1 2 8 4 ");
}
테스트에 대한 의존성이 너무 연결되어 있는 느낌이 들지 않나요?
또한 무엇을 테스트하는지 의도가 명확하게 드러나지 않는 느낌도 들어요
처음에는 pushSequence( ) 메서드를 테스트하다가
갑자기 pushBack() 메서드도 테스트하고
또 deleteNode() 메서드도 테스트하고
정말 중구난방입니다
우리가 기억해야 될 것은
테스트 코드도 코드다.
Clean Code에 의하면 항상 코드에 의도를 명확하게 드러내야 해요
딱 한가지만 테스트할 수 있게 하는 것이 다른 사람이 읽기에도 정말 좋을 것 같아요
F.I.R.S.T
Test Code는 FIRST라는 다섯가지 규칙을 따릅니다.
- Fast : 테스트는 빨라야 한다.
- Independent : 각 테스트는 서로 의존하면 안된다.
- Repeatable : 테스트는 어떤 환경에서도 반복 가능해야 한다.
- Self-Validating : 테스트는 bool 값으로 결과를 내야 한다.
- Timely : 테스트는 실제 코드를 작성하기 전에 작성해야 한다.
한가지씩 천천히 살펴보면,
시스템을 구성하고 있는 코드가 점점 많아질 수록, 단위 테스트는 많아질 것이에요
그래서 복잡한 시스템일수록 테스트가 빨라야 검증이 빨라지겠죠?
앞에서 말한대로 테스트가 서로 의존되면
정말 유지보수하기 힘들어집니다
작성한 Test Code는 Production Code가 배포되는 그날까지
항상 함께해야 되요!!! 반드시
또한 assert 문을 통해 테스트가 True, False 인지 판별가능해야 하구요
테스트는 언제 작성한다?
Production Code를 작성하기 전에 작성한다!!
맺으며
오늘은 Test Code에 대해 살펴보았는데,
아마 깊이 있는 내용은 아니고 어느 정도 개념적인 것만 작성한 거라서
많이 모자를 수 있어요 ㅎㅎ
그때마다 항상 피드백 주시면 감사하겠습니다!
다같이 Clean Code를 작성하는 그날까지
다음 포스팅에서 만나요~ ^-^
'Developer > 개발서적' 카테고리의 다른 글
오브젝트(조영호) 책 후기 - 객체지향설계의 끝은 어디인가 (1) | 2020.01.07 |
---|---|
Clean Code(클린코드) - 우리가 코드를 깨끗하게 작성해야 하는 이유 : (1) 함수는 한가지 일만 제대로 하게 하라 (0) | 2019.12.11 |
Clean Code(클린코드) - 우리가 코드를 깨끗하게 작성해야 하는 이유 : 소개글 (0) | 2019.12.07 |
개발서적 - 객체지향의 사실과 오해 (0) | 2019.05.17 |