많은 백엔드 개발자들이 TDD 방법론을 사용을 하고 있습니다. 테스트 코드를 구현 함에 있어서 자주 마주치는 상황이 있다고 하면은 어떤게 좋은 테스트 코드인가 일 것입니다. 이러한 좋은 테스트 코드를 찾게 되다 보면은 자주 접하게 되는 것이 함수에 대해서 Mock으로 대체 할 것인가 아닌가에 대한 여부라고 생각합니다. 이에 대한 방법으로 생겨난 접근법이 Mockist 입니다. 반대로 함수 그대로 사용하면서 실제로 테스트 해보는 것을 Classicist 라고 합니다. 그렇다면 이러한 접근법들이 어떠한 내용 내포하고 있는지 톺아보도록 하겠습니다.
Mockist
"Mockist"는 소프트웨어 테스팅 접근 방식 중 하나로, 특히 TDD(Test-Driven Development)와 관련이 깊습니다. 이 접근 방식은 모킹(mocking)이라는 개념을 중요하게 다루며, 코드의 다른 부분을 모킹하여 테스트 케이스를 작성하고 검증하는 방식을 강조합니다.
Mockist 접근 방식의 주요 특징은 다음과 같습니다
- 모킹(Mocking): 모킹은 실제 의존성을 가진 코드 대신 가짜 객체나 동작을 사용하여 테스트를 수행하는 것을 의미합니다. 이렇게 함으로써 코드의 특정 부분만을 테스트할 수 있습니다. 모킹을 사용하면 테스트를 더 격리시키고 예상한 동작이 발생하는지 확인할 수 있습니다.
- Interface-Focused Testing (인터페이스 중심 테스팅): Mockist 접근 방식에서는 인터페이스에 집중하여 테스트를 작성합니다. 클래스나 모듈의 내부 구현보다는 외부와의 인터페이스나 상호 작용에 초점을 맞춥니다.
- 작은 단위 테스트 (Small Unit Tests): Mockist 방식은 작은 단위의 코드 조각을 격리된 환경에서 테스트하는 것을 강조합니다. 이러한 단위 테스트는 코드의 격리된 부분을 빠르게 검증하는 데 도움을 줍니다.
- Stub, Mock, Spy: Mockist 접근 방식은 주로 스텁(stub), 모의 객체(mock object), 스파이(spy)와 같은 테스트 더미(dummy)를 사용합니다. 스텁은 실제 동작 대신 예상 결과를 반환하거나 특정 동작을 수행합니다. 모의 객체는 특정 상호 작용을 감시하고 검증하는 데 사용됩니다. 스파이는 함수의 호출 정보를 추적하고 기록하는 데 사용됩니다.
- TDD에 적합: Mockist 접근 방식은 Test-Driven Development(TDD)에 자주 사용됩니다. 테스트를 먼저 작성하고, 그에 따라 코드를 개발하는 방식을 TDD라고 하는데, 이때 Mockist 접근 방식은 코드의 의존성을 해결하면서 빠르게 테스트를 작성할 수 있도록 도와줍니다.
Mockist 접근 방식은 코드의 다양한 부분을 격리시키고 테스트하기 위해 모의 객체 및 스텁을 사용하여 코드를 작성하는 방식입니다. 이 방식은 코드의 품질을 유지하고 버그를 최소화하기 위해 효과적일 수 있습니다.
이러한 Mockist 접근법을 통한 개발을 하면은 블록을 쌓듯이 개발을 차근차근 진행한다는 느낌을 받게 됩니다. 하나의 서비스 로직을 구현하고 있다고 생각해봅시다. 그 로직에는 하나의 Method를 사용하는 것이 아닌 여러개의 Method를 사용하여 해당 로직을 구현하게 될 것입니다.
그렇다면 서비스 로직을 통째로 구현하기 전에 하는 것이 무엇일까요? 바로 Method 작성일 것입니다. 통합 되기전에 여러 개로 나뉘어진 Method들이 먼저 작성하게 되는데 이러한 Method들이 제대로 작동하는지 검증하기 위해서는 테스트코드를 작성하여 검증을 하여야 될 것입니다.
이렇게 작은 메서드 하나 하나 마다 테스트 코드를 작성하는 것을 단위테스트(유닛테스트) 라고 지칭하고 있습니다. 하나의 서비스 로직을 단위로 나위어서 테스트 한다고 하여 붙여진 이름인 것입니다.
근데 Mockist 접근 개발법에 대한 가장 중요 시 되는 포인트가 있습니다. 그것은 바로 Method Test 들은 독립성을 유지 시켜야 한다라는 것입니다. 독립성이 유지 되어야 한다는 말은 무슨 뜻일까요? 이미 여러 번 테스트 코드를 작성해보신 분들이라면 바로 감이 오실 듯 합니다. 바로 자신 외에 다른 것에 종속성이 없어야 한다라는 것입니다.
예를 들어 하나의 Method를 검증하는 테스트 코드를 작성 하는 과정에서 다른 라이브러리를 활용하여 테스트 하게 되는 상황이라고 보겠습니다. 아마 초기 테스트 코드를 작성 하는 개발 환경에서는 무리 없이 테스트를 통과하게 될 것입니다. 하지만 테스트 환경이 아닌 실제 프로덕션 되는 환경에서는 어떻게 될까요? 분명 기존 Method는 변경 된 사항이 없는데 실패라고 뜰 것입니다.
이러한 문제점을 좀 더 해결하기 위해 독립성에 집중 하는 것이 Mockist 입니다. 이렇게 독립적인 테스트를 통해서 하나씩 쌓아 올리 듯이 개발을 하게 되면 각 Layer에 존재하는 코드들이 제대로 작동하는지 검증을 할 수 있게 됩니다.
Mockist가 가지는 다른 장점으로는 빠른 테스트속도 라는 것입니다. 실제로 외부로부터 의존을 하지 않기 때문에 어딘가에 연결하거나 하는 작업을 할 필요가 없다라는 것입니다.
그리고 Mock이라는 대체 함수로 변경하여 테스트를 하기 때문에 어려운 난이도의 테스트들도 Mock으로 대체하여 처리하면 좀 더 쉽게 테스트 코드를 작성을 할 수 있게 됩니다.
하지만 이러한 Mockist에게도 치명적인 단점이 존재하고 있습니다. 그것은 바로 신뢰성에 대한 이슈입니다. 하나의 메소드를 검증하는 방식을 채택하기 위해 독립성을 강화하였지만 이러한 독립성 때문에 다른 라이브러리들은 Mocking (Mock으로 대체하다) 하여야 합니다. 이렇게 될 경우 실제로 메소드가 작동을 하였을 때와 같은 결과가 나온다고 확신할 수 있는 부분인가에 대한 불신이 따라오게 됩니다.
Classicist
"Classicist"는 소프트웨어 테스팅 접근 방식 중 하나로, 코드의 완결성과 내부 구현에 주목하며 테스트 케이스를 작성하는 방식을 의미합니다. 이 접근 방식은 테스트 중심 개발(Test-Centric Development)이나 행위 주도 개발(Behavior-Driven Development, BDD)과도 관련이 있습니다.
Classicist 접근 방식의 주요 특징은 다음과 같습니다
- 실제 동작 검증: Classicist 방식은 코드의 실제 동작을 검증하는 데 중점을 둡니다. 코드의 내부 구현보다는 코드가 어떻게 동작해야 하는지를 확인하는 데 주력합니다.
- 통합 테스트와 단위 테스트: Classicist 방식은 통합 테스트와 단위 테스트 모두를 사용하여 코드의 품질을 보장합니다. 통합 테스트는 다양한 컴포넌트 및 모듈 간의 상호 작용을 검증하며, 단위 테스트는 코드의 작은 단위를 개별적으로 테스트합니다.
- TDD와 결합: Classicist 방식은 Test-Driven Development(TDD)와 자주 결합됩니다. 테스트를 먼저 작성하고, 그에 따라 코드를 개발하는 방식을 TDD라고 하는데, Classicist 방식은 코드를 작성하면서 테스트가 동작하지 않을 때까지 진행하여 코드의 완결성과 동작을 보장합니다.
- 인터페이스보다 구현 중심: Classicist 방식에서는 코드의 내부 구현보다는 코드의 인터페이스와 외부 동작에 더 집중합니다. 이로써 코드의 사용 방법과 예상 동작에 초점을 맞춥니다.
- Real Objects 사용: Classicist 방식은 가능한 실제 객체를 사용하여 테스트를 수행하며, 스텁이나 모의 객체보다 실제 객체의 동작을 이용합니다.
Classicist 접근 방식은 코드의 내부 동작과 완결성을 중요시하며, 테스트를 통해 코드가 예상한 대로 동작하는지를 검증하는 데 초점을 둡니다. 코드의 신뢰성과 품질을 향상시키는 데 도움을 줄 수 있는 방법 중 하나입니다.
Classicist의 경우는 실제로 사용되는 라이브러리를 활용하자라는 개념으로 보시면 되겠습니다. 이러한 실제 사용을 통해 서비스에서 나타날 수 있는 치명적인 문제점이나 숨어 있을 버그들을 발견하는데에 매우 유리합니다.
또 다른 장점으로는 기존에 작성한 코드를 그대로 사용하는 경우가 많아서 테스트 코드를 작성하는데 큰 어려움이 없이 진행 할 수 있다라는 것입니다. 기존에 작성한 코드로 상황별로 처리하기 때문에 새로운 접근법이 생기는데 그것이 바로 BDD 입니다.
Classicist가 가질 수 있는 단점으로 단위테스트에 대한 개념 혼용이 발생 한다라는 것입니다. 단위 테스트라 하면 말 그대로 하나의 Method를 테스트 하는 코드인데 Classicist는 하나의 Layer에서만 검증을 수행하는 것이 아닌 연관된 모든 Method를 사용해야 하는 부분이기 때문에 해당 단위만 검증이 되었다고 하기에는 어렵다고 볼 수 있겠습니다.
그래서 인지 Classicist는 단위테스트 보다는 통합테스트에 관련된 내용으로 많이 다루어 지고 있습니다.
추가적으로 실제 다른 라이브러리에 연결하고 끊는 작업을 수행하기 때문에 테스트시간이 길다라는 것입니다. 몇 초 걸리지 않아서 괜찮은 부분이라고 볼 수 있지만 테스트 코드를 작성하는 것이 개발자의 주 업무이기 때문에 한번 구동 했을 때 5초가 걸린다고 하면 매 검증마다 대기하는 시간이 발생한다는 문제가 있습니다. 이것은 실제 많은 테스트코드를 작성해보면 느끼게 되는 단점이 될 수 있을 듯 합니다.
'CS 지식 > 방법론' 카테고리의 다른 글
DDD(Domain Driven Dsign) (0) | 2023.07.27 |
---|---|
Agile (0) | 2023.07.12 |