[JUnit] TDD -1
- JUnit
- 2020. 8. 17.
이번 글에서는 TDD에 대해 알아보도록 하겠습니다.
1. TDD란?
test먼저 작성하고 그 test를 통과시키는 code를 작성하는 방법입니다.
예를 들어 A+B를 더하는 메서드를 만들어야 하는 상황이라면, A+B를 더하는 메서드를 작성하기전에 그것을 테스트하는 코드를 먼저 작성합니다. 작성한 테스트는 당연히 실패할 것이고, 이제 해당 테스트가 통과할 수 있도록 메서드를 작성하면 되겠습니다.
이 때 각 테스트는 'single piece of logic'을 테스트해야 합니다. 하나의 메서드에 대해서 여러상황에 대한 테스트를 늘려나가다보면 어느새 완벽한 메서드가 만들어지게 되있을 것 입니다..😎!
2. Valid ISBN Number
이제 순서대로 TDD를 통해 코드를 작성해보도록 하겠습니다.
최종적으로 작성하고자하는 메서드는 valid한 ISBN Number를 검사하는 것 입니다. ISBN Number는 도서의 고유 번호? 정도로 생각하면 될 것 같습니다.
3. Create Project
시작해봅시다! 😆
먼저 Spring initializer를 사용해 아래와 같이 비어있는 프로젝트를 하나 생성하겠습니다.
다음으로 valid한 ISBN Number를 검사하는 ValidateISBN 클래스를 생성합니다.
여기서 중요한점은 ValidateISBN 클래스에 바로 code를 작성하는 것이아니라 이 비어있는 ValidateISBN 클래스를 Test하는 Test class를 작성하는 것부터 시작해야 된다는 것 입니다. 따라서 바로 Test 클래스인 ValidateISBNTest를 생성해줍니다.
ValidateISBN
public class ValidISBN {
}
ValidateISBNTest
public class ValidateISBNTest {
}
3. Fail
비어있는 Test 클래스를 생성한 뒤에는 아래와 같이 fail()을 호출하는 아무것도 작성되지 않은 test 메서드를 하나 작성합니다. 이 테스트는 당연히 실패할 것입니다.
public class ValidateISBNTest {
@Test
public void checkValidISBN(){
fail("Not ye implemented");
}
}
한번 테스트 해보도록 하겠습니다.
위와 같이 테스트가 실패했습니다. 이제 여러분은 TDD의 첫번째 단계인 'new test initially fail'를 통과한 것입니다 😅.
4. Pass
이제 다음으로 해야될 것은 위에서 실패한 Test를 통과시키는 것 입니다.
우리가 기대하는 outcome은 앞서 생성한 ValidateISBN 클래스가 valid한 ISBN Number를 검사하는 것 이기때문에, 아래와 같이 test code를 수정합니다.
이때 아직 ValidateISBN 클래스에는 checkISBN이라는 메서드가 존재하지 않습니다. 따라서 위와 같이 빨간색으로 표시된 것을 확인할 수 있습니다.
'Alt+Enter'를 누르고 checkISBN 메서드를 자동 생성합니다.
ValidateISBN
public class ValidateISBN {
public boolean checkISBN(int i) {
return false;
}
}
이제 기본적인 뼈대는 완성되었습니다. 다시 한번 test를 수행하면, 아직 까진 checkISBN 메서드가 아무것도 내용없이 false를 return하고 있으므로 테스트는 아래와 같이 실패합니다.
이제 checkValidISBN 테스트가 통과할 수 있도록 checkISBN에 code를 작성하면 됩니다.
TDD의 rule을 따라서 checkISBN에서 항상 true를 return하도록 아래와 같이 코드를 변경하면, checkValidISBN을 통과할 수 있습니다.
ValidateISBN
public class ValidateISBN {
public boolean checkISBN(int i) {
return true;
}
}
물론, 위의 code는 말도안되는 code입니다.. 😅 다만, TDD 정신에서는 이와 같은 절차를 따르도록 요구합니다. 다시한번 테스트를 수행하면 아래와 같이 test가 통과하는 것을 확인할 수 있습니다.
5. Refactoring
이제 마지막 단계입니다. 고칩시다!
5-1) checkInvalidISBN
위에서 작성한 말도안되는 checkISBN 메서드를 reafactoring해서 의미있는 메서드로 만들면 되겠습니다.
제대로된 checkISBN 메서드라면 valid/invalid를 구분할 수 있어야 할 수 있을 것입니다. 따라서, 아래와 같이 checkInvalidISBN test를 추가합니다.
/* Valid Number : 140449116 */
/* Invalid Number : 140449117 */
class ValidateISBNTest {
@Test
public void checkValidISBN(){
ValidateISBN validator = new ValidateISBN();
boolean result = validator.checkISBN(140449116);
assertTrue(result);
}
@Test
public void checkInvalidISBN(){
ValidateISBN validator = new ValidateISBN();
boolean result = validator.checkISBN(140449117);
assertFalse(result);
}
}
새롭게 작성한 checkInvalidISBN test를 실행시키면, 아래와 같이 test가 실패합니다. checkISBN 메서드는 아직까지 true만 return하는 code만 작성되어있으므로 당연한 결과입니다.
5-2) checkISBN
이제 checkISBN를 수정해 invalid Number는 false를 return 하도록 아래와 같이 수정합니다.
public class ValidateISBN {
public boolean checkISBN(int i) {
if(i == 140449116){
return true;
}
return false;
}
}
물론, 현재는 valid input값으로 '140449116'만 명시하고 있지만, 이는 향후 TDD를 통해 수정할 것이니 상관없습니다. 계속 진행합니다.
이제 checkISBN 메서드는 140449116일 경우에는 true를 그외의 숫자에는 false를 return할 것입니다. test 해보면 아래와 같이 2개의 테스트 모두 통과하는 것을 확인할 수 있습니다.
물론 아직까지도 checkISBN 메서드는 제대로된 메서드가 아닙니다. 단지 2개의 test를 통과하기위한 껍데기?.. 에 불과합니다. 아직까지 개선이 필요할 것 같습니다 😅.
5-3) checkValidISBN
조금더 수정해보도록 하겠습니다. 비슷하게 제대로된 checkISBN 메서드라면 모든 valid Number에는 true를 return할 것입니다. 아래와 같이 valid Number를 하나더 추가해 test 해보도록 하겠습니다.
@Test
public void checkValidISBN(){
ValidateISBN validator = new ValidateISBN();
boolean result = validator.checkISBN(140449116);
assertTrue(result);
/* 추가 */
result = validator.checkISBN(140177396);
assertTrue(result);
}
test가 실패했습니다. checkISBN 메서드는 아직까지 '140449116'의 input에 대해서만 true를 return하므로 당연한 결과입니다. 이제 이를 수정해야 합니다.
다음글에서는 제대로된 ISBN Number 로직을 작성해 보도록 하겠습니다.
참고 자료 : https://www.udemy.com/course/practical-test-driven-development-for-java-programmers/
추천서적
파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
'JUnit' 카테고리의 다른 글
[JUnit] Bad Test (0) | 2020.08.20 |
---|---|
[JUnit] Mock & Mockito -2 (0) | 2020.08.20 |
[JUnit] Mock & Mockito -1 (0) | 2020.08.20 |
[JUnit] Stub (0) | 2020.08.20 |
[JUnit] TDD -2 (0) | 2020.08.17 |