Topic 42 속성 기반 테스트
데이비드 토머스, 앤드류 헌트
느낌표 ! (인상 깊은 문장 | 문맥)
계약, 불변식, 속성
<항목 23. 계약에 의한 설계>에서 우리는 코드가 지켜야 하는 ‘계약’을 코드에 포함하자고 이야기했다. 선행 조건에 맞추어 입력을 넣으면 코드가 생산하는 출력이 주어진 후행 조건에 맞음을 보장해 준다.
p.322
계약의 예를 들자면 398831488 bytes -> 380MB 로 표현해주는 함수가 있다. 이를 검증하기 위해서는 assert.equal(niceBytes(398831488), ‘380MB’) 를 통해 검증할 수 있다. 이처럼 특정 값을 입력했을 때 출력을 검사하는 것이 계약이라고 볼 수 있다.
‘불변식 invariant‘이라는 것도 있었는데, 함수 실행 전후로 계속 어떤 부분의 상태에 대하여 참이 되는 조건을 말한다. 예를 들어, 리스트를 정렬했을 때의 결과는 정렬하기 전 리스트와 원소의 수가 같을 것이다. 그렇다면 리스트의 길이가 불변식에 해당한다. 이렇게 코드에 존재하는 계약과 불변식을 뭉뚱그려서 ‘속성 property‘이라고 부른다. 코드에서 속성을 찾아내서 테스트 자동화에 사용할 수 있는데, 이것을 ‘속성 기반 테스트 property-based testing‘라 한다.
p.322
책에서는 정렬의 예를 드는데 정렬을 하기 전의 리스트와 정렬을 한 후의 리스트의 원소의 수가 같다는 것을 계약으로 정의하고 소개하고 있다.
불변식은 입력에 따라서 변하는 값이 아니라 입력에 상관없이 변하지 않는 값이다.
속성 기반 테스트는 우리를 자주 놀래킨다
속성 기반 테스트가 강력한 까닭은 그저 입력을 생성하는 규칙과 출력을 검증하는 단정문만 설정한 채 제멋대로 작동하도록 놔두기 때문이다.
p.328
속성 기반 테스트 없이 작성하다보면 테스트 케이스는 통과하는데 버그를 발견하곤한다. 당연히 살펴보면 테스트 케이스는 오류의 상황을 가정하지 못한 것이다. 이를 방지하기 위한 구체적인 방안과 추상적인 방안도 있겠지만 속성 기반 테스트로 그러한 상황을 꽤나 많이 방지할 수 있다.
속성 기반 테스트가 실패했다면 테스트 함수가 어떤 매개 변수를 사용했는지 알아낸 다음 그 값을 이용하여 별도의 단위 테스트를 정식으로 추가하는 것이 좋다. 이 단위 테스트는 두 가지 역할을 한다. 첫 번째는 속성 기반 테스트의 여러 가지 다른 수행 결과와 상관없이 문제가 발생하는 상황에 집중할 수 있게 해 준다. 두 번째는 단위 테스트가 ‘회귀 테스트 regression test‘역할을 한다. 속성 기반 테스트는 임의의 값을 생성하여 사용하기 때문에 다음번에 실행했을 때 똑같은 값을 테스트 함수에 넘긴다는 보장이 없다. 문제를 일으켰던 값을 사용하는 단위 테스트를 만들어 두면 버그가 완전히 해결되었음을 보장할수 있다.
p.329
책에서는 숫자 정렬 시 랜덤한 숫자를 사용하도록 하였는데 이는 테스트할 때마다 통과를 장담할 수 없다. 만약 통과하지 못한 경우가 있다면 해당 값은 단위 테스트로 만들어 사용하기를 권장하고 있다.
속성 기반 테스트는 설계에도 도움을 준다
속성 기반 테스트는 여러분이 코드를 불변식과 계약이라는 관점으로 바라보게 한다. 여러분은 무엇이 변하지 않아야 하고, 어떤 조건을 만족해야 하는지 생각하게 된다. 이런 관점으로 보면 코드에 마법과 같은 효과가 일어난다. 경계 조건은 줄어들고, 데이터의 일관성을 해치는 함수는 더 도드라진다.
p.329
기능을 잘 만들 때는 머릿속에 정리에 깔끔하게 되어야하는데 이 때 도움 받을 수 있는 것은 경계 값이다. 경계 값에 따라 다른 로직이 필요하기 때문에 이를 종이에 옮겨 도식화를 해보면 한결 쉬워진다. 이것이 끝이 아니라 속성 기반 테스트를 위해 불변식을 생각해보면 더욱 좋은 설계와 깔끔한 로직이 나올 수 있을 것이다.
Topic 42 느낌
Topic 42 에서는 속성 기반 테스트의 예제와 장점을 알기 쉽게 설명하고 있다.