-
Notifications
You must be signed in to change notification settings - Fork 0
[99bottles] TDD
-
2.15:Verses 99 98 Literal
- 여기서의 duplication은 좋지 않음
- 아직 이해하지 못한 개념에 대한 독립적이고 구체적인 예를 보여주기 위한 중복은 괜찮음
- 예를 들어, 위에서 만들었던 verse에서의 중복(switch & case)은
- 각 케이스가 서로 다른 정보를 제공하고(unique)
- 기본적인 추상화는 함께 공유한다
- 방금 만든 중복은 독립된 새로운 예시가 아니고 이미 확인된 것을 복사하기만 했음
- 하지만 해당하는 내용(99, 98에 대한 가사)은 verse의
defaultstatement에 구현되어있음 - 새로운 정보를 제공하지 x, 이미 있는 예시를 활용하지 x => 중복이 허용되는 패턴에 해당 x
- 하지만 해당하는 내용(99, 98에 대한 가사)은 verse의
- 그리고 이렇게 verse의 코드를 복사해오는 것이 verses의 진짜 역할(책임)을 가린다.
- verses의 책임: 인자를 이해해서 제대로 된 output을 내는 것, verse의 가사들에 대해 알 필요가 x
- verse에게 반복해서 요청하고, 가사들을 엮어내는 것이 할 일이다.
- verse가 책임을 진 부분에 대해서 다른 부분이 그 책임을 빼앗으면 안된다.
- verses의 책임: 인자를 이해해서 제대로 된 output을 내는 것, verse의 가사들에 대해 알 필요가 x
- 여기서의 duplication은 좋지 않음
-
2.17:Verses 99 98 Message
- verse에게 메세지를 보내서 일을 하도록 시킴
-
이 경우에 다음에 무엇을 해야할지가 너무 명확하다. 이럴때는 바로 그것을 하면 된다.
-
"Green Bar Patterns" three well-defined workflows
- 켄트 벡이 자기 책에서 소개하고 있는 워크 플로우, 테스트가 계속 통과중인 상태에서의 작업
-
Obvious Implementation
- 명백하게 구현 방법을 알때 시도하는 방법
- 구현하는 부분이 사소할때만 시도해야 함
- 하다가 안되면 다른 두가지 방법을 써야 함
-
Fake It
- 패턴이나 알고리즘을 찾을 때까지 아주 작은 단위로 작업하는 것
- 가능한 빨리 테스트를 통과하도록 하며(정적 값을 이용하는 등) 나아가는 것
- 구현에 대해 알지만 제대로 파악하지 못한 것들이 있는 경우
-
Triangulate
- fake it과 대조적으로 더 많은 테스트 케이스를 추가할 것을 제안함
- 솔루션을 구현하는 방법을 전혀 모르는 경우
- 구현 아이디어가 안전하다고 생각되면 다시 fake it, obvious implementation으로 전환할 것
- 주의할 것은 테스트 코드를 실제 프로덕션 코드처럼 중요하게 여기고 리팩토링 해야한다는 것
99부터 0가지 loop를 돌아야한다는 점, verse에게 일을 시켜야하고 모아서 결과로 만들어야 한다는 점이 명확하다. 명확하면 그것을 바로 하면 된다. 테스트로부터 코드를 만들어 내면 구체적인 예들을 통해 추상화 할 수 있다.
-
2.20: Verses Within a Range

-
2~0에 해당하는 코드 생성하기(범위)
-
2.19처럼 if/else로 분기를 하는 방법이 있고 2.20처럼 추상화하는 방법이 있다. 이 경우에는
- 이해하기 쉬움
- 구현 비용이 저렴함
- 추상화를 위한 정보를 모두 가지고 있음 그러므로 추상화를 하는 것이 맞다.
이 챕터의 목적은 Bottles라는 클래스를 만든는 것인데, 이제 verse, verses를 했으니 song을 만들 차례이다. 유저는 song 대신에 verses(99, 0)를 이용할 수 있다. song이라는 삭제하지 않을 이유가 있는가?
하지만 유저는 99, 0이라는 정보를 알거나 Bottles가 어떻게 가사를 생산하는지 알 필요가 없다.
- song: 이름만 알면 사용할 수 있다.
- song대신 verses(99, 0)를 사용해야 한다면
- verses 메소드 이름
- 두개의 인자를 요구한다는 것
- 인자의 의미(start, end)
- 전체 음악을 생성하기 위해 start, end에 넣어야하는 숫자(99, 0)
의도와 실행의 차이를 이해하면 본질을 먼저 이해하고 디테일은 나중에 (필요하다면) 이해할 수 있다. (켄트 벡)
song : 의도
verses : 실행, 반드시 필요한 public API 이지만 song의 역할을 대신 할 수는 없다.
- 2.22: Shameless Green Initial
테스트 코드에서 몇가지 빠진것이 있다.(song, 4-97절에 대한 커버리지, 순서에 대한 test)
이 테스트를 강화시켜 봅시다.
-
TDD를 통해서 쉽게 바꿀 수 있고 간단하고 버그가 없는 소프트웨어를 만들 수 있다. 비용은 들지만 이익이 더 크다.
-
TDD에 대한 전반적인 동의가 있지만 바꾸기 어렵고 이해하기 힘들고 실행시간이 오래걸리는 테스트들이 존재한다. 이런 테스트는 변화를 방해한다.
-
이런 문제는 테스트가 코드와 너무 밀접해서 발생한다. 이런 경우 코드를 바꿀 때마다 테스트를 변경해야 한다.
-
테스트를 작성하는 것을 배우는 첫번째는 코드에 대해서 모른 상태로, 코드가 무엇을 하는지 확인하는 테스트를 짜는 것이다.
-
앞으로 test-to-code coupling에 대해서 살펴볼 것이며 아래는 현재의 테스트 코드 상태이다.
-
2.23: No Song Test
-
2.24: Whole Song Test Logic 이 song에 대한 테스트는 결함이 있다. song의 책임은 100개의 verses를 만드는 것이다. song이 가사를 어떻게 만들어내는지 모른다고 생각했을때, 테스트할 수 있는 방법은 전체 가사와 비교하는 것이다.
- 커플링 verses와 비교하는 것은 Bottles와 커플링이 일어난다. Bottles가 올바른 동작을 할때에도 테스트가 실패할 수 있다. (verses를 사용하는 방법이 바뀌었을때)
세부 구현을 바꾸었을때 실패하는 테스트들은 코드와 과도하게 커플링 되어있다고 볼 수 있고 이것은 변화를 느려지게 하고 비용을 증가시킨다.
- 2.25: Badly Broken Bottles Song 이 예시 코드는 제대로 된 song을 생성하지 않고 99-98 verses와 2-0 verses만 리턴한다. 이 코드는 테스트 코드의 약점을 이용했다.
이런 악용을 방지하기 위해 아래처럼 테스트를 변경할 수 있다.
- 2.26: Whole Song Test Logic Again
이런 식으로 바꾸는 것은 song을 실행시키는 것이 song에 포함된 코드를 실행시키는 것과 같다는 말을 하고 있다.
2.25에서
song()이verses(99, 0)과 같다고 말했던 것처럼 2.26에서는song()이downTo(99, 0).map(i => bottles.verse(i)).join('\n')과 같다고 말한다.
이 테스트는 Bottles의 코드를 그대로 흉내내고 있다. 한발짝 물러났지만 아직도 세부사항이 바뀌면 코드가 망가질 수 있다는 것은 변함이 없다.
- 2.27: Song Test song에 대한 테스트는 Bottles가 어떤 일을 하는지 몰라야 한다. song에 대한 기대는 완전한 가사를 생성할 것이라는 것이다.
길이가 너무 길어서 전체 가사를 쓰는것에 저항할 수도 있다. 그것에 대한 대안을 있을까?
- 다른 메소드의 output 이용하기
- 앞의 두 테스트가 해당됨
- 코드의 특성에 따라 달라지나 앞의 겨우에는 커플링이 일어남
- 동적으로 만든 string 이용하기
- 테스트내에서 동적으로 구절을 만드는 방법
- 이 경우에는 Bottles의 메소드를 강제로 호출하거나 구현해야하는데, 이런 논리를 사용하면 테스트가 예상치 못하게 중단될 수 있음
- hard-coded string 이용하기
- 예상출력이 명확하고 테스트에 종속성이 없기 때문에 이 경우에는 hard-coded string을 사용하는 것이 이해하기 쉽고 변경하기 쉽다.
우리에게 허용된 것은 세번째 옵션이다. 추상화는 코드를 위한 것이지 테스트를 위한 것이 아님 테스트는 구체적인 예시를 위한 공간이다. 테스트를 추상화하면 코드를 변경할 때마다 테스트가 깨질 수 있다.
이제 Bottles와 그에 대한 테스트가 모두 작성되었습니다.
-
테스트를
- 작은 단계로 코드를 작성할 때
- 커플링을 주의하고 현재 코드와 테스트를 분리할 때
-
이런 효과가 있다.
- 리팩토링하기 쉽고 코드를 안전하게 만듬
- 잘 짜여진 해결책으로 이끔
-
next
Shameless Green은 이해하기 쉽고 간단하다. 하지만 확장하기 좋거나 영리한 코드는 아니다.
Chapter3 에서는 새로운 요구사항들을 소개할 것이다.
- 테스트 작성 패턴 3가지/의도와 실행 구분하기/커플링/추상화는 코드에서