<일기>
어제 밤에 잠도 안 오고 자기도 싫고 해서 2시까지 그냥 누워만 있다가 유튜브 보다가 잤는데 일어나보니 8시 55분 ㅋㅋ 바로 수업 시작..
오늘은 오전엔 팀과제 하면서 구현을 조금 더 구체화 해두었고 다른 팀원분들이 작업 완료해야 내가 할 수 있는게 있어서 그거 빼고 다 완성해두었다.
오후에는 테스트 주도 개발 시작하기 책 읽었다. 150p 까지 코드 쳐보면서 노션에 정리하며 술술 읽고 있다. 내가 딱 찾던 테스트 입문서여서 재밌게 읽고 있다. 다 읽어버리고 싶은데 토요일에 이펙티브 자바 스터디가 있어서 그거 준비도 하고, 또 일요일에는 서평단으로 러닝 MYSQL 책도 리뷰 써야해서 훑어봐야한다. 그 사이 천천히 읽어보는걸로~
</일기>
오늘 플젝에서 팀원분이랑 캔버스로 이케이케 해서 서로 구현할 부분 조율해갔다.
색깔별로 각 담당할 부분을 정했었고, 내가 파랑이다. 내가 연관된 부분이 해주어야 할 것들을 다 적었다. 나 은근히 문서화 좋아하네. 내가 맡은 부분이 여기저기 걸쳐있어서 중앙에서 처리해줘야 해서 내가 골랐는데 그냥 여기 가져와서 저기 보내주고 끝나면 끝났어~ 하면 돼서 일찍 끝났다. 플로우차트를 다 그리기에는 너무 방대해서,, 따로 내 부분만 피그잼으로 만들어서 올려둘 생각이다. 아이패드에는 그렸는데 더 이쁘게 해서 올리는게 보기 좋으니~
이 밑으로는 오늘 TDD 책 읽고 정리한 부분. 깃허브에는 챕터 단위로 커밋을 해두었다.
04. TDD, 기능 명세, 설계
기능 명세
개발자가 코드를 작성하는 이유는 사용자가 사용할 어떤 기능을 제공하기 위함
기능에 대한 명세는 다양한 형태로 존재하지만, 기능은 크게 입력과 결과라는 두 가지 기능으로 나뉜다.
예를 들어, 로그인 기능은 아이디와 암호를 입력으로 받아 성공과 실패의 결과가 있다.
입력은 기능을 실행하는데 필요한 값이다. 보통 메서드의 파라미터로 전달한다.
결과는 여러 형식으로 정의할 수 있다. 리턴 값 형식도 있고, 변경도 있다. 결과는 상황에 따라 달라질 수 있다.
설계는 기능 명세로부터 시작한다. 스토리보드를 포함한 다양한 형태의 요구사항 문서를 이용해서 기능 명세를 구체화한다. 기능 명세를 구체화하는 동안 입력과 결과를 도출하고, 이렇게 도출한 기능 명세를 코드에 반영한다.
테스트 코드를 작성하는 과정에서 클래스 이름, 메서드 이름, 메서드 파라미터, 실행 결과 4가지를 결정했다.
타입의 이름을 정의하고, 타입이 제공할 기능을 결정하는 것은 기본적인 설계 행위이다. 이 과정에서 타입이 제공할 기능을 실행하는데 필요한 값과, 결과가 무엇인지 고민한다. 즉, TDD 자체가 설계는 아니지만, TDD를 하다보면 일부 설계를 진행하게 된다.
05. JUnit 5 기초
JUnit 5 모듈 구성
JUnit 5는 크게 3개의 요소로 구성되어 있다.
- JUnit 플랫폼 : 테스팅 프레임워크를 구동하기 위한 런처와, 테스트 엔진을 위한 API 제공
- JUnit 5 주피터 : JUnit 5를 위한 테스트 API와 실행 엔진을 제공
- JUnit 5 빈티지 : JUnit 3과 4로 작성된 테스트를 JUnit 5 플랫폼에서 실행하기 위한 모듈을 제공
JUnit을 이용하여 테스트 코드를 작성하는 방법은 테스트로 사용할 클래스를 만들고, private가 아닌 메서드 앞에 @Test 어노테이션을 붙이면 된다.
주요 단언 메서드
메서드 | 설명 |
assertEquals(expected, actual) | 실제 값(actual)이 기대하는 값(expected)과 같은지 검사 |
assertNotEquals(unexpected, actual) | 실제 값이 특정 값과 같지 않은지 검사 |
assertSame(Object expected, Object actual) | 두 객체가 동일한 객체인지 검사 |
assertNotSame(Object unexpected, Object actual) | 두 객체가 동일하지 않은 객체인지 검사 |
assertTrue(boolean condition) | 값이 true인지 검사 |
assertFalse(boolean condition) | 값이 false인지 검사 |
assertNull(Object actual) | 값이 null인지 검사 |
assertNotNull(object actual) | 값이 null이 아닌지 검사 |
fail() | 테스트를 실패 처리 |
assertThrows(Class<T> expectedType, Executable executable) | executable을 실행한 결과로 지정한 타입의 익셉션이 발생하는지 검사 |
asserDoesNottThrows(Class<T> expectedType, Executable executable) | executable을 실행한 결과로 지정한 타입의 익셉션이 발생하지 않는지 검사 |
assertAll(Executable… executables) | 모든 검증을 실행하고 그중에 실패한 것이 있는지 검사 |
테스트 라이프사이클
JUnit은 각 테스트 메서드마다 다음 순서대로 코드를 실행한다.
- 테스트 메서드를 포함한 객체 생성
- (존재하면) @BeforeEach 어노테이션이 붙은 메서드 실행
- @Test 어노테이션이 붙은 메서드 실행
- (존재하면) @AfterEach 어노테이션이 붙은 메서드 실행
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class LifecycleTest {
public LifecycleTest() {
System.out.println("new LifecycleTest");
}
@BeforeEach
void setUp() {
System.out.println("setUp");
}
@Test
void a() {
System.out.println("A");
}
@Test
void b() {
System.out.println("B");
}
@AfterEach
void tearDown() {
System.out.println("tearDown");
}
}
위 코드의 테스트 결과는
new LifecycleTest
setUp
A
tearDown
new LifecycleTest
setUp
B
tearDown
가 됨. 매 @Test를 돌릴 때마다 생성자가 실행됨.
@Test 메서드를 실행할 때마다 객체를 새로 생성하고 테스트 메서드를 실행하기 전후로 @BeforeEach, @AfterEach 어노테이션이 붙은 메서드를 실행함. @BeforeAll, @AfterAll 어노테이션이 붙은 건 각각 실행 전, 후에 한 번만 실행된다.
테스트 메서드 간 실행 순서 의존과 필드 공유를 하면 안 된다.
@DisplayName 어노테이션으로 테스트에 표시 이름을 붙일 수 있다.
@Disabled 어노테이션을 통해 특정 테스트를 실행하지 않을 수 있다.
모든 테스트를 실행하는 방법은 (나는 그레이들 래퍼를 사용하므로) 아래와 같다.
./gradlew test
06.테스트 코드의 구성
기능에서의 상황
기능은 주어진 상황에 따라 다르게 동작한다. 파일을 읽어올 때 파일이 없는 경우나, 숫자야구 같이.
테스트 코드의 구성 요소 : 상황, 실행, 결과 확인
기능은 상황에 따라 결과가 달라진다. 테스트 코드는 상황, 실행, 결과 확인의 3가지 요소로 테스트를 구성할 수 있다.
상황, 실행, 결과 확인은 영어 표현 given, when, then 에 대응한다.
@Test
void exactMatch() {
// 정답이 456인 상황 (given)
BaseballGame game = new BaseballGame("456");
// 실행 (when)
Score score = game.guess("456");
// 결과 확인 (then)
assertEquals(3, score.strikes());
assertEquals(0, score.ball());
}
물론 상황이 없는 경우도 존재한다. 상황-실행-결과 확인 구조에 너무 집착하지 않아야 한다.
외부 상태가 테스트 결과에 영향을 주지 않도록 실행 전에 외부를 원하는 상태로 만들거나, 테스트 실행 후에 외부 상태를 원래대로 되돌려 놓아야 한다. 하지만 외부 요인은 다루기 힘드므로, 대역을 통해서 외부 상황이나 결과를 대체할 수 있다.
'TIL ✍️' 카테고리의 다른 글
23년 10월 27일(금요일) - 19번째 TIL (0) | 2023.10.27 |
---|---|
23년 10월 26일(목요일) - 18번째 TIL (1) | 2023.10.26 |
23년 10월 24일(화요일) - 16번째 TIL (1) | 2023.10.24 |
23년 10월 23일(월요일) - 15번째 TIL (2) | 2023.10.23 |
23년 10월 20일(금요일) - 14번째 TIL (1) | 2023.10.20 |