Backend Language/TDD

[TDD Chapter2] TDD ์‹œ์ž‘

chaerlo127 2023. 1. 12. 01:52
728x90

์†Œ์†๋œ GDSC MJU์—์„œ TDD ์Šคํ„ฐ๋””๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ, ๋‹ค์Œ ์ฑ…์„ ์ •๋ฆฌํ•˜๋Š” ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ…์„ ์ง„ํ–‰ํ•˜๊ณ ์ž ํ•œ๋‹ค.

 

ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ ์‹œ์ž‘ํ•˜๊ธฐ - YES24

TDD(Test-Driven Development)๋Š” ํ…Œ์ŠคํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค. ๊ตฌํ˜„์„ ๋จผ์ € ํ•˜๊ณ  ๋‚˜์ค‘์— ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋จผ์ € ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ๊ทธ๋‹ค์Œ์— ๊ตฌํ˜„ํ•œ๋‹ค. ๊ตฌํ˜„ ์ฝ”๋“œ๊ฐ€ ์—†๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์—ฌ๊ธฐ

www.yes24.com

 

๐Ÿ€ TDD Chapter 1: TDD ๊ฐœ๋ฐœ ์ค€๋น„

๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— build.gradle ์„ค์ •๋งŒ ์ž‘์„ฑํ•˜๊ณ  ๋„˜์–ด๊ฐ„๋‹ค.

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

	// junit ์ถ”๊ฐ€
	testImplementation('org.junit.jupiter:junit-jupiter:5.5.0')
}

 

 

๐Ÿ€ TDD Chapter 2: TDD ์‹œ์ž‘

๐Ÿ‘€ TDD๋ž€?

ํ…Œ์ŠคํŠธ๋ž€?
๊ธฐ๋Šฅ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ์„ ์ง„ํ–‰

๋ฏธ๋ฆฌ ์•ž์„œ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜์—ฌ ๊ฐœ๋ฐœ์„ ํ•˜์ง€ ์•Š๊ณ , 
ํ…Œ์ŠคํŠธํ•  ๋งŒํผ๋งŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ

์ง€์†์ ์ธ ์ฝ”๋“œ ์ •๋ฆฌ๋Š” ํ–ฅํ›„ ์œ ์ง€ ๋ณด์ˆ˜ ๋น„์šฉ์„ ๋‚ฎ์ถ”๋Š”๋ฐ ๋„์›€์ด ๋จ

TDD ํ๋ฆ„

์„ค๊ณ„ -> ํ…Œ์ŠคํŠธ -> ์ฝ”๋”ฉ -> ๋ฆฌํŒฉํ† ๋ง -> ํ…Œ์ŠคํŠธ

# Red - Green _Refactor
ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์‹คํŒจ : RED
ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์„ฑ๊ณต: GREEN
๋ฆฌํŒฉํ† ๋ง: REFACTOR
์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์‹คํŒจํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ์‹œํ‚ค๋Š” ๊ฒƒ ์˜๋ฏธ

 

 

์•„๋ž˜๋Š” ๊ฐ„๋‹จํ•œ ๋ง์…ˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ด๋‹ค 

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
/**
 * ๊ธฐ๋Šฅ์„ ์™„์„ฑํ•˜๋ฉด test package -> main package๋กœ ์ด๋™
 * ์™„์„ฑ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ๊ฐ€ ๋ฐฐํฌ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•จ
  */

public class CalculatorTest {

    @Test
    void plus(){
        int result = Calculator.plus(1, 2);
        assertEquals(3, result); // ์‹ค์ œ ๊ฐ’๊ณผ ๋™์ผ ํ•œ์ง€ ๋น„๊ต
        assertEquals(5, Calculator.plus(4, 1));
    }
}



public class Calculator {
    public static int plus(int a1, int a2){
        return a1+a2;
    }

 

  • @Test : ๊ธฐ๋Šฅ์„ ๊ฒ€์ฆํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋กœ ์ธ์‹
  • assertEquals(): ์ธ์ž๋กœ ๋ฐ›์€ ๋‘ ๊ฐ’์ด ๋™์ผํ•œ์ง€ ๋น„๊ต

 

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚œ ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ์—๋Š” test Package ์—์„œ main package๋กœ ์ด๋™ํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ์ค‘์ธ ์ฝ”๋“œ๋Š” ์•„์ง ์™„์ „ํ•˜์ง€ ์•Š์•„ ์‹ค์ œ main package์— ์žˆ์„ ๊ฒฝ์šฐ ๋ฐฐํฌ๋˜์–ด ์„œ๋น„์Šค ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ‘€ TDD ์˜ˆ: ์•”ํ˜ธ ๊ฒ€์‚ฌ๊ธฐ

ํ˜„์‹ค์ ์ธ ์•”ํ˜ธ ๊ฒ€์‚ฌ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž. 

์•”ํ˜ธ๊ฒ€์‚ฌ๊ธฐ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด 3๊ฐ€์ง€์˜ ๊ทœ์น™์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

1. ๊ธธ์ด๊ฐ€ 8๊ธ€์ž ์ด์ƒ
2. 0๋ถ€ํ„ฐ 9 ์‚ฌ์ด์˜ ์ˆซ์ž๋ฅผ ํฌํ•จ
3. ๋Œ€๋ฌธ์ž ํฌํ•จ
[๊ฐ•ํ•จ] ์„ธ๊ฐ€์ง€ ๊ทœ์น™์„ ๋ชจ๋‘ ์ถฉ์กฑ  [๋ณดํ†ต] 2๊ฐœ์˜ ๊ทœ์น™ ์ถฉ์กฑ  [์•ฝํ•จ] 1๊ฐœ ์ดํ•˜ ๊ทœ์น™ ์ถฉ์กฑ

 

1๏ธโƒฃ ์ฒซ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

TDD๋ฅผ ํ•˜๋ฉด์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. 

์ฒซ ๋ฒˆ์žฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ž˜ ์„ ํƒํ•˜์ง€ ์•Š์œผ๋ฉด ์ดํ›„ ์ง„ํ–‰ ๊ณผ์ •์ด ์ˆœํƒ„ํ•˜๊ฒŒ ํ˜๋Ÿฌ๊ฐ€์ง€ ์•Š๋Š”๋‹ค. 

 

์ฒซ ๋ฒˆ์งธ์˜ ๊ฒฝ์šฐ ๊ฐ€์žฅ ์‰ฝ๊ฑฐ๋‚˜ ๊ฐ€์žฅ ์˜ˆ์™ธ์ ์ธ ์ƒํ™ฉ์„ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.

์•”ํ˜ธ ๊ฒ€์‚ฌ๊ธฐ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜๊ฑฐ๋‚˜ ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ์ค‘์—์„œ ์„ ํƒํ•˜๋ฉด ๋˜๋Š”๋ฐ, ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋Š” ๋งŽ์€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ ๋ชจ๋“  ๊ฒ€์‚ฌ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ฐ€์žฅ ๋จผ์ € ์‚ดํŽด๋ณผ ์˜ˆ์ •์ด๋‹ค.
// ๊ธฐ๋ณธ์ ์ธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class PasswordStrengthMeterTest {

  @Test
  void meetsAllCriteria_Then_Strong() {
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter("123ABCDE456");
    assertEquals(PasswordStrength.STRONG, result);
  }

}
// ํ…Œ์ŠคํŠธ์— ํ•„์š”ํ•œ ์ฝ”๋“œ ์ž‘์„ฑ ํด๋ž˜์Šค
public class PasswordStrengthMeter {

    public PasswordStrength meter(String s) {
      return PasswordStrength.STRONG;
    }

}

// enum class
public enum PasswordStrength {
  STRONG;
}

 

2๏ธโƒฃ ๋‘ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๊ธธ์ด๋งŒ 8๊ธ€์ž ๋ฏธ๋งŒ์ด๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์€ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ 

ํŒจ์Šค์›Œ๋“œ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ 8๊ธ€์ž ๋ฏธ๋งŒ์ด๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์•”ํ˜ธ์˜ ๊ฐ•๋„๊ฐ€ ๋ณดํ†ต์ด์–ด์•ผ ํ•œ๋‹ค. 

public class PasswordStrengthMeter {
    public PasswordStrength meter(String s) {
        if (s.length() < 8) {
            return PasswordStrength.NORMAL;
        }
        return PasswordStrength.STRONG;
    }
}
// ํ…Œ์ŠคํŠธ ์ฝ”๋“œ
@Test
  void meetsOtherCriteria_except_for_Length_Then_Normal() {
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter("ab12!@A");
    assertEquals(PasswordStrength.NORMAL, result);
  }
  
  // enum class
public enum PasswordStrength {
  STRONG, NORMAL;
}

3๏ธโƒฃ ์„ธ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ์ˆซ์ž๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„์€ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

์ˆซ์ž๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์ด๋ฉฐ, ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์€ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ณดํ†ต ๊ฐ•๋„์˜ ์•”ํ˜ธ๋ฅผ ๊ฐ–๊ฒŒ ๋œ๋‹ค.

@Test
  void meetsOtherCriteria_except_for_Number_Then_Normal() {
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter("ab!@ABqwer");
    assertEquals(PasswordStrength.NORMAL, result);
  }
  
  public PasswordStrength meter(String s) {
        if (s.length()) {
            return PasswordStrength.NORMAL;
        }
        boolean containsNum - meetsContainingNumberCriteria(s);
       
        if(!containsNum) 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;
  }

 

4๏ธโƒฃ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ์ฝ”๋“œ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์˜ ๋Œ€์ƒ์ด๋‹ค. ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์—์„œ ์ค‘๋ณต์ด ๋ฐœ์ƒํ•˜๋ฉด ์•Œ๋งž๊ฒŒ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ์˜๋ฏธ๊ฐ€ ์ž˜ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค. 

ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ๋ฌดํ„ฑ๋Œ€๊ณ  ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
์ค‘๋ณต์„ ์ œ๊ฑฐํ•œ ํ›„์—๋„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€์ง€ ์•Š๊ณ  ์ˆ˜์ •์ด ์šฉ์ดํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค. 
์ค‘๋ณต์„ ์ œ๊ฑฐํ•œ ๋’ค์— ์˜คํžˆ๋ ค ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์ง€๋ฉด ์ œ๊ฑฐํ–ˆ๋˜ ์ค‘๋ณต์„ ๋˜๋Œ๋ ค์•ผ ํ•œ๋‹ค.

-> ๊ณผ๊ฑฐ, ํ•ญ์ƒ ์ฝ”๋“œ๋Š” ๊ฐ„๊ฒฐํ•œ ๊ฒƒ์ด ์ข‹๋‹ค๊ณ ํ•˜์—ฌ ์ค‘๋ณต๋œ ๊ฒƒ์„ ๋ชจ๋‘ extract method๋กœ ๋นผ๋‘์–ด์„œ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ์˜คํžˆ๋ ค ๋…์ด๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. 
 private PasswordStrengthMeter meter = new PasswordStrengthMeter();

    private void assertStrength(String password, PasswordStrength expStr){
        PasswordStrength result = meter.meter(password);
        assertEquals(expStr, result);
    }
    ///

    // ๋นˆ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ ๋˜ํ•œ ๋‚˜๋ฆ„๋Œ€๋กœ ์˜๋ฏธ๊ฐ€ ์žˆ์Œ
    @Test
    void name(){
    }

    @Test // ๋ชจ๋“  ๊ทœ์น™์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetsAllCriteria_Then_Strong(){
        assertStrength("ab12!@AB", PasswordStrength.STRONG);
        assertStrength("abc!Add", PasswordStrength.STRONG);
    }
    /**
     * assertEquals: ๋‘ ๊ฐ’์ด ๊ฐ™์€์ง€ ๋น„๊ตํ•˜๋Š” ๋‹จ์–ธ
     * ๋‹จ์–ธ: ๊ฐ’์˜ ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์— ์ต์…‰์…˜ ๋ฐœ์ƒ -> ํ…Œ์ŠคํŠธ ์‹คํŒจ
     */

    @Test // ๊ธธ์ด๋งŒ 8๊ธ€์ž ๋ฏธ๋งŒ์ด๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetsOtherCriteria_except_for_Length_Then_Normal(){
        assertStrength("ab12!@A", PasswordStrength.NORMAL);
    }

    @Test // ์ˆซ์ž๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์€ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetOtherCriteria_except_for_number_Then_Normal(){
        assertStrength("ab!@ABqwer", PasswordStrength.NORMAL);
    }

5๏ธโƒฃ ๋„ค ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ

// enum class
public enum PasswordStrength {
  STRONG, NORMAL, INVALID;
}

  public PasswordStrength meter(String s) {
  		if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
        if (s.length()) {
            return PasswordStrength.NORMAL;
        }
        boolean containsNum - meetsContainingNumberCriteria(s);
       
        if(!containsNum) 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;
  }

6๏ธโƒฃ ๋‹ค์„ฏ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๋Œ€๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

@Test // ๋Œ€๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetsOtherCriteria_except_for_Uppercase_Then_Normal(){
        assertStrength("ab12!@df", PasswordStrength.NORMAL);
}

  public PasswordStrength meter(String s) {
  		if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
        if (s.length()) {
            return PasswordStrength.NORMAL;
        }
        boolean containsNum - meetsContainingNumberCriteria(s);
        boolean containsUpp = meetsContainingUppercaseCriteria(s);
        if(!containsUpp) return PasswordStrength.NORMAL;
        if(!containsNum) 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;
      }

7๏ธโƒฃ ์—ฌ์„ฏ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๊ธธ์ด๊ฐ€ 8๊ธ€์ž ์ด์ƒ์ธ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ 

// enum class
public enum PasswordStrength {
  STRONG, NORMAL, WEAK, INVALID;
}

@Test // ๊ธธ์ด๊ฐ€ 8๊ธ€์ž ์ด์ƒ์ธ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetsOnlyLengthCriteria_Then_Weak(){
        assertStrength("abcdefghi", PasswordStrength.WEAK);
    }
  public PasswordStrength meter(String s) {
  		if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
       	boolean lengthEnough = s.length() >=8;
        
        /*if (s.length()) {
            return PasswordStrength.NORMAL;
        } */
        boolean containsNum - meetsContainingNumberCriteria(s);
        boolean containsUpp = meetsContainingUppercaseCriteria(s);
        // ๋ชจ๋“  ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•”ํ˜ธ ๊ฐ•๋„๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ๋‹ค
        if(!lengthEnough && !containsUpp && !containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough) return PasswordStrength.NORMAL;
        if(!containsUpp) return PasswordStrength.NORMAL;
        if(!containsNum) 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;
      }

 

if ์ ˆ์„ ์•„๋ž˜์— ๋‘๋Š” ์ด์œ ๋Š” 

1. ๊ฐœ๋ณ„ ๊ทœ์น™์„ ๊ฒ€์‚ฌํ•˜๋Š” ๋กœ์ง
2. ๊ทœ์น™์„ ๊ฒ€์‚ฌํ•œ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์•”ํ˜ธ ๊ฐ•๋„๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋กœ์ง

์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

 

8๏ธโƒฃ ์ผ๊ณฑ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ์ˆซ์ž ํฌํ•จ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

๋‹ค๋ฅธ ๋ฌธ์ž๋Š” ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ์ˆซ์ž๋กœ๋งŒ ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. 

// enum class
public enum PasswordStrength {
  STRONG, NORMAL, WEAK, INVALID;
}

    @Test // ์ˆซ์ž ํฌํ•จ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ , ์ˆซ์ž๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ
    void meetsOnlyNumCriteria_Then_Week(){
        assertStrength("12345", PasswordStrength.WEAK);
    }

  public PasswordStrength meter(String s) {
  		if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
       	boolean lengthEnough = s.length() >=8;
        
        /*if (s.length()) {
            return PasswordStrength.NORMAL;
        } */
        boolean containsNum - meetsContainingNumberCriteria(s);
        boolean containsUpp = meetsContainingUppercaseCriteria(s);
        // ๋ชจ๋“  ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•”ํ˜ธ ๊ฐ•๋„๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ๋‹ค
        if(!lengthEnough && !containsUpp && !containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough && !containsUpp && containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough) return PasswordStrength.NORMAL;
        if(!containsUpp) return PasswordStrength.NORMAL;
        if(!containsNum) 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;
      }

9๏ธโƒฃ ์—ฌ๋Ÿ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ๋Œ€๋ฌธ์ž ํฌํ•จ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

// enum class
public enum PasswordStrength {
  STRONG, NORMAL, WEAK, INVALID;
}

 	@Test // ๋Œ€๋ฌธ์ž ํฌํ•จ ์กฐ๊ฑด๋งŒ ์ถฉ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
    void meetsOnlyUpperCriteria_Then_Week(){
        assertStrength("ABZEF", PasswordStrength.WEAK);
    }

  public PasswordStrength meter(String s) {
  		if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
       	boolean lengthEnough = s.length() >=8;
        
        /*if (s.length()) {
            return PasswordStrength.NORMAL;
        } */
        boolean containsNum - meetsContainingNumberCriteria(s);
        boolean containsUpp = meetsContainingUppercaseCriteria(s);
        // ๋ชจ๋“  ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•”ํ˜ธ ๊ฐ•๋„๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ๋‹ค
        if(!lengthEnough && !containsUpp && !containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough && !containsUpp && containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough && containsUpp && !containsNum) return PasswordStrength.WEAK;
        if(!lengthEnough) return PasswordStrength.NORMAL;
        if(!containsUpp) return PasswordStrength.NORMAL;
        if(!containsNum) 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;
      }

๐Ÿ”Ÿ ์ฝ”๋“œ ์ •๋ฆฌ && ์•„ํ™‰ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ: ์•„๋ฌด ์กฐ๊ฑด๋„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ && ์ฝ”๋“œ ์ •๋ฆฌ: ์ฝ”๋“œ ๊ฐ€๋…์„ฑ ๊ฐœ์„ 

๋น„์Šทํ•œ ์ฝ”๋“œ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•œ๋‹ค. 

public class PasswordStrengthMeter {
    public PasswordStrength meter(String s){
        if(s == null || s.isEmpty()) return PasswordStrength.INVALID;
        int metCounts = getMetCriteriaCounts(s); // extract method -> ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด

        // ๊ฐœ๋ณ„ ๊ทœ์น™์„ ๊ฒ€์‚ฌํ•˜๋Š” ๋กœ์ง + ๊ทœ์น™์„ ๊ฒ€์‚ฌํ•œ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์•”ํ˜ธ ๊ฐ•๋„๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋กœ์ง
        if(metCounts <= 1) return PasswordStrength.WEAK;
        if(metCounts == 2) return PasswordStrength.NORMAL;
        return PasswordStrength.STRONG;
    }

    private int getMetCriteriaCounts(String s) {
        int metCounts = 0;
        if(s.length() >= 8) metCounts++;
        if(meetsContainingNumberCriteria(s)) metCounts++;
        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;
    }


}

1๏ธโƒฃ1๏ธโƒฃ ํ…Œ์ŠคํŠธ์—์„œ ๋ฉ”์ธ์œผ๋กœ ์ฝ”๋“œ ์ด๋™

๋ชจ๋‘ ๋‹ค ์ƒ์„ฑํ•œ ์ฝ”๋“œ๋Š” ํ…Œ์ŠคํŠธ ํŒจํ‚ค์ง€์—์„œ ๋ฉ”์ธ ํŽ˜ํ‚ค์ง€๋กœ ์ด๋™ํ•œ๋‹ค. 

 

 

728x90