자동화 테스트 작성하기

에츠허르 다익스트라 (Edsger W. Dijkstra) 는 1972년 자신의 에세이 ‘겸손한 프로그래머 (The Humble Programmer)’에서 ‘프로그램 테스트는 버그의 존재를 보여주는 데에는 매우 효율적인 방법일 수 있지만, 버그의 부재를 보여주기에는 절망적으로 부적절하다’라고 말했습니다. 그렇다고 해서 가능한 많은 테스트를 시도하지 말아야 한다는 뜻은 아닙니다!

프로그램의 정확성은 곧 ‘프로그램이 얼마나 의도한 대로 작동하는가’와 같습니다. 러스트는 프로그램의 정확성에 굉장히 신경을 써서 설계된 언어지만, 정확성을 증명하기란 어렵고 복잡합니다. 러스트 타입 시스템이 이 역할의 큰 부담을 해소해 주고 있으나 타입 시스템만으로 모든 문제를 잡아내지는 못합니다. 따라서 러스트는 언어 자체적으로 자동화된 소프트웨어 테스트 작성을 지원합니다.

전달받은 숫자에 2를 더하는 add_two 함수를 작성한다고 칩시다. 함수 시그니처는 매개변수로 정수를 전달받고, 결과로 정수를 반환합니다. 이 함수를 구현하고 컴파일할 때 러스트는 앞서 배운 타입 검사 및 대여 검사를 수행합니다. 함수에 String 값이나 유효하지 않은 참조자가 전달될 일이 없도록 보장해 주죠. 하지만 러스트는 함수가 의도대로 작동하는지에 대해서는 검사할 수 없습니다. 함수가 매개변수에 2를 더하지 않고, 10을 더하거나 50을 빼서 반환해도 모를 일입니다! 이런 경우에 테스트를 도입합니다.

예를 들어 add_two 함수에 3을 전달하면 5가 반환될 것임을 단언 (assert) 하는 테스트를 작성하고 코드를 수정할 때마다 테스트를 실행하면, 제대로 작동하던 기존 코드에 문제가 생기지 않았을지 걱정할 필요가 없습니다.

테스트는 복잡한 기술입니다. 이번 장에서 좋은 테스트를 작성하는 방법에 대한 모든 것을 전부 다룰 수는 없습니다. 이번 장은 러스트의 테스트 메커니즘을 설명합니다. 테스트 작성 시 사용하는 어노테이션, 매크로를 배우고, 테스트 실행 시의 기본 동작과 실행 옵션, 유닛 테스트와 통합 테스트를 조직화하는 방법을 배워보도록 하죠.