로버트 C.마틴의 클린 코드를 읽고 정리한 내용입니다.
테스트는 유연성, 유지보수성, 재사용성을 제공한다.
테스트 케이스가 없다면 실제 코드를 유연하게 만드는 버팀목도 사라진다. 코드에 유연성, 유지보수성, 재사용서을 제공하는 버팀목이 바로 단위 테스트이다. 테스트 케이스가 있다면 실제 코드의 변경이 두렵지 않다. 테스트 케이스가 없다면 모든 변경은 잠정적인 버그가 된다.
테스트 코드가 지저분하면 코드를 변경하는 능력이 떨어지며 코드 구조를 개선하는 능력도 떨어진다. 테스트 코드가 지저분할수록 실제 코드도 지저분해지고 실제 코드도 망가진다.
깨끗한 테스트 코드
테스트 코드에서 가독성을 높이려면 가독성이 필요하다. 가독성을 높이기 위해서는 명로성, 단순성, 풍부한 표현력이 필요하다. 테스트 코드는 최소의 표현으로 많은 것을 나타내야 한다.
FIRST
FIRST 규칙에 대해 알아보자
Fast
각 테스트는 빠르게 실행되어야 한다. 테스트는 빈번하게 이루어지기 때문에 테스트가 느리면 자주 돌릴 엄두가 나지 않는다. 코드를 마음껏 정리하지도 못하고 결국 코드 품질이 망가지기 시작한다.
아래 코드는 데이터베이스 쿼리를 많이 수행하거나 테스트 데이터를 설정하는 데 시간이 오래 걸릴 수 있다.
// 나쁜 예
@Test
public void testDatabaseQuery() {
List<User> users = userRepository.findAll();
assertTrue(users.size() > 0);
}
// 좋은 예
@Test
public void testDatabaseQuery() {
when(userRepository.findAll()).thenReturn(Collections.singletonList(new User()));
List<User> users = userService.getAllUsers();
assertTrue(users.size() > 0);
}
Independent
각 테스트는 독립적이어야 한다. 한 테스트가 다음 테스트에 영향을 줘서는 안된다. 어떤 순서로 실행해도 괜찮아야 한다. 테스트가 의존하게 되면 한 테스트가 실패하면 다른 테스트도 잇달아 실패하므로 원인을 진단하기 어려워 진다.
// 나쁜 예
@Test
public void testFileCreation() {
File file = new File("example.txt");
assertTrue(file.createNewFile());
assertTrue(file.exists());
assertTrue(file.delete());
}
// 좋은 예
@Test
public void testCalculateTax() {
double amount = 100.0;
double taxRate = 0.1;
double expectedTax = 10.0;
double actualTax = taxCalculator.calculateTax(amount, taxRate);
assertEquals(expectedTax, actualTax, 0.01);
}
Repeatable
테스트는 어떤 환경에서도 반복 가능해야 한다. 테스트가 돌아가지 않는 환경이 하나라도 있다면 그러한 환경에서 테스트를 수행하지 못하기 때문이다.
// 나쁜 예
@Test
public void testWeatherService() {
String city = "New York";
WeatherService service = new WeatherService();
String temperature = service.getTemperature(city);
assertNotNull(temperature);
}
// 좋은 예
@Test
public void testSum() {
int a = 1;
int b = 2;
int expectedSum = 3;
int actualSum = calculator.sum(a, b);
assertEquals(expectedSum, actualSum);
}
Self-validating
테스트는 성공 아니면 실패다. 통과 여부를 알기 위해 로그 파일을 읽게 만들어서는 안된다. 테스트가 스스로 성공과 실패를 가늠하지 않는다면 판단은 주관적이 되어버린다.
// 좋은 예
@Test
public void testLogin() {
User user = new User("username", "password");
AuthenticationService authService = new AuthenticationService();
boolean result = authService.login(user);
assertTrue(result);
}
Timely
테스트는 적시에 작성해야 한다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다. 실제 코드를 구현한 다음에 테스트 코드를 만들면 실제 코드가 테스트하기 어렵다는 사실을 발견하게 된다. 실제 코드를 테스트가 불가능하도록 설계하게 될 수도 있다.
'책' 카테고리의 다른 글
면접을 위한 CS 전공지식 노트 - 시간 복잡도 (0) | 2023.04.18 |
---|---|
Clean Code - 의미있는 이름 (0) | 2023.04.17 |
Clean Code - 객체와 자료구조 (1) | 2023.04.12 |
면접을 위한 CS 전공지식 노트 - 조인 (JOIN) (0) | 2023.04.11 |
Clean Code - 클래스 (0) | 2023.04.06 |