일반적으로 테스트는 단위 테스트, 통합 테스트, 엔드투엔드 테스트로 크게 나눠볼 수 있다.
단위 테스트(Unit Test)는 가장 빈번히 사용되는 테스트로 하나의 단위(함수, 컴포넌트)로 테스트 케이스를 작성한다. 단위 테스트는 종속성이나 다른 요소와의 복잡한 상호 작용이 없는 테스트이다. 이를 위해 연관된 부분에 대해서는 가짜 객체인 Mock을 이용하기도 한다. 단위 테스트는 테스트 비용이 가장 저렴하고 테스팅 속도가 매우 빠르다.
통합 테스트(Integration Test)는 다른 요소와의 종속성을 처리하므로 좀 더 복잡도가 높아진다. 쉽게 생각하면 기존에 Mock으로 테스트하던 부분이 실제 구현부분으로 대체되어 여러 모듈간 상호 작용을 테스트 한다고 보면 쉽다.
마지막 엔드투엔드 테스트(E2E, End to End Test)는 사용자와 앱의 상호 작용에 대한 테스트이다. 예를 들어 웹의 경우 실제 browser를 이용해서 UI 테스트를 진행해서 전체 앱을 테스팅하며 인수 테스트 형태를 띈다.
vue에서의 테스트
vue에서는 프로젝트 생성 시 unit test와 End-to-End 테스트를 위한 옵션을 설정할 수 있다.
vite의 unit test 프레임워크는 vitest가 사용된다. 앞으로의 포스팅 과정에서는 vitest를 이용한 단위 테스트를 진행해볼 예정이다.
End-To-End 테스트를 위해서는 가장 대표적인 프레임워크인 Cypress 등을 지원하는데 E2E는 간단히 컨셉을 이해할 수 있는 동영상을 참고하기로 하자.
가끔 하나의 test에서 여러개의 expect를 처리할 때가 있는데 이때 expect.soft라는 함수도 제공된다. expect는 테스트 과정에서 하나라도 오류가 나면 바로 테스트를 종료하고 이후의 expect는 고려하지 않는다. 반면 expect.soft는 이후에 나온 테스트도 계속 진행하게 된다.
test('expect.soft test 1', () => {
expect.soft(1 + 1).toBe(3) // assertion은 실패했으나 다음 expect 진행
expect.soft(1 + 2).toBe(4) // 이 assertion을 체크함
})
test('expect.soft test 2', () => {
expect(2 + 2).toBe(3) // assertion 실패 후 test 자체가 종료됨
expect.soft(2 + 2).toBe(4) // 이 assertion을 체크하지 않음
})
테스트 라이프 사이클 관리
테스트 별로 공통적으로 처리할 내용이 있다면 beforeEach, afterEach, beforeAll, afterAll 함수를 이용할 수 있다.
beforeEach, afterEach는 각각 매 test 호출되기 전/후에 필요한 전처리, 후처리를 작성할 수 있다. beforeAll, afterAll은 모든 테스트의 전/후에 필요한 전/후 처리를 작성한다.
let i=0;
beforeEach(async ()=>console.log(`매 테스트 이전 - ${i++}`))
afterEach(async ()=> console.log(`매 테스트 이후 - ${i++}`))
beforeAll(async ()=>console.log(`모든 테스트 이전 한번 - ${i++}`))
afterAll(async ()=> console.log(`모든 테스트 이후 한번 - ${i++}`))
위 lifecycle callback은 파일에 선언된 모든 테스트에 영향을 끼치게 된다. 만약 describe 내부에 선언하는 경우는 해당 describe에만 영향을 끼친다.
위에서는 callback을 모두 async 형태로 만들었지만 꼭 그럴 필요는 없다. 비동기 작업이 필요할 때만 async 로 처리해주면 된다.