테스트 란 ?
애플리케이션이 요구사항에 맞게 잘 작동 하는지 검증하는 작업
테스트가 필요한 이유
- 매번 새로운 기능을 추가하거나, 수정 작업을 할 때마다 해당 기능과 영향을 받는 또 다른 기능들이 어떻게 동작 하는지 실행 결과를 확인하는 작업이 필요하다.
- 그렇기 때문에 반복적으로 이 기능이 잘 작동 하는지 개별로 사람이 확인하는 작업을 거쳐야하며, 이것은 매우 번거롭지만 사용하는 제품의 신뢰도와 안정성을 위해서 필요로 하는 작업이다.
- 무조건 적용하기 보다는 테스트를 작성하는 비용과 효용을 따져서 상황에 맞게 선택하는 것이 바람직하다.
테스트의 종류
종류는 많지만 현재 가장 많이 사용 되고 있는 테스트는 크게 아래 3개로 추려진다.
- 단위 테스트 : 모듈(함수, 클래스) 단위의 테스트로 기능이 실패했을 때의 문제 파악이 빠르고, 작성하는 데 비용이 적다.
- 통합 테스트 : 단위 테스트보다 조금더 큰 단위의 테스트로 개별 모듈 간의 상호 작용을 테스트할 수 있지만, 그만큼 속도가 떨어지고 작성하는데 비용이 든다.
- E2E(End to End) 테스트 : 실제 사용자가 사용하는 것과 같은 조건에서 전체 시스템을 테스트하는 방법으로 단위 테스트나 통합 테스트보다 작성하기 어렵고 실행 속도도 느리다. 다만 API 서버, DB 등 외부 서비스를 모두 사용하여 통합된 시스템을 테스트해 볼 수 있다.
좋은 테스트란 ?
- 속도가 빠른 테스트 ( 느리면 테스트 실행하기에 부담 / 빠른 피드백은 개발 속도를 향상 시킴 )
- 독립적인 테스트를 수행할 수 있는 테스트 ( 최소한의 단위로 문제가 발생한 원인을 쉽게 알 수 있도록 )
- 테스트 검사 결과가 안정인 테스트 ( 실행할 때 마다 동일한 결과가 나오며, 외부 요인에 간섭 받으면 안됨 )
- 어떤 테스트를 수행하기 위한 것인지 의도가 명확한 테스트
- 구조화가 잘되어 있어서 이해하기 쉬운 테스트
Cypress 설치 및 사용 방법
Cypress 실행 방법에 대해 확인하기 위한 간단한 요약본 자세한 것은 아래 공식 사이트 참조
[ 링크 ] JavaScript End to End Testing Framework
1. 라이브러리 설치
# 프로젝트 경로로 이동 후 package.json 파일에 dev dependency 추가
# npm
npm install cypress --save-dev // npm i -D cypress
# yarn
yarn add cypress --dev
시스템적인 요구사항도 있으니 자세한 사항은 공식 문서를 보고 참고한다. ( 매번 바뀌니 수시로 확인 필요 )
2. cypress 실행
# project root에서 다음 커맨드를 수행
npx cypress open
# yarn
yarn run cypress open
# The long way with the full path
./node_modules/.bin/cypress open
# with the shortcut using npm bin
$(npm bin)/cypress open
매번 실행할 때, 해당 커맨드의 작성에 불편함이 느껴진다면 package.json에서 스크립트 필드에 cypress 실행 명령을 추가하는 것이 편하다.
{
"scripts": {
"cypress:open": "cypress open"
}
}
이와 같이 project root에 커맨드를 추가 해준다.
npm run cypress:open
이후에는 스크립트에 작성한 커맨드를 통해 실행할 수 있게 된다.
3. CLI tools
- Cypress를 실행하면 테스팅을 할 수 있도록 GUI의 실행화면이 제공되고, 해당 인터페이스를 통해서 테스트 타입(E2E, Component)을 정하고, 설정과 실행할 브라우저를 선택할 수 있다.
- 이후 테스트 작성 방법은 공식문서를 통해 자주 사용하는 명령어는 익히고, 잘 잊어 먹는 부분은 기록해두고 수시로 보는 시간을 들여서 숙지하는 방식으로 학습하면 된다.
E2E 작성 방법
자주 사용하는 것, 잘 잊어 먹는 메소드 기록
파일명 작성법
[파일 이름(=Spec)].cy.js
보통 Cypress 에서 이 테스트 단위의 파일을 Spec 이라고 부른다.
테스트 초기 셋팅
describe('oo 기능 테스트',() => {
beforeEach(() => {
cy.visit('테스트 할 사이트 URL');
});
// oo 기능에 대한 테스트 코드가 작성될 영역
it('요구사항 1에 대한 설명(예시 : 버튼 1을 누르면 숫자 1이 증가한다.)', () => {
// 요구사항 1을 충족시키기 위한 구체적인 테스트 코드를 작성
});
});
메소드
지금까지 배운 메소드로 추후 계속 갱신하며 내용을 채울 예정
cy.get(’html 선택자') // 해당 선택자의 html 요소를 선택함
should('비교 대상', '예상하는 값'); // 두 값을 비교해서 test가 통과되는지 확인
// 비교 대상 키워드
// 'eq' -> 앞에서 받은 값과 같은지 비교
// 'have.text' -> 현재 선택된 텍스트와 같은지 비교
then((value) => {
const preValue = Number(value); // 문자 값을 숫자로 연산하기 위해 형변환 하는 예시
});
// 선택자로 받은 값을 형변환 하거나 다양하게 처리할 수 있도록 then 키워드로
// 받아서 처리할 수 있다.
click(); // 클릭 이벤트를 발생시키는 메소드로 요소를 선택하기 위해 사용한다.
// 예시: 'cy.get('#target').click()'
invoke('text'); // invoke 안에 text를 문자열로 받는 경우 html 안의 text를 가져온다.
contains('특정 문자'); // 특정 문자가 포함하는지 확인한다.
// 동일한 이름의 여러 선택자가 있는 경우 그것을 구별하기 위해 내부의 텍스트가 같은지 확인하고
// 그 문자가 포함된 요소를 선택하기 위해 사용한다.