본문 바로가기

개발

정말로 단위 테스트를 통합 테스트보다 많이 작성해야 할까?

반응형

테스트 피라미드

통합 테스트를 줄이고, 단위 테스트를 많이 작성해야 한다는 말 들어보셨나요? 이러한 주장을 하면 보통 리팩터링의 저자 마틴 파울러의 테스트 피라미드를 예시로 사용합니다.

마틴파울러의 테스트 피라미드

해당 그림을 보면 UI 테스트나 통합 테스트는 지양해야 할 대상처럼 보이고, 테스트 더블(e.g. 모킹)을 활용한 단위 테스트를 늘려야만 할 것 같습니다.

테스트 피라미드에 대한 논쟁

하지만 얼마 전 우연히 마틴 파울러의‘테스트 피라미드에 반박하는 트위터 게시글을 보게 되었습니다.

“마틴 파울러의 테스트 피라미드는 시대가 지난 개념이다. 통합 테스트를 유닛 테스트보다 많이 작성하는 게 새로운 통념이다. 프론트엔드에서는 트로피 모양 테스트, 백엔드에서는 벌집 모양 테스트 등이 이를 뒷밤침한다.”

트위터에서 언급된 사람들 같은 경우도 모두 상당한 실력자로 보이며, 해당 트위터에 반응하여 마틴 파울러도 블로그(On the Diverse And Fantastical Shapes of Testing)를 작성하였습니다.

마틴 파울러의 입장

블로그의 내용을 요약하면 다음과 같습니다. (요약에서 ‘나’라는 말은 ‘마틴 파울러’를 지칭합니다.)

  1. 통합 테스트라는 단어는 혼동의 의지가 많은 단어이다. 나에게 있어 통합 테스트는 여러 사람(팀이) 작성한 코드들을 모두 통합하여 테스트해야 하는 상황 (즉, 코드 작성자와 테스트 코드 작성자가 다른 상황)에서 사용하는 단어이다. 유닛 테스트는 개발자가 본인의 개발과정에서 직접 작성하는 테스트를 의미한다. (TDD의 저자 켄트 백 역시 이 의미로 유닛 테스트를 지칭한다.)
  2. 사람들이 작성자들이 통합 테스트라고 부르는 것을 보면 내가 sociable unittest라고 부르는 것과 흡사하다. sociable test란 테스트 더블(e.g mock) 등을 사용하지 않고, 상위 모듈을 통해 하위 모듈을 간접적으로 테스트하는 것을 의미한다. 그리고 사람들이 단위 테스트라고 부르는 것을 나는 solitary unittest라고 정의한다.
  3. 아래 트위터가 나의 의견을 잘 대변해준다.

“사람들은 어떤 종류의 테스트를 어떤 비중으로 써야 하는지 논쟁하기를 좋아하는데, 그것은 본질이 아니다. 거의 어떠한 팀도 명확한 경계를 설정하고, 빠르고 안정적으로 실행 가능하고, 실용적인 이유로만 실패하는 테스트를 작성하지 않는다. 우리가 집중해야 할 것은 그런 것들이다.”

즉, 마틴 파울러는 sociable unittest(통합 테스트) 보다 solitary unittest(단위 테스트)를 많이 작성해야 한다고 주장한 적이 없습니다. 오히려 마틴 파울러는 sociable unittest관점에서 테스트를 먼저 접근합니다. 이런 생각은 마틴 파울러의 다른 포스트 들에서도 엿볼 수 있습니다.

“mockist는 solitary unittest를 해야 한다고 주장하고, classicsts는 sociable test를 선호한다. 나는 두 스타일의 테스터들을 모두 알고 있으며 그들을 모두 존중한다. (개인적으로 나는 classic style을 사용해 왔다.) - [UnitTest]

“나는 외부 리소스를 위해 테스트 더블 (mock, stub 등)을 사용하는 것을 절대적인 규칙이라고 생각하지 않는다. 외부 리소스에 접근하는 것이 충분히 안정적이고 빠르다면, 유닛 테스트에서 사용하지 않을 이유가 없다.”- [UnitTest]

“나의 고수준 테스트가 빠르고, 신뢰할 수 있고, 변경하기 쉽다면 저수준 테스트가 필요하지 않다." - [TestPyramid]

테스트 코드의 본질

마틴 파울러가 제시한 트위터의 의견처럼 ‘각 테스트를 얼마만큼의 비중으로 작성해야 하는 가는 테스트 코드의 본질적인 측면을 벗어나 있다고 생각합니다.

테스트 코드의 본질을 가장 잘 설명해주는 말은 '켄트 백'이 언급한 “불안함을 지루함으로 바꾸는 과정”이라고 할 수 있습니다. 이를 바꿔 말하면 지루함을 대가로 요구사항을 올바르게 구현하고 있다는 자신감을 얻는 것입니다. 리팩터링을 할 때에도 내가 테스트한 요구사항이 깨지지 않을 것이라는 자신감을 가질 수 있습니다.

따라서 중요한 것은 ‘어떠한 테스트를 작성해야 코드 작성의 불안감을 없애고 자신감을 얻을 수 있느냐’입니다. (다만 이 불안함이 막연한 불안함은 아닌지 되짚어볼 필요는 있습니다.)

마무리

저는 이번 포스트를 통해서 ‘테스트 피라미드’ 구조가 잘못되었다고 주장하고 싶다거나, ‘sociable unittest(통합 테스트)’를 ‘solitary unittest’보다 많이 작성해야 한다고 주장하고 싶은 것은 아닙니다. 팀의 구성과 크기, 설계의 성숙도, 코드의 복잡도, 테스트 코드의 피드백 속도 등에 따라서 얼마든지 이 비중은 달라질 수 있다고 생각합니다.

막연히 테스트 코드의 비중을 테스트 피라미드와 같이 정해두고 접근하기보다는 우리가 작성하는 테스트 코드를 통해서 얻을 수 있는 효용과, 잃게 되는 비용에 초점을 맞춰야 합니다. 이 판단에 따라서 테스트 코드의 비중은 얼마든지 유동적으로 조정될 수 있습니다.

제가 전달한 내용 중에 사실이 다른 부분이 있거나 피드백이 있으시면 댓글로 남겨주시면 감사하겠습니다. 긴 글 읽어주셔서 감사합니다.

참고 자료

[1]. 마틴 파울러 - TestPyramid
[2]. 마틴 파울러 - UnitTest
[3]. 마틴 파울러 - On the Diverse And Fantastical Shapes of Testing

더 읽어볼 만한 자료

[1]. 강남언니 CTO 이규원 님의 ‘정말로 테스트 대역이 필요한가’
[2]. Kent C. Dodds의 발표 'Write tests, not too many, mostly Integration'
[3]. Twitter Thread

반응형