diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculator.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculator.java" new file mode 100644 index 0000000..ba73d0e --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculator.java" @@ -0,0 +1,41 @@ +package testdriven.chap03; + + +import java.time.LocalDate; +import java.time.YearMonth; + +public class ExpiryDateCalculator { + public LocalDate calculateExpiryDate(PayData payData) { + int addedMonths = payData.getPayAmount() == 100_000 ? 12: payData.getPayAmount() / 10_000; + if (payData.getFirstBillingDate() != null) { + return expiryDateUsingFirstBillingDate(payData, addedMonths); + } else { + return payData.getBillingDate().plusMonths(addedMonths); + } + } + + private LocalDate expiryDateUsingFirstBillingDate(PayData payData, int addedMonths) { + LocalDate candidateExp = payData.getBillingDate().plusMonths(addedMonths); + final int dayOfFirstBilling = payData.getFirstBillingDate().getDayOfMonth(); + // 첫 납부 일자(31일)와 후보 만료일의 일자(28일)이 같지 않을때 + if (isSameDayOfMonth(candidateExp, dayOfFirstBilling)) { + // 후보 만료일(실제 날짜로 확인)이 첫 돈을 낸 일자보다 더 작은 경우에는 후보 만료일의 일자로 return + final int dayLenOfCandiMon = lastDayOfMonth(candidateExp); + if (dayLenOfCandiMon < dayOfFirstBilling) { + return candidateExp.withDayOfMonth(dayLenOfCandiMon); + } + // 첫 납부일의 일자를 후보 만료일의 일자로 사용 + return candidateExp.withDayOfMonth(dayOfFirstBilling); + }else{ + return candidateExp; + } + } + + private boolean isSameDayOfMonth(LocalDate candidateExp, int dayOfFirstBilling) { + return dayOfFirstBilling != candidateExp.getDayOfMonth(); + } + private int lastDayOfMonth(LocalDate date) { + return YearMonth.from(date).lengthOfMonth(); + } +} + diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculatorTest.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculatorTest.java" new file mode 100644 index 0000000..25190d5 --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/ExpiryDateCalculatorTest.java" @@ -0,0 +1,86 @@ +package testdriven.chap03; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ExpiryDateCalculatorTest { + + @Test + void 만원_납부하면_한달_뒤가_만료일이_됨(){ + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 3, 1)) + .payAmount(10_000) + .build(), + LocalDate.of(2019, 4, 1)); + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 1, 5)) + .payAmount(10_000) + .build(), + LocalDate.of(2019, 2, 5)); + } + + @Test + void 납부일과_한달_뒤_일자가_같지_않음(){ + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 1, 31)) + .payAmount(10_000) + .build(), + LocalDate.of(2019, 2, 28)); + } + + @Test + void 첫_납부일과_만료일이_일자가_다를때_만원_납부(){ + PayData payData = PayData.builder() + .firstBillingDate(LocalDate.of(2019, 5, 31)) + .billingDate(LocalDate.of(2019, 6, 30)) + .payAmount(10_000) + .build(); + assertExpiryDate(payData, LocalDate.of(2019, 7, 31)); + } + + @Test + void 이만원_이상_납부하면_비례해서_만료일_계산(){ + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 3, 1)) + .payAmount(20_000) + .build(), LocalDate.of(2019, 5, 1)); + + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 3, 1)) + .payAmount(30_000) + .build(), LocalDate.of(2019, 6, 1)); + } + + @Test + void 첫_납부일과_만료일_일자가_다를때_이만원_이상_납부(){ + assertExpiryDate(PayData.builder() + .firstBillingDate(LocalDate.of(2019, 1, 31)) + .billingDate(LocalDate.of(2019, 2, 28)) + .payAmount(20_000) + .build(), LocalDate.of(2019, 4, 30)); + + assertExpiryDate(PayData.builder() + .firstBillingDate(LocalDate.of(2019, 3, 31)) + .billingDate(LocalDate.of(2019, 4, 30)) + .payAmount(30_000) + .build(), LocalDate.of(2019, 7, 31)); + + } + + @Test + void 십만원을_납부하면_1년_제공(){ + assertExpiryDate(PayData.builder() + .billingDate(LocalDate.of(2019, 1, 28)) + .payAmount(20_000) + .build(), LocalDate.of(2020, 1, 28)); + } + + private void assertExpiryDate(PayData payData, LocalDate expectedExpiryDate) { + ExpiryDateCalculator cal = new ExpiryDateCalculator(); + LocalDate expiryDate = cal.calculateExpiryDate(payData); + assertEquals(expiryDate, expectedExpiryDate); + } +} diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrength.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrength.java" new file mode 100644 index 0000000..f865c27 --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrength.java" @@ -0,0 +1,5 @@ +package testdriven.chap03; +// 테스트 진행할 만큼만 코드를 작성하고 추가해나가기 +public enum PasswordStrength { + STRONG, NORMAL, INVALID, WEAK; +} diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeter.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeter.java" new file mode 100644 index 0000000..3fab13e --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeter.java" @@ -0,0 +1,11 @@ +package testdriven.chap03; + +public class PasswordStrengthMeter { + + public PasswordStrength meter(String s){ +// if("ab12!@A".equals(s) || "Ab12!c".equals(s)) return PasswordStrength.NORMAL; + if(s.length()<8) return PasswordStrength.NORMAL; + else return PasswordStrength.STRONG; + } + +} diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeterTest.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeterTest.java" new file mode 100644 index 0000000..31bf204 --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PasswordStrengthMeterTest.java" @@ -0,0 +1,17 @@ +package testdriven.chap03; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class PasswordStrengthMeterTest { + @Test + void meetsOtherCreteria_except_for_length_Then_Normal(){ + testdriven.chap03.PasswordStrengthMeter meter = new PasswordStrengthMeter(); + PasswordStrength result = meter.meter("ab12!@A"); + assertEquals(PasswordStrength.NORMAL, result); + PasswordStrength result2 = meter.meter("Ab12!c"); + assertEquals(PasswordStrength.NORMAL, result2); + } + +} diff --git "a/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PayData.java" "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PayData.java" new file mode 100644 index 0000000..d688275 --- /dev/null +++ "b/\354\236\245\354\261\204\354\235\200/test-driven/src/test/java/testdriven/chap03/PayData.java" @@ -0,0 +1,56 @@ +package testdriven.chap03; + +import net.bytebuddy.asm.Advice; +import org.springframework.test.web.reactive.server.WebTestClient; + +import java.time.LocalDate; + +public class PayData { + private LocalDate billingDate; + private LocalDate firstBillingDate; + private int payAmount; + private PayData(){} + + public PayData(LocalDate firstBillingDate, LocalDate billingDate, int payAmount){ + this.firstBillingDate = firstBillingDate; + this.billingDate = billingDate; + this.payAmount = payAmount; + } + + public LocalDate getFirstBillingDate(){ + return firstBillingDate; + } + public LocalDate getBillingDate(){ + return billingDate; + } + public int getPayAmount(){ + return payAmount; + } + + public static Builder builder(){ + return new Builder(); + } + + public static class Builder{ + private PayData payData = new PayData(); + + public Builder firstBillingDate(LocalDate firstBillingDate){ + payData.firstBillingDate = firstBillingDate; + return this; + } + + public Builder billingDate(LocalDate billingDate){ + payData.billingDate = billingDate; + return this; + } + + public Builder payAmount(int payAmount){ + payData.payAmount = payAmount; + return this; + } + + public PayData build(){ + return payData; + } + } +}