티스토리 뷰

암호 강도 측정 기능을 TDD로 구현했을 때의 순서는 다음과 같았다.

 

1. 모든 규칙을 충족하는 암호 강도는 '강함' - 아무 것도 걸지 않고 그대로 보내버린다.

2. 길이만 8글자 미만이고 나머지 규칙은 충족하는 암호의 강도는 '보통' - 8글자 미만 if문을 짜고 보통을 리턴한다.

3. 숫자를 포함하지 않고 나머지 규칙은 충족하는 암호의 강도는 '보통' - 숫자 포함if문을 짜고 보통을 리턴한다.

4. 값이 없는 암호의 강도는 '유효하지 않음' - 값이 없으면 잘못된 값으로 리턴한다.

5. 대문자를 포함하지 않고 나머지 규칙은 충족하는 경우 - 대문자 관련 if문을 짜고 위 두개의 이프문을 사용하거나 변수로 결과값을 넣어 사용한다.

6. 길이가 8글자 이상인 규칙만 충족하는 경우 - 2번의 반대값으로 이프문을 짠다.

7. 숫자 포함 규칙만 충족하는 경우 - 3번의 반대값으로 이프문을 짠다

8. 대문자 포함 규칙만 충족하는 경우 - 5번 규칙에서 반대로 설정한다.

즉 모두 변수로 리팩토링이 가능하며 true false 값을 셀수 있게된다. 카운트를 매겨 9번을 해결 할 수 있게 된다.

9. 아무 규칙도 충족하지 않는 경우

 

이 순서가 중구 난방으로 보이지만 그냥 나온 것은 아니란다. 실제로 이 순서는 다음 규치겡 따라 나왔다.

1. 쉬운 경우에서 어려운 경우로 진행

2. 예외적인 경우에서 정상인 경우로 진행

반대로 어려운 경우를 먼저 시작하거나 정상 상황을 먼저 시작하면 구현 과정이 원활하게 진행 되지 않기도 한다.

 

초반에 복잡한 테스트부터 시작하면 안 되는 이유

- 만약 초반부터 다양한 조합을 검사하는 복잡한 상황을 테스트로 추가하면 해당 테스트를 통과 시키기 위해 한 번에 구현해야 할 코드가 많아진다. 예를 들어 다음 순서로 테스트를 진행한다면?

1. 대문자 포함 규칙만 충족하는 경우 : 아무것도 작성안하고 WEAK(약함) 값을 넣으면 된다.

2. 모든 규칙을 충족하는 경우 : 길이, 대문자 포함, 숫자 관련을 모두 통과 하게 끔 짜야한다.

3. 숫자를 포함하지 않고 나머지 규칙은 충족하는 경우 : 벌써 머리가 아프다. 숫자 포함하지 않는 if안에 대문자 포함, 길이 관련을 넣어야 할까? 고민이 들게 된다.

 

즉 어떤 값으로 if문을 짜고 값을 줘야할지 막막해지게 만든다. 쉬운 단계로 짜면서 결과값을 만들어 내야한다.

 

 

 

만약 기술 구현을 해야한다면 구현하기 쉬운 테스트는 뭘까?

 

1.  모든 조건을 충족하는 경우

2. 모든 조건을 충족하지 않는 경우

 

2번은 뭔가 다 구현해야 할 것 같다.

1번은 사실 가장 강한 결과값을 내면된다.

 

그 다음

1. 모든 규칙을 충족하지 않는 경우

2. 한 규칙만 충족하는 경우

3. 두 규칙을 충족하는 경우

 

1번은 다 짜야할것 같고

2번은 한 규칙만 충족시켜서 강도 약함을 넣어도 된다.

3번은 한 규칙만 틀려서 강도 보통을 넣어도 된다.

 

그렇다면 어떤 규칙을 테스트하는게 가장 빠를까? 그건 길이 검사가 간단할 거라 생각했다.

즉 길이가 8글자 이하고 두규칙을 충족하는 3번으로 간게 된다. 

즉, 하나의 조건문으로 두개의 충족결과를 만들 수 있다. 가장 빠르다.

반대도 마찬가지다. 길이가 8글자 이상이고 나머지 규칙은 충족하지 않는 경우는 강도 약함으로 설정한다.

이것도 1개의 조건문으로 해결이 된다.

 

예외상황을 먼저 테스트해야하는 이유

- 예외 상황을 전혀 고려하지 않은 코드에 예외 상황을 반영하려면 코드의 구조를 뒤집거나 코드 중간에 예외 상황을 처리하기 위해 조건문을 중복해서 추가하는 일이 벌어진다.

- TDD를 하는 동안 예외 상황을 찾고 테스트에 반영하면 예외 상황을 처리하지 않아 발생하는 버그도 줄어든다.

ㄴ 암호 등급 측정 예의 경우 암호 값이 없는 상황에 대한 테스트를 추가했다. 이 테스트를 추가하지 않으면 시스템 운영 중에 NPE가 발생할 수 있다.

 

 

TDD를 처음 할 때에는?

1. 정해진 값을 리턴 (하드로 리턴해버린다)

2. 값 비교를 이용해서 정해진 값을 리턴

3. 다양한 테스트를 추가하면서 구현을 일반화 한다.

 

위 단계를 거쳐서 연습하는 것과 바로 구현하는 것에는 차이가 있다.

테스트를 만들고 통과시키는 과정에서 구현이 막힐 때가 있다. 이럴 때 위 단계를 이용해서 TDD를 연습한 개발자는 조금씩 기능을 구현해 나갈 수 있다. 반면에 단계적으로 나아가는 연습을 하지 않은 개발자는 조금만 구현이 떠오르지 않아도 진전을 이루지 못하고 막혀있거나 한 번에 많은 코드를 구현하려고 시도한다. 그리고 실패할 확률이 올라간다.

 

만약 "asdd221" 라는 값을 넣는다면

if ("asdd221".equals(s)){
 return NORMAL;
}

 

이렇게 만들어 버린다.

그리고 추가로 "gfsd#41" 가 들어간다면 

 

if ("asdd221".equals(s) || "gfsd#41".equals(s)){
 return NORMAL;
}

이렇게 무조건 NORMAL이 나오게 하다가

상수를 제거하고 일반화 하는 것이다.

 

if (s.length() < 8){
 return NORMAL;
}

 

이 과정이 지루하게 느껴질 수도 있지만, 이런 연습과정을 나중에 코드가 잘 떠오르지 않을 때 점진적으로 구현을 진행할 수 있는 밑거름이 된다.

 

지속적인 리팩토링

테스트를 통과한 뒤에는 리팩토링을 진행하는데 리팩토링이 필요한 후보가 보이면 하면 된다.

 

코드 중복은 대표적인 리팩토링의 대상이다.

 

라틴 파울러의 리팩토링이 이라는 책이 도움이 된다. 1편은 자바 2편은 자바스크립트

 

구현 초기에는 전반적인 흐름을 모르기 떄문에 메서드 추출과 같은 리팩토링을 진행하면 코드 구조를 못잡을 가능성이 있다.

코드 구조가 잘못되면 다음 테스트를 통화시키는 과정에서 코드가 복잡해지거나 구현을 더는 진행하지 못하고 막힐 수 있따. 이럴 때에는 멈추고 메서드 추출 리팩토링을 다시 되돌려야한다.

 

그런 뒤에 코드의 의미나 구조가 더 명확해지면 그때 다시 리팩토링을 시도한다.

 

 

'dev_공부일지 > JAVA TDD' 카테고리의 다른 글

실제 테스트의 순서 정리  (0) 2024.06.08
TDD 시작  (0) 2024.05.23
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함