소프트웨어 테스팅
- 주요 이해관계자들에게 시험 대상 제품 또는 서비스 품질에 관한 정보를 제공하는 조사 과정
- 프로그램이나 응용 프로그램을 실행하여 소프트웨어 버그를 찾는 절차를 포함하나 이에 국한되지는 않는다.
- 테스팅 레벨
- 단위 테스팅 (unit testing)
- 통합 테스팅 (Integration testing)
- 시스템 테스팅 (System testing)
- 인수 테스팅 (Accentance testing)
- 단위 > 통합 > 시스템 > 인수 로 갈수록 테스팅 횟수가 적어짐
단위테스트
- 단위테스트는 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차
- 각 모듈의 개발을 완료한 후 개발자가 명세서의 내용대로 정확히 구현하였는지를 테스트함
- 상태검증 vs 행위검증
- 상태검증 : 메서드가 수행된 후 SUT나 협력 객체의 상태를 살펴봄으로써 올바른 동작을 했는지 판단
- 행위검증 : 객체의 특정 메소드가 호출되었는지 등의 행위를 검사해 올바르게 동작하는지 판단
- 테스트 더블
- 의존 구성요소를 사용할 수 없을 때 테스트 대상 코드와 상호작용 하는 객체
- 자동화된 테스트를 작성할 때, 여러 객체들이 의존성을 갖는 경우 테스트 하기 까다로움
- → 테스트 더블은 테스트하고자 하는 대상만 독립적으로 테스트 할 수 있도록 구현한 실제 객체보다 단순한 객체
- 종류
- Dummy
- 인스턴스화 된 객체가 필요하지만 기능은 필요하지 않은 경우에 사용
- stub
- 호출시 미리 준비된 답변으로 응답하는 객체
- 테스트시에 프로그램된 것 외에는 응답하지 않음
- mock
- 호출에 대한 기대를 명세하고 내용에 따라 동작하도록 프로그래밍 된 객체
통합테스트
- 단위테스트 보다 더 큰 동작을 달성하기 위해 여러 모듈을 모아 이들이 의도대로 협력하는지 확인하는 테스트
- 외부 라이브러리 까지 묶어 검증할 때 사용
JUnit
- 자바에서 단위 테스트를 수행할 수 있도록 하는 라이브러리
- 기능
- 매 단위 테스트마다 테스트 글래스의 인스턴스가 생성되어 독립적인 테스트가 가능하게 함
- Annotation을 제공하여 테스트 라이프 사이클을 관리하게 함
- assert로 테스트 케이스의 수행 결과를 판별 → assertEquals
- 구조
- JUnit platform : JVM 상에 테스팅 프레임워크를 런칭하기 위한 근간을 제공함, 테스트를 발견하고 테스트 계획을 생성하는 TestEngine 인터페이스를 가짐. TestEngine은 추상체
- JUnit Jupiter : TestEngine의 실제 구현체 중 하나로 jupiter-api를 사용해서 작성한 테스트 코드를 발견하고 실행.
- JUnit Vintage : JUnit 4 버전으로 작성한 테스트 코드를 실행할 때는 vintage-engine 모듈을 사용함
- Annotation
- @Test : 해당 메소드가 테스트 메소드임을 지정함
- @BeforeAll : 테스트 메소드들이 실행되기 전 실행
- @AfterAll : 테스트 메소드들이 실행된 후 실행
-
- Assert 메소드를 사용하여 테스트 진행
https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Assertions.html
- hamcrest
- JUnit에서 사용되는 Matcher 라이브러리
- Matcher : match operation을 수행하는 객체
- assertThat문을 주로 사용함
Mockito
- 단위 테스트를 위해 가짜 객체인 Mock을 생성해주는 프레임워크
- Mock은 진짜 객체와 비슷하게 동작하지만 개발자가 그 객체의 행동을 관리한다
- 사용
- when : Mock 객체에 특정 조건을 지정
Voucher voucher = mock(Voucher.class); // Voucher 클래스의 mock 객체
when(voucher.getID()).thenReturn("1234") // getID 메소드가 호출되면 1234 리턴
- verify : 해당 메소드가 호출되었는지를 확인
verify(voucher).getId(); // voucher의 getID 메소드가 호출 되었는지 확인
- inOrder : 메소드가 순서대로 호출되었는지 확인
inOrder.verify(voucherServiceMock).getVoucher(fixedAmountVoucher.getVoucherId());
inOrder.verify(orderRepositoryMock).insert(order);
inOrder.verify(voucherServiceMock).useVoucher(fixedAmountVoucher);
// 세 메소드가 순서대로 호출되지 않으면 테스트가 통과되지 않음
통합테스트
- 스프링에서 JUnit을 사용하여 통합 테스트를 진행
- @SpringJUnitConfig
- 아래 두 annotation으로 이루어져있다.
- @ExtendsWith : extension을 등록하는 어노테이션
- @ContextConfiguration : 통합 테스트시 application context를 로드하고 configure하는 방식을 정의하는 메타데이터를 정의함 → spring context 로드
@Configuration
@ComponentScan(basePackages = {"com.example.skbak.order", "com.example.skbak.voucher"})
static class Config { // app configuration
}
@Autowired
ApplicationContext context; // config 클래스에 정의된 대로 context를 생성하고 주입받음