실습 · 연습문제 1개
버그를 잡는 테스트 쓰기 standardize-check
이번에는 함수를 구현하는 것이 아니라 테스트를 쓴다. 채점기는 여러분의 테스트에 올바른 구현 두 개와 버그가 있는 구현 여러 개를 넣어 본다. 좋은 테스트는 올바른 구현을 모두 통과시키고, 버그가 있는 구현은 모두 실패시킨다.
테스트할 함수의 명세는 다음과 같다.
standardize(x)는 shape(N, D)인 float 배열x를 받아, 같은 shape의 새 배열을 반환한다. 반환한 배열의 각 열은 평균이 0이고 표준편차(ddof=0, 즉 으로 나눈 것)가 1이다. 값이 모두 같은 열(표준편차 0)은 모두 0이 된다. 입력 배열x는 바꾸지 않는다.
함수 check_standardize(standardize)를 완성한다. 인자로 받은 구현이 명세를 어기면 AssertionError를 내고(assert 문이나 np.testing.assert_allclose를 쓰면 된다), 명세를 지키면 아무것도 하지 않고 끝난다. 테스트 데이터는 함수 안에서 직접 만든다.
채점기가 넣어 보는 버그는 연구 코드에서 실제로 흔한 것들이다. 무엇인지는 직접 생각해 본다. 명세의 문장 하나하나가 테스트 하나가 될 수 있다.
주의할 점:
- 올바른 구현이라도 부동소수점 오차 때문에 평균이 정확히 0이 되지 않는다. 0과 비교할 때 상대 허용오차(
rtol)는 소용이 없다. - 채점기의 올바른 구현 둘은 계산 순서가 달라 마지막 자릿수가 다를 수 있다. 같은 공식을 테스트 안에 그대로 복사해
==로 비교하는 테스트는 올바른 구현을 떨어뜨린다. - 행과 열의 수가 같은 입력(정사각 행렬)만 쓰면 놓치는 버그가 있다.