인프런 "모든 개발자의 실무를 위한 필수 기본기 클래스" 강의를 듣고 정리한 내용 + 따로 검색하여 공부한 내용입니다.
테스트 기본 이해하기
💡 테스트, 테스트 코드란 무엇인가?
- 소프트웨어를 테스트하는 작업이다. 숨겨진 버그는 없는지, 여러 명이 동시에 이용할 때에도 잘 견디는지 등 문제를 점검하는 일이다.
- 제품 혹은 서비스 품질을 확인하는 용도
- SW의 버그 찾는 용도
- 제품(함수, 특정 기능, UI, 성능, API 스펙)이 예상하는 대로 동작하는지 확인 및 검증을 하는 것이다.
- 보통 우리가 local 환경에서 테스트를 하는데, 백엔드는 postman을 이용하여 api 테스트를 하고, 프론트엔드는 로컬에서 브라우저에 접속하여 테스트를 하게 된다. 이 경우, 혼자서 테스트한다는 단점이 있다. 또한 사람이 하다 보니 일관성이 없고 놓치는 부분이 있기 마련이다.
- 테스트 코드를 잘 작성해 둔다면, 버그에 견고한 코드를 작성할 수 있다. 여러 명이 있는 팀에서 SW의 버그를 줄이고 안전하게 코드를 개발하기 위한 핵심 장치라고 볼 수 있다.
테스트 종류
목표와 플랫폼, 환경에 따라 다양한 테스트가 존재한다. 위 그림처럼 테스트 피라미드라고 부른다.
유닛 테스트 (Unit Test)
- 가장 작은 단위의 테스트로, 독립적인 하나의 컴포넌트, 함수, 모듈, 클래스 등 하나의 단위를 테스트 하는 것이다.
통합 테스트 (Integration Test)
- 유닛 테스트보다 더 여러 요소를 통합한 테스트
- 의존성 있는 객체들의 정상 작동 여부까지 포함하는 테스트로, 통합했을 때 모듈들과 클래스들끼리 서로 상호작용이 잘 되는지 테스트하는 것이다.
- 일반적으로 통합테스트는 외부 의존성을 포함하고 있는 경우가 많다. 하지만 테스트 환경은 운영 환경과 분리되어야 한다. 따라서 테스트에서 재현할 수 없는 외부 의존성 (운영 DB, 운영 API 서버 등)은 테스트 더블을 사용한다.
E2E 테스트 (E2E Test)
-
End to End의 약자로, 끝에서 끝, 즉 클라이언트 입장에서 테스트하는 것이다. UI 테스트, 사용자 테스트라고 하기도 한다.
-
E2E 테스트를 하게 되면 통합 테스트나 유닛 테스트도 유기적으로 하게 된다.
-
E2E 테스트는 서버 내부 동작은 전혀 관여하지 않은 채, 철저히 엔드 유저 입장에서 서버를 이용하는 시나리오대로 테스트해보는 것이다.
- E2E테스트 도구로 Cypress, TestCafe, Selenium Webdriver 등이 있다.
-
Docker Compose : E2E 테스트 환경 만들 때 격리된 테스트 환경을 편하게 구축해 줄 수 있는 것
⬜ 비용적인 측면
Unit Test -> E2E Test로 올라갈수록 비용이 비싸진다. 테스트 코드 작성도 유닛 테스트가 쉬우며 실행, 수행, 자동화 시에도 비용이 거의 들지 않는다. E2E Test (사용자 테스트) 시에는 그 환경과 플랫폼을 제공하는 비용이 많이 든다.
개발적인 효율성 측면에서도 유닛테스트가 훨씬 저렴하다. 개발 시 유닛 테스트를 작성하면 오류나 버그를 즉각적으로 캐치하여 해결 가능하지만, 모듈이나 크래스가 다 완성된 다음 서로 상호작용하거나 사용자가 사용하는 상위 레벨만을 테스트해서 문제가 발생한다면, 버그를 찾고 문제를 추적하는데 더 오랜 시간이 소요된다.
⬜ 속도적인 측면
아무래도 단위 테스트가 가볍기 때문에 Unit Test가 빠르고 위로 갈수록 느려진다.
피라미드 테스트 외에도 상황과 목적에 따라 아래와 같은 다양한 테스트가 존재한다.
- Contract Test
- A/B Test
- Stress Test
🙋♀️잠깐, 테스트 코드가 필요한 이유가 뭘까?!
- 테스트 코드는 프로젝트 코드에 대한 가장 정확한 문서가 된다. 문서화의 효과를 얻을 수 있다.
- 제품/기능에 대해 자신감을 얻을 수 있다. 기능이 정상 동작하는지 확인이 가능하다.
- 요구사항을 만족할 확률이 높아지며 이슈에 대해 예측할 수 있다.
- 유지보수가 쉬워지고, 코드 품질도 향상된다. 코드간 의존성을 낮추어 독립적이고 재사용 가능한 코드를 작성할 수 있다.
- 리팩토링과 지속적인 개발을 위해 필수적이다.
- 무엇보다도 시간을 절약할 수 있다. 미리미리 버그를 찾고 개선할 수 있기 때문에 시간을 허비하지 않아도 된다.
의존성을 대체하는 테스트 더블
💡 테스트 더블이란?
외부 의존성을 끊어내어 테스트할 수 있게 하는 것이다. 의존성 객체들을 대체함으로써 테스트를 좀 더 원활하게 진행하기 위한 객체라고 보면 된다.
참고(https://martinfowler.com/bliki/TestDouble.html)
테스트 더블의 종류
-
dummy
-
실제 내부 동작은 구현하지 않은 채, 객체의 인터페이스만 구현한 테스트 더블 객체
-
간단하게 테스트할 때 사용
-
-
stub
-
dummy 테스트 더블 객체에서 테스트에 필요한 최소한의 구현만 해둔 테스트 더블 객체
-
테스트에서 호출될 요청에 대해 미리 준비해둔 결과만을 반환함
-
-
spy
-
stub에서 테스트에 필요한 정보를 기록해두는 테스트 더블 객체
-
stub의 역할을 포함
-
실제로 내부가 잘 동작했는지 등을 별도 인스턴스 변수로 기록해둠
-
-
fake
-
동작의 구현은 갖추고 있지만, 테스트에서만 사용할 수 있는 테스트 더블 객체
-
대체할 객체가 복잡한 내부 로직이나 외부 의존성이 있을 때 사용
-
-
mock
-
mocking 한다 = 외부 의존성을 끊어준다.
-
테스트에 필요한 인터페이스와 반환 값을 제공해주는 객체
-
해당 메서드가 제대로 호출되었는지를 확인하는 행위 검증의 기능을 가짐
-
다른 테스트 더블과 다르게 보통은 객체를 직접 정의하지 않고, 보통 Mock 객체로 반환 값을 미리 지정해둔다.
- 대부분의 테스트 프레임워크는 Mocking을 정밀하게 할 수 있도록 지원해준다.
-
TDD 기본 개념
💡 TDD란 무엇일까?
TDD 과정
-
요구사항을 테스트코드로 먼저 작성하기
-
테스트 대상 구현하기
- 테스트 대상 SRP 원칙을 지키도록 리팩토링하기
- 위 TDD 개발 과정을 레드-그린-리팩토링 이라고 한다.
- 실패 → 성공 → 리팩토링의 순환을 가지는 “레드-그린-리팩토링“ 순서로 개발하는 것이다.
- 실패 → 성공 → 리팩토링의 순환을 가지는 “레드-그린-리팩토링“ 순서로 개발하는 것이다.
-
일단 먼저 실패하는 테스트 코드를 작성한다. 아직 구현체가 작성되지 않았으므로 테스트는 실패한다.
-
테스트가 통과될 정도의 간단한 구현 코드를 작성한다. 구현이 완료되어 테스트는 성공한다.
-
기존 코드를 필요에 따라 리팩토링 한다.
이 과정을 무한 반복하면서 개발한다.
TDD 장단점
장점
-
TDD를 하면 꼼꼼한 테스트를 통해 코드 품질과 테스트 코드의 문서화 품질이 올라간다.
-
기대하는 것을 테스트 코드로 미리 명확하게 정의할 수 있다. 그래서 사용하기 좋은 코드를 작성할 수 있게 된다.
-
테스트를 훨씬 꼼꼼하게 작성하게 된다.
- 테스트코드를 먼저 작성하기 때문에 요구사항 분석 및 철저한 이해를 하게 된다. 이후에 어떤 식으로 코드를 짤 것인지 설계를 할 수 있다. 그래서 코드 개발하기 앞서 모든 요구사항(목표)에 대해 점검할 수 있으며, 구현할 때 사용자 입장에서 코드를 작성할 수 있다.
-
테스트 코드가 깔끔한 코드 사용 문서가 된다.
- TDD에서 테스트 코드는 테스트할 대상의 구현을 모른 채 작성되기 때문에, 철저히 사용자 중심적으로 작성된다. 따라서 테스트 코드는 코드를 사용하기 위해 필요한 최소한의 내용만 담게 된다.
단점
- 테스트가 가능하도록 코드를 설계하는 것은 어렵다.
- 추상화, 의존성 주입 등을 잘 활용해야 테스트 가능하도록 코드 설계가 가능하다.
-
익숙하지 않은 채 TDD를 진행하면 개발 프로세스가 느려질 수 있다.
🙋♀️잠깐, TDD는 꼭 해야 할까?!
- TDD를 하는 경우는 아래와 같다.
- 요구사항이 명확한 경우
- 비즈니스 로직인 경우
- 협업 시 명세서(문서) 역할을 하기 위해
- 설계에 대한 고민이 필요한 경우
- 대부분의 사람들이 UI 컴포넌트를 작성할 때는 TDD를 하진 않는다.
- TDD를 할 때도 있고, 하지 않을 때도 있지만, 명백한 사실은 사용자에게 배포하는 코드라면 해당 기능에 대한 테스트 코드는 반드시 작성해야 한다. 코드 리뷰를 요청하기 전 main repository에 코드를 머지하기 전에, 코드와 테스트 코드를 포함해서 머지해야 하며, 좋은 문서화를 위해서라도 테스트 코드는 꼭 작성하는 것이 좋다.
참고
https://ui.toast.com/fe-guide/ko_TEST
https://tech.kakao.com/2021/11/08/test-code/
'Devlog > CS' 카테고리의 다른 글
객체 지향 프로그래밍이란? (0) | 2022.08.07 |
---|---|
객체지향 5대 원칙 - SOLID 원칙 (0) | 2022.08.06 |
쿠키와 세션, 인증 이해하기 (0) | 2022.06.24 |
OSI 7계층과 TCP/IP 4계층 모델 (0) | 2022.06.22 |
프로그램 운영 기본 지식 (0) | 2022.06.21 |