SMALL
TDD 이란?
TDD 이란 테스트 주도 개발 이라고 한다. 프로덕션 코드보다 테스트 코드를 먼저 작성하는 개발 방법으로 쓰고 있고,
TFD ( Test First Development ) + 리팩토링 으로 기능 동작을 검증 한다. ( 매소드 단위 )
테스트 코드를 작성을 왜 할까?
나도 처음에는 테스트 코드 없이 그냥 바로 기능 개발하고 그때 그때 고치는 편이였다. 하지만 TDD 방법을 알게 되었고 그 방법을 통해 개발을 진행해보니 무엇보다 기능 결함이 없고 안전성이 확보 되었다. 그리고 문서화 역할도 테스트 코드에서 할수 있고, 테스트하기 위해 쉬운 코드를 작성하다 보면 더 낮은 결합도를 가진 설계를 얻을 수 있어서 테스트 코드를 작성하는것 같다. 아래에 예제를 통해 확인할 수 있다.
- 코드
PasswordValidatorTest.java
package org.example;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
/**
* 비밀번호는 최소 8자 이상 12자 이하여야 한다.
* 비밀번호가 8자 미만 또는 12자 초과인 경우 IllegalArgumentException 예외를 발생.
* NBSP 경계조건에 대해 테스트 코드를 작성해야 한다.
*/
public class PasswordValidatorTest {
@DisplayName("비밀번호는 최소 8자 이상 12자 이하면 예외가 발생하지 않는다.")
@Test
void validatePasswordTest() {
//메인에 있는 매서드를 통해 접근하여 값을 주고 오류가 나오는지 확인.
Assertions.assertThatCode(() -> PasswordValidator.validate("12345678912"))
.doesNotThrowAnyException();
}
@DisplayName("비밀번호가 8자 미만 또는 12자 초과인 경우 IllegalArgumentException 예외를 발생.")
@Test
void validatePasswordTest2() {
//만약 오류 발생시 IllegalArgumentException 라는 객체의 오류 인지? 확인후
//그 문자가 만약 비밀번호는 최소 8자 이상 12자 이하여야 한다. 인지도 확인.
Assertions.assertThatCode(() -> PasswordValidator.validate("1234567"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("비밀번호는 최소 8자 이상 12자 이하여야 한다.");
}
@DisplayName("비밀번호가 8자 미만 또는 12자 초과인 경우 IllegalArgumentException 예외를 발생.")
@ParameterizedTest //다른것들은 주소 참고. -> https://www.petrikainulainen.net/programming/testing/junit-5-tutorial-writing-parameterized-tests/
@ValueSource(strings = {"123456", "123456789123"})
void validatePasswordTest3(String password) {
//ParameterizedTest 는
//ValueSource 에 있는 값들을 validatePasswordTest3 매서드의 매개변수로 넣어줘서 테스트 진행.
Assertions.assertThatCode(() -> PasswordValidator.validate(password))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("비밀번호는 최소 8자 이상 12자 이하여야 한다.");
}
}
PasswordValidator.java
package org.example;
public class PasswordValidator {
public static void validate(String password) {
int length = password.length();
if(!(length >= 8 && length < 12)){
throw new IllegalArgumentException("비밀번호는 최소 8자 이상 12자 이하여야 한다.");
}
}
}
gradle
implementation('org.passay:passay:1.6.1')
testImplementation('org.assertj:assertj-core:3.23.1')
testImplementation('org.junit.jupiter:junit-jupiter-params:5.8.2')
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
또 다른 방법 BDD ( Behavior Driven Development )
BDD 는 행위 주도 개발이다. 시나리오를 만들고 그 시나리오를 기반으로 테스트 코드를 작성하는 개발 방법이다. 시나리오에는 Given When Then 구조를 가진다. 아래에 예제를 통해 확인할수 있다.
- 코드
UserTest.java
package org.example;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class UserTest {
@DisplayName("비밀번호는 초기화 여부를 판단한다.")
@Test
void passwordTest() {
//given
User user = new User();
//when
user.initPassword();
//then
Assertions.assertThat(user.getPassword()).isNotNull();
}
}
User.java
package org.example;
public class User {
private String password;
public void initPassword() {
RandomPasswordGenerator randomPasswordGenerator = new RandomPasswordGenerator();
String randomPassword = randomPasswordGenerator.generatePassword();
/*
* 비밀번호는 최소 8자 이상 12자 이하여야 한다.
*/
if (randomPassword.length() >= 8 && randomPassword.length() < 12) {
this.password = randomPassword;
}
}
public String getPassword() {
return password;
}
}
RandomPasswordGenerator.java
package org.example;
import org.passay.CharacterData;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.PasswordGenerator;
public class RandomPasswordGenerator {
public static final String ALLOWED_SPL_CHARCTERS = "!@#$%^&*()_+";
public static final String ERROR_CODE = "ERRONEOUS_SPECIAL_CHARS";
public String generatePassword(){
PasswordGenerator gen = new PasswordGenerator();
CharacterData lowerCaseChars = EnglishCharacterData.LowerCase;
CharacterRule lowerCaseRule = new CharacterRule(lowerCaseChars);
lowerCaseRule.setNumberOfCharacters(2);
CharacterData upperCaseChars = EnglishCharacterData.UpperCase;
CharacterRule upperCaseRule = new CharacterRule(upperCaseChars);
upperCaseRule.setNumberOfCharacters(2);
CharacterData digitChars = EnglishCharacterData.Digit;
CharacterRule digitRule = new CharacterRule(digitChars);
digitRule.setNumberOfCharacters(2);
CharacterData specialChars = new CharacterData() {
@Override
public String getErrorCode() {
return ERROR_CODE;
}
@Override
public String getCharacters() {
return ALLOWED_SPL_CHARCTERS;
}
};
CharacterRule splCharRule = new CharacterRule(specialChars);
splCharRule.setNumberOfCharacters(2);
return gen.generatePassword((int) (Math.random() * 13), splCharRule, lowerCaseRule, upperCaseRule, digitRule);
}
}
gradle
implementation('org.passay:passay:1.6.1')
testImplementation('org.assertj:assertj-core:3.23.1')
testImplementation('org.junit.jupiter:junit-jupiter-params:5.8.2')
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
반응형
LIST
'Spring' 카테고리의 다른 글
Querydsl (2) | 2023.05.19 |
---|---|
Rest Repositories (0) | 2023.05.19 |
DTO, Entity, Response 연관관계 (0) | 2023.05.16 |
JUnit5, AssertJ (0) | 2023.05.11 |
JPA (1) (0) | 2023.05.11 |