iOS 테스팅⚒️: Public API vs @testable
@testable은 Xcode에서 테스트 코드 작성을 처음 시작할 때 만날 수 있습니다. 처음 테스트 코드를 작성할 때 만나기에 ‘왜 써야 하지?’에 대한 명확한 정의 없이 사용하기 십상입니다. @testable을 사용하면 어떤 이점을 얻을 수 있고 사용 시 고려해야 할 점에 대해 나눠보려 합니다. 💡 @testable 1️⃣ Internal 또는 Public으로 표시된 Class와 Class의 상태, 동작이 마치 Public으로 선언된 것처럼 동작하기 시작합니다. 2️⃣ Entity나 Model로 주로 사용하는 Struct 역시 Public으로 선언된 것처럼 동작하기 시작합니다. 3️⃣ Public으로 선언된 것처럼 동작하기 시작하기 때문에 테스트 코드에서 서브클래싱이 가능합니다. 당연하겠지만 @testable을 사용하지 않으려면 API에 접근제어자를 선언해야 합니다😀 💡 PublicAPI PublicAPI 라는 건 엔지니어의 약속입니다. 동료 엔지니어에게 ‘이 API를 공개합니다!’ 의 의미보다 더 중요한 건 ‘공개하지 않는 API 내부 구현을 최대한 숨겼다 !’입니다. 이 약속은 코드 작성자가 원하는 만큼 API 내부 구조를 변경할 수 있는 자유를 제공하며, 접근할 수 있는 공개 API가 변경되지 않는 한 동료 엔지니어는 눈 하나 깜짝하지 않을 것입니다!!😌 @testable을 사용하면 ‘API 내부 구현을 최대한 숨겼다’라는 약속하지 않기 때문에 고려해야 할 사항이 있습니다. 테스트 대상(SUT)의 동작을 테스트 후 고객의 피드백에 따라 객체 동작 변경이 발생했을 때 테스트 케이스도 수정해야 하는 상황이 발생하곤 합니다. 물론 PublicAPI를 사용한다고 해서 테스트 케이스를 수정해야 하는 상황이 발생하지 않는 것이 아닙니다. 다만 PublicAPI의 ‘내부 구현을 최대한 숨겼다.’라는 약속이 깨졌습니다. 이런 상황에서 팀에 오가는 대화 중 “이 테스트는 지난주에 작성했는데, 왜 리팩터링에 도움이 되기는커녕 방해가 될까?” 이런 말이 나왔다면, 일반적으로 PublicAPI가 아닌 구현 세부 사항(Private)을 테스트하고 있다는 신호입니다. 다시 테스트 코드를 수정할 때 비용이 발생하지만 테스트 케이스의 가치가 없다고는 볼 수 없습니다. 하지만 이 상황을 결과로 테스트 케이스의 신뢰도가 떨어진다면 큰 문제입니다. ❗️@testable 사용 시 고려할 사항 @testable을 사용해서 생긴 문제라기보단 팀에서 정한 약속이 없으므로 생긴 문제입니다. 문제를 피하려고 테스트 해야 할 PublicAPI를 만들고 PublicAPI만 테스트하는 것을 선호합니다. PublicAPI만 테스트한다고 해서 테스트 커버리지가 떨어지는 게 아니라 PrivateAPI가 간접적으로 실행되고 있다는 의미입니다. PublicAPI 테스트 케이스가 성공할 때 실행되지 않는 코드가 있다면 아마도 제거해야 할 죽은 코드일 것입니다. 테스트 코드를 작성하는 연습을 할 때 커버리지 100%를 목표로 달리는 것은 굉장히 좋은 방법입니다. 하지만 ‘코드 베이스에서 가장 중요한 기능’, ‘사용자가 가장 필요한 기능.’, ‘사용자의 목소리에 가장 귀 기울이고 피드백 받아야 하는 기능’만이라도 신뢰도 높은 테스트 코드를 작성해도 훌륭한 소프트웨어 엔지니어링을 수행 중인 팀이라고 생각합니다.