자동화된 테스트 작성
1972년 에츠허르 데이크스트라는 “The Humble Programmer“라는 에세이에서 “프로그램 테스트는 버그의 존재를 보여주는 데 매우 효과적이지만, 버그가 없다는 것을 보여주기에는 부적합하다“고 말했다. 하지만 그렇다고 해서 테스트를 최대한 많이 해보지 말라는 뜻은 아니다!
프로그램의 정확성은 코드가 우리가 의도한 대로 동작하는 정도를 의미한다. Rust는 프로그램의 정확성에 대해 높은 관심을 가지고 설계되었지만, 정확성을 증명하는 것은 복잡하고 쉽지 않다. Rust의 타입 시스템은 이러한 부담의 상당 부분을 떠안고 있지만, 타입 시스템만으로는 모든 것을 잡아낼 수 없다. 그래서 Rust는 자동화된 소프트웨어 테스트 작성을 지원한다.
예를 들어, 어떤 숫자에 2를 더하는 add_two
함수를 작성한다고 가정해보자. 이 함수의 시그니처는 정수를 매개변수로 받고 정수를 반환한다. 이 함수를 구현하고 컴파일하면, Rust는 지금까지 배운 타입 검사와 borrow 검사를 모두 수행하여, 예를 들어 String
값이나 잘못된 참조를 이 함수에 전달하지 않도록 보장한다. 하지만 Rust는 이 함수가 정확히 우리가 의도한 대로 동작하는지, 즉 매개변수에 2를 더하는지, 아니면 10을 더하거나 50을 빼는지 확인할 수 없다! 바로 여기서 테스트가 필요하다.
예를 들어, add_two
함수에 3
을 전달했을 때 반환 값이 5
인지 확인하는 테스트를 작성할 수 있다. 코드를 변경할 때마다 이러한 테스트를 실행하여 기존의 정상 동작이 변경되지 않았는지 확인할 수 있다.
테스트는 복잡한 기술이다. 이 한 장에서 좋은 테스트를 작성하는 방법의 모든 세부 사항을 다룰 수는 없지만, 이 장에서는 Rust의 테스트 기능에 대해 논의할 것이다. 테스트 작성 시 사용할 수 있는 어노테이션과 매크로, 테스트 실행 시 제공되는 기본 동작과 옵션, 그리고 테스트를 단위 테스트와 통합 테스트로 조직화하는 방법에 대해 이야기할 것이다.