1. 일곱 번째 테스트
숫자 포함 조건만 충족하는 경우
1) 테스트 코드 작성
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PasswordStrengthMeterTest {
private PasswordStrengthMeter meter = new PasswordStrengthMeter(); // 중복되는 코드, 필드에서 생성하도록 수정
private void assertStrength(String password, PasswordStrength expStr) { // 중복되는 코드, 메소드를 이용해서 제거
PasswordStrength result = meter.meter(password);
assertEquals(expStr, result);
}
// 생략
@Test
@DisplayName("비밀번호 강도 약함 - 숫자 포함 조건만 충족")
void meetsOnlyNumCriteria_Then_Weak() {
assertStrength("12345", PasswordStrength.WEAK);
}
}
2) 숫자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
public class PasswordStrengthMeter {
public PasswordStrength meter(String s) {
if (s == null || s.isEmpty()) // null, empty 처리를 위한 구현
return PasswordStrength.INVALID;
// 길이가 8자 이상인 경우 true
boolean lengthEnough = s.length() >= 8;
// 0~9 범위의 숫자가 있는 경우 true
boolean containsNum = meetsContainingNumberCriteria(s);
// 대문자를 포함하는 경우 true
boolean containsUpp = meetsContainingUppercaseCriteria(s);
// 길이가 8이상인 조건만 충족하는 경우를 통과시키기 위한 코드 추가
if (lengthEnough && !containsNum && !containsUpp) return PasswordStrength.WEAK;
// 숫자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
if (!lengthEnough && containsNum && !containsUpp) return PasswordStrength.WEAK;
if (!lengthEnough) return PasswordStrength.NORMAL;
if (!containsNum) return PasswordStrength.NORMAL;
if (!containsUpp) return PasswordStrength.NORMAL;
return PasswordStrength.STRONG;
}
// 숫자 확인 메소드 추출
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드 추출
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 테스트 코드 실행 통과
2. 여덟 번째 테스트
대문자 포함 조건만 충족하는 경우
1) 테스트 코드 작성
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PasswordStrengthMeterTest {
private PasswordStrengthMeter meter = new PasswordStrengthMeter(); // 중복되는 코드, 필드에서 생성하도록 수정
private void assertStrength(String password, PasswordStrength expStr) { // 중복되는 코드, 메소드를 이용해서 제거
PasswordStrength result = meter.meter(password);
assertEquals(expStr, result);
}
// 생략
@Test
@DisplayName("비밀번호 강도 약함 - 대문자 포함 조건만 충족")
void meetsOnlyUpperCriteria_Then_Weak() {
assertStrength("ABCD", PasswordStrength.WEAK);
}
}
2) 대문자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
public class PasswordStrengthMeter {
public PasswordStrength meter(String s) {
if (s == null || s.isEmpty()) // null, empty 처리를 위한 구현
return PasswordStrength.INVALID;
// 길이가 8자 이상인 경우 true
boolean lengthEnough = s.length() >= 8;
// 0~9 범위의 숫자가 있는 경우 true
boolean containsNum = meetsContainingNumberCriteria(s);
// 대문자를 포함하는 경우 true
boolean containsUpp = meetsContainingUppercaseCriteria(s);
// 길이가 8이상인 조건만 충족하는 경우를 통과시키기 위한 코드 추가
if (lengthEnough && !containsNum && !containsUpp) return PasswordStrength.WEAK;
// 숫자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
if (!lengthEnough && containsNum && !containsUpp) return PasswordStrength.WEAK;
// 대문자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
if (!lengthEnough && !containsNum && containsUpp) return PasswordStrength.WEAK;
if (!lengthEnough) return PasswordStrength.NORMAL;
if (!containsNum) return PasswordStrength.NORMAL;
if (!containsUpp) return PasswordStrength.NORMAL;
return PasswordStrength.STRONG;
}
// 숫자 확인 메소드 추출
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드 추출
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 테스트 코드 실행 통과
3. 코드정리
meter() 메소드 리팩토링
1) 작성된 코드를 보고 코드의 의미를 파악하여 코드 수정
public class PasswordStrengthMeter {
public PasswordStrength meter(String s) {
if (s == null || s.isEmpty()) // null, empty 처리를 위한 구현
return PasswordStrength.INVALID;
int metCounts = 0; // 조건의 개수 카운트를 위한 변수 추가
// 길이가 8자 이상인 경우 true
boolean lengthEnough = s.length() >= 8;
if (lengthEnough) metCounts++;
// 0~9 범위의 숫자가 있는 경우 true
boolean containsNum = meetsContainingNumberCriteria(s);
if (containsNum) metCounts++;
// 대문자를 포함하는 경우 true
boolean containsUpp = meetsContainingUppercaseCriteria(s);
if (containsUpp) metCounts++;
// 1개의 조건 충족 시 강도가 약함이라는 규칙을 잘 보여줌
if (metCounts == 1) return PasswordStrength.WEAK;
if (metCounts == 2) return PasswordStrength.NORMAL;
// 코드 수정 전
// // 길이가 8이상인 조건만 충족하는 경우를 통과시키기 위한 코드 추가
// if (lengthEnough && !containsNum && !containsUpp) return PasswordStrength.WEAK;
//
// // 숫자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
// if (!lengthEnough && containsNum && !containsUpp) return PasswordStrength.WEAK;
//
// // 대문자 포함 조건만 충족하는 경우를 통과시키기 위한 코드 추가
// if (!lengthEnough && !containsNum && containsUpp) return PasswordStrength.WEAK;
return PasswordStrength.STRONG;
}
// 숫자 확인 메소드 추출
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드 추출
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 테스트 실행 통과 확인
2) 수정된 코드 재 수정
public class PasswordStrengthMeter {
public PasswordStrength meter(String s) {
if (s == null || s.isEmpty()) // null, empty 처리를 위한 구현
return PasswordStrength.INVALID;
int metCounts = 0; // 조건의 개수 카운트를 위한 변수
// 길이가 8자 이상인 경우 metConuts 1증가
if (s.length() >= 8) metCounts++;
// 0~9 범위의 숫자가 있는 경우 metConuts 1증가
if (meetsContainingNumberCriteria(s)) metCounts++;
// 대문자를 포함하는 경우 metConuts 1증가
if (meetsContainingUppercaseCriteria(s)) metCounts++;
// 조건 충족 개수에 따른 강도가 잘 보임
if (metCounts == 1) return PasswordStrength.WEAK;
if (metCounts == 2) return PasswordStrength.NORMAL;
return PasswordStrength.STRONG;
}
// 숫자 확인 메소드 추출
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드 추출
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 테스트 코드 실행 통과
4. 아홉 번째 테스트
아무 조건도 충족하지 않은 경우
1) 테스트 코드 작성
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PasswordStrengthMeterTest {
private PasswordStrengthMeter meter = new PasswordStrengthMeter(); // 중복되는 코드, 필드에서 생성하도록 수정
private void assertStrength(String password, PasswordStrength expStr) { // 중복되는 코드, 메소드를 이용해서 제거
PasswordStrength result = meter.meter(password);
assertEquals(expStr, result);
}
// 생략
@Test
@DisplayName("아무 조건도 충족하지 않은 경우")
void meetsNoCriteria_Then_Weak() {
assertStrength("abc", PasswordStrength.WEAK);
}
}
-> 테스트 실행 통과 실패, 예상되는 값은 WEAK인데 STRONG이 나옴
2) 아무조건도 충족하지 않은 암호를 위한 코드 구현(코드는 방법 1로 구현)
- 방법 1. 충족 개수가 1개 이하인 경우 WEAK을 반환
- 방법2. 충족 개수가 0개인 경우 WEAK을 반환
- 방법3. 충족 개수가 3개인 경우 STRONG을 반환하는 코드를 추가하고 마지막에 WEAK 반환
public PasswordStrength meter(String s) {
if (s == null || s.isEmpty()) // null, empty 처리를 위한 구현
return PasswordStrength.INVALID;
int metCounts = 0; // 조건의 개수 카운트를 위한 변수
// 길이가 8자 이상인 경우 metConuts 1증가
if (s.length() >= 8) metCounts++;
// 0~9 범위의 숫자가 있는 경우 metConuts 1증가
if (meetsContainingNumberCriteria(s)) metCounts++;
// 대문자를 포함하는 경우 metConuts 1증가
if (meetsContainingUppercaseCriteria(s)) metCounts++;
// 조건 충족 개수에 따른 강도가 잘 보임
if (metCounts <= 1) return PasswordStrength.WEAK;
if (metCounts == 2) return PasswordStrength.NORMAL;
return PasswordStrength.STRONG;
}
// 숫자 확인 메소드 추출
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드 추출
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 테스트 코드 실행 통과
5. 코드 정리
코드 가독성 개선
- metCounts 변수를 계산하는 부분을 메서드로 빼서 가독성을 높임
public class PasswordStrengthMeter {
public PasswordStrength meter(String s) {
// null, empty 처리를 위한 구현
if (s == null || s.isEmpty())
return PasswordStrength.INVALID;
// 조건 충족 개수를 계산하는 metCounts 메소드 호출
int metCounts = getMetCriteriaCounts(s);
// 조건 충족 개수에 따른 강도
if (metCounts <= 1) return PasswordStrength.WEAK;
if (metCounts == 2) return PasswordStrength.NORMAL;
return PasswordStrength.STRONG;
}
// metCounts 계산 메소드
private int getMetCriteriaCounts(String s) {
int metCounts = 0; // 조건의 개수 카운트를 위한 변수
// 길이가 8자 이상인 경우 metConuts 1증가
if (s.length() >= 8) metCounts++;
// 0~9 범위의 숫자가 있는 경우 metConuts 1증가
if (meetsContainingNumberCriteria(s)) metCounts++;
// 대문자를 포함하는 경우 metConuts 1증가
if (meetsContainingUppercaseCriteria(s)) metCounts++;
return metCounts;
}
// 숫자 확인 메소드
private boolean meetsContainingNumberCriteria(String s) {
for(char ch : s.toCharArray()) {
if(ch >= '0' && ch <= '9') {
return true;
}
}
return false;
}
// 대문자 확인 메소드
private boolean meetsContainingUppercaseCriteria(String s) {
for(char ch : s.toCharArray()) {
if(Character.isUpperCase(ch)) {
return true;
}
}
return false;
}
}
-> 코드 리팩토링을 통해 가독성이 좋아짐
-> 테스트 및 코드 리팩토링이 끝난 파일을 src/test/java에서 src/main/java로 이동하면 끝!
'Spring > Test' 카테고리의 다른 글
TDD 테스트 주도 개발, 기능 명세와 설계 (0) | 2022.11.27 |
---|---|
TDD 테스트 코드 작성 방법 (0) | 2022.11.27 |
테스트 주도 개발 시작하기 - TDD 시작, TDD 암호 검사기 2 (0) | 2022.11.27 |
테스트 주도 개발 시작하기 - TDD 시작, TDD 암호 검사기 1 (0) | 2022.11.27 |
테스트 주도 개발 시작하기 - TDD 시작, TDD란 (0) | 2022.11.27 |