-
테스트 작성
- 요구사항에 맞는 테스트를 작성
- 아직 구현되지 않은 코드이므로 테스트 당연히 실패..😔
-
코드 작성
- 테스트를 통과하기 위한 최소한의 코드를 작성
-
리팩터링
- 코드를 개선하거나 정리하면서 테스트를 유지
테스트를 작성하고, 테스트를 통과하는 최소한의 코드를 작성하는 과정을 반복
class StrongBoxTest {
private lateinit var padlockBox: StrongBox<String>
private lateinit var buttonBox: StrongBox<Int>
private lateinit var dialBox: StrongBox<String>
private lateinit var fingerBox: StrongBox<Double>
@Before
fun setUp() {
padlockBox = StrongBox(KeyType.PADLOCK)
buttonBox = StrongBox(KeyType.BUTTON)
dialBox = StrongBox(KeyType.DIAL)
fingerBox = StrongBox(KeyType.FINGER)
}
@Test
fun `초기 호출은 null 리턴`() {
padlockBox.put("Treasure")
assertNull(padlockBox.get())
}
@Test
fun `10_000회까지 null 리턴 10_001회 도달하면 값 리턴 `() {
buttonBox.put(42)
repeat(10_000) { assertNull(buttonBox.get()) }
assertEquals(42, buttonBox.get())
}
}
enum class KeyType(val maxAttempts: Long) {
PADLOCK(1_024),
BUTTON(10_000),
DIAL(30_000),
FINGER(1_000_000)
}
class StrongBox<T>(private val keyType: KeyType) {
private var item: T? = null
private var usageCount: Long = 0
fun put(item: T) {
this.item = item
}
fun get(): T? {
if (usageCount >= keyType.maxAttempts) {
return item
}
usageCount++
return null
}
}
코드 구현 후 테스트를 실행해서 통과하는지 확인
코드를 개선하거나 Edge Case를 추가로 처리
@Test
fun `아무것도 넣지 않은 금고`() {
val emptyBox = StrongBox<String>(KeyType.DIAL)
assertNull(emptyBox.get())
repeat(30_000) { assertNull(emptyBox.get()) }
assertNull(emptyBox.get())
}
@Test
fun `금고에는 1개의 인스턴스만 담을 수 있다`() {
padlockBox.put("Treasure")
padlockBox.put("Diamond")
repeat(1_024) { assertNull(padlockBox.get()) }
assertEquals("Diamond", padlockBox.get())
}