목차
* 주의 : 책(폴M 듀발 저 - 지속적인 통합) 내용 중 기억하고 싶은 내용 및 제 생각을 적은 글 입니다. 책이 나온지 오래되어 설명에 나온 기술스택이 현재 사용되지 않는게 많아 기술스택보다는 이론이나 책의 조언들 위주로 작성할 것 같고, 기술스택은 제가 알고있는대로 수정해서 작성합니다. 따라서 책에서 말하고자 하는 바와 다를 수 있습니다.
* 별도로 표기되어 있지 않다면 이미지 출처는 '지속적인 통합 (폴M 듀발 저)' 책 입니다.
CHAPTER 6. 지속적인 테스트
- 선형 시스템의 신뢰도는 각 시스템 컴포넌트의 신뢰도를 곱한 값
- 각각의 신뢰도가 99%인 컴포넌트 100개로 구성된 프로그램이라면 37% 신뢰할 수 있다.
- 신뢰할 만한 소프트웨어를 만들려면 최소한 객체 수준에서 신뢰도를 보장해야 한다.
- 이는 단위 테스트를 통해서만 이뤄낼 수 있다.
- 또한 무언가가 변하면 그때마다, 언제라도 테스트를 실행해야 한다.
테스트 자동화하기
- 지속적인 통합 시스템이 작성된 모든 테스트를 매번 돌리게 되면 빌드는 점점 오래 걸리게 된다.
- 개발자 테스트를 각각의 범주(단위 테스트, 컴포넌트 테스트, 시스템 테스트, 기능 테스트)로 나누면 빠른 테스트를 먼저, 느린 테스트를 나중에 돌리기 좋다.
- 단위 테스트
- 소프트웨어 시스템 내의 작은 요소(대부분 클래스 하나)의 행동을 검증
- 종속적인 객체가 파일 시스템이나 DB같은 외부 개체에 의존하고 가짜 클래스(Mock)을 쓰지 않으면, 그 테스트는 컴포넌트 테스트가 된다.
- 즉, 단위 테스트의 중요한 측면은 DB 같은 외부 의존성에 전혀 기대지 않는다는 점이다.
- 고전파 vs 런던파(mockist)
- 런던파의 경우 A 클래스를 테스트할 때, A가 B 클래스에 의존한다면 B를 Mock으로 대체해야 한다는 쪽이다.
- 즉, 하나의 클래스에 대해 의존성 있는걸 전부 Mocking 해야 한다는게 런던파이다.
- 서로 장단점이 있을 것 같다. 일단 런던파는 리팩토링이 힘들다. (리팩토링 후 Mocking해둔 테스트 코드가 의미 없어짐)
- 컴포넌트 테스트 (하위시스템 테스트)
- 컴포넌트들이 상호작용하여 예상된 총체적 행동을 생산해내는지 검증 (시스템의 일부를 검증)
- DB, 파일 시스템, 네트워크 종점 등과 같은 외부 의존성이 필요할 수도 있음
- 시스템 테스트
- 웹 페이지, 웹 서비스 종점, GUI가 처음부터 끝까지 설계된 대로 작동하는지 검증
- 전체 소프트웨어 시스템을 실행시키고 수행. 즉 서블릿 컨테이너나 관련 DB와 같이 완전히 설치된 시스템이 있어야 함.
- 인수 테스트와 비교해 좀 더 시스템적인 측면(성능, 신뢰성, 보안)
- 기능 테스트 (인수 테스트)
- 어플리케이션의 기능성을 클라이언트의 관점에서 테스트하는 것
- 즉, 테스트 자체가 클라이언트를 흉내 내는 테스트.
- 시스템 테스트와 비교해 좀 더 사용자 측면(요구사항)
- Selenium 같은 프레임워크로 웹페이지 조정해서 테스트 할 수 있다고 함.
시간이 덜 걸리는 테스트부터 실행하기
- 단위 테스트를 가장 자주 실행하고 컴포넌트 테스트, 시스템 테스트, 기능 테스트는 2차 빌드 때 돌리거나 일정 주기마다 돌려도 된다.
- 단위 테스트
- 진정한 단위 테스트라면 실행부터 완료까지 눈깜짝할 사이에 끝나야 한다.
- 누군가 코드를 체크인할 때마다 단위 테스트를 돌려야한다(빌드 커밋).
- 컴포넌트 테스트
- 단위 테스트에 비해 실행 시간이 약간 길다.
- 2차 빌드의 일부로 실행하거나 주기적으로 실행해야 한다.
- 물론 컴포넌트 테스트가 가벼운 프로젝트라면 커밋 빌드 때마다 테스트를 돌려도 된다.
- 시스템 테스트, 기능 테스트(인수 테스트)
- 시스템 테스트나 기능 테스트를 하려면 완전히 설치된 시스템이 필요하고 시간이 가장 많이 걸린다.
- 밤 같이 일하지 않을 때 시스템 테스트를 돌리는 편이 좋다.
결함 검사용 테스트 작성하기
- 테스트와 지속적인 통합은 결함의 빈도를 줄일 수 있지만, 그래도 여전히 결함은 발생할 수 있다. 결험을 만들어낸 건 용서받을 수 있다. 하지만 똑같은 실수는 단 한 번뿐이어야 한다.
- 결험 발생 시 우선 결함을 노출시키는 테스트 케이스를 작성한다. (결함을 똑같이 재현해서 성공시키는 테스트케이스)
- 그리고 결함을 고치면 이제 결함을 재현한 테스트는 실패한다. 그리고 결함을 수정한 코드를 검증하도록 테스트 케이스를 갱신한다.
- 위의 방법을 통해 고친 코드가 올바르게 행동하는걸 진정으로 단언하는 회귀 테스트를 갖출 수 있고, 다시 동일한 문제가 발생하는걸 막을 수 있다.
테스트 케이스 하나에 어썰트(assert) 하나로 제한하기
- 책에선 어썰트가 여럿일 때, 그 중 첫 번째가 실패하면 실패한 그 지점부터 테스트 케이스 전체가 버려지므로 하나로 제한하라고 하는 것 같다.
- junit5 기준으로 assertAll이나 assertSoftly를 사용하면 내부에 포함된 모든 어썰트들을 멈추지 않고 전부 실행한 후 결과를 알려준다.
assertSoftly(
() -> assertNotNull(studyBasic),
() -> assertEquals(StudyBasicStatus.ENDED, studyBasic.getStatus(), () -> "Study 생성시 초기값은 " + StudyBasicStatus.ENDED + " 이여야 함."),
() -> assertTrue(studyBasic.getLimit() > 5, () -> "스터디 참가 인원은 5 이상이어야 함.")
);
- "두 가지 다른 행위를 하나에서 검증하지" 마라 라고 읽으면 될 것 같다.
질문
- 단위 테스트, 컴포넌트 테스트, 시스템 테스트, 기능 테스트 같은 자동화된 테스트들을 여러 범주로 나누었습니까?
- 지속적인 통합 시스템을 조정하여 각 테스트 범주를 각기 다른 빌드 때 돌리고 있습니까?
- 테스트들을 자동화할 수 있습니까? 자동화된 개발자 테스트를 버전 관리 저장소에 커밋해 넣었습니까?
'Study > 지속적인 통합' 카테고리의 다른 글
[지속적인 통합] 8장. 지속적인 배포 (0) | 2023.03.19 |
---|---|
[지속적인 통합] 7장. 지속적인 검사 (0) | 2023.03.19 |
[지속적인 통합] 5장. 지속적인 데이터베이스 통합 (0) | 2023.03.12 |
[지속적인 통합] 4장. 변경될 때마다 소프트웨어를 빌드하기 (0) | 2023.03.08 |
[지속적인 통합] 3장. 지속적인 통합을 이용해 위험 줄이기 (0) | 2023.03.08 |
댓글