Cypress를 통한 E2E Test

Cypress를 통한 E2E Test

생성일
2023년 05월 11일
태그
Cypress

Background

현재 서비스를 앞두고 있는 프로젝트에는 3가지 환경이 있다.
stage - 팀 내부에서 테스트를 하기 위한 환경, Docker를 통해 AWS EKS로 배포되어있다.
stage-live - QA팀이 실제 데이터를 가지고 테스트를 하기 위한 환경, AWS Amplify로 배포되어있다.
live - 실제 서비스가 되는 환경, AWS Amplify로 배포되어있다.
 
현재. 회사에서 앱 리브랜딩에 총력을 다하고 있기 때문에, 웹 서비스를 테스트할 여유가 없다. 앱 리브랜딩 일정에 맞추어 기존의 기능을 그대로 가지고 디자인만 바꾸어 1차 배포를 진행하려고 한다.
1차 배포에는 로그인 기능이 없기 때문에, Cypress를 통하여 간단한 동작만을 테스트하려고 한다.
또한, 많은 유저가 사용하기 때문에 웹 성능과 사용자 경험이 매우 중요하다. 매번 LightHouse로 성능을 측정하는 것이 보통 일이 아니기 때문에, Amplify Pipeline에 LightHouse CI를 적용하려고 한다.

해보자

stage-live 환경에 cypress를 적용하기 위해 새로운 feature branch를 생성하고, AWS Amplify를 사용하여 동일한 환경으로 배포를 하였다.
시작으로, 로컬에 cypress 를 설치한다.
pnpm install cypress --dev
 
로컬에서 Cypress Cli를 이용할 수 있다.
./node_modules/.bin/cypress open
notion image
 
package.json 에 명령어를 추가하였다.
"scripts": { "cypress:open": "cypress open" }
pnpm cypress:open
 
E2E 테스트를 선택해준다. 후에 테스트할 브라우저를 선택한다.
notion image
 
시작하면 다음과 같이 크롬 브라우저가 열린다.
notion image
 
cypress 설치하고 cli를 여는 것까지 완료했으면 이제는 테스트를 해볼 시간이다.
 
해당 경로의 파일을 수정하려는데 TypeScript 오류를 마주쳤다.
// cypress/e2e/spec.cy.ts describe('template spec', () => { it('passes', () => { cy.visit('https://example.cypress.io') }) })
'describe' 이름을 찾을 수 없습니다. 테스트 실행기의 형식 정의를 설치하려는 경우 'npm i --save-dev @types/jest' 또는 'npm i --save-dev @types/mocha'를 시도합니다.ts(2582)
cypress.config.js 를 설정해주자
import { defineConfig } from 'cypress'; import { lighthouse, prepareAudit } from '@cypress-audit/lighthouse'; export default defineConfig({ video: false, e2e: { baseUrl: 'http://localhost:3000', setupNodeEvents(on, config) { on('before:browser:launch', (browser = {}, launchOptions) => { prepareAudit(launchOptions); }); on('task', { lighthouse: lighthouse(), }); }, }, });

ESLint Settings

pnpm install --save-dev eslint-plugin-cypress
// .eslintrc.js module.exports = { plugins: ['cypress'], env: { 'cypress/globals': true, }, extends: ['plugin:cypress/recommended'], }

Real Test 작성하기

공식문서에서 제공하는 case로 테스트를 해 볼 생각이다. 단계는 다음과 같다.
  1. Visit a web page.
  1. Query for an element.
  1. Interact with that element.
  1. Assert about the content on the page.
 
  • Visit a web page
AWS Amplify로 호스팅 되어있는 feature branch의 페이지를 방문한다.
cy.visit 메서드를 통해 방문한다.
describe('My First Test', () => { it('Visits main-web-v2', () => { cy.visit('https://{Amplify주소}.amplifyapp.com/') }) })
해당 파일을 저장했더니 다음과 같이 체킹을 진행한다.
notion image
좌측 테스트들은 콘솔창을 통해 더 자세히 확인할 수 있다.
 
  • Query for an element
페이지에서 발생하는 액션들을 테스트하기 위한 단계이다.
cy.contains 메서드를 통해 체크하고 싶은 것들을 포함시킨다.
describe('My First Test', () => { it('Visits main-web-v2', () => { // 사이트 방문 cy.visit('https://{Amplify 주소}.amplifyapp.com/'); // 체크할 사항들 포함 cy.contains('이벤트'); }); });
해당 코드는 페이지에 이벤트가 존재하는지 확인하는 코드이다. 저장을 하면 다음과 같이 찾아준다.
notion image
notion image
 
  • Interact with that element
이제는 선택된 요소를 클릭할 것이다. click 메서드를 활용한다.
다음은 에어팟 키워드로 상품 리스트 페이지로 진입하는 과정이다.
describe('My First Test', () => { it('이벤트 탭이 존재하는지 확인하기', () => { // 사이트 방문 cy.visit('https://{Amplify 주소}.amplifyapp.com/'); // 체크할 사항들 포함 cy.contains('#에어팟').click(); }); });
notion image
 
  • Assert about the content on the page
3번째 단계에서 진행한 상호작용에서 반드시 행해져야하는 task들을 지정하는 곳이다. 에어팟 탭을 눌렀을 때 url이 정상적으로 작동하는지 테스트하는 코드이다.
describe('My First Test', () => { it('이벤트 탭이 존재하는지 확인하기', () => { // 사이트 방문 cy.visit('https://{Amplify 주소}.amplifyapp.com/'); // 체크할 사항들 포함 cy.contains('#에어팟').click(); // 해당 액션이 반드시 발생해야함 cy.url().should('include', '/search'); }); });

Continuous Integration

서론에서 말했다시피, 이러한 테스트 코드와 성능 측정 등을 CI에 넣어서 자동화하는 것이 목표이다. 따라서, 간단하게 테스트했던 cypress를 CI에 세팅하려고 한다.
AWS Amplify에 Cypress를 통한 E2E 테스트를 적용시켜보자.
 
현재 Amplify 배포 단계는 3단계이다.
  1. Provision
  1. Build
  1. Deploy
E2E 테스트를 추가해주면 Provision과 Build 단계 사이에 Test 단계가 생성된다.
  • AWS의 USER_DISABLE_TESTS 변수를 이용하여 특정 브랜치에만 테스트를 적용시킬 수 있다.
notion image
 
  • 다음은 amplify.yml 파일을 수정해주어 test 단계를 넣어주어야 한다.
version: 1 frontend: phases: preBuild: commands: - if [ "${AWS_BRANCH}" = "main" ]; then curl -d "APP_NAME=main-web-live&ENV=LIVE" -X POST https://gt37hz2t7zalff3es4e3voqvwu0tetey.lambda-url.ap-northeast-2.on.aws/start; fi - curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=7.25.0 sh -; - source /root/.bashrc; - CI=true pnpm install; build: commands: - env | grep -e NEXT_PUBLIC_ >> .env.production - env | grep -e NEXTAUTH_ >> .env.production - env | grep -e KAKAO_ >> .env.production - env | grep -e NAVER_ >> .env.production - pnpm build; postBuild: commands: - if [ "${AWS_BRANCH}" = "main" ]; then curl -d "APP_NAME=main-web-live&ENV=LIVE" -X POST https://gt37hz2t7zalff3es4e3voqvwu0tetey.lambda-url.ap-northeast-2.on.aws/end; fi artifacts: baseDirectory: .next files: - '**/*' test: artifacts: baseDirectory: cypress configFilePath: '**/mochawesome.json' files: - '**/*.png' - '**/*.mp4' phases: preTest: commands: # korean font install - wget http://static.campaign.naver.com/0/hangeul/renew/download/NanumFont_TTF.zip - unzip Nanum*.zip - mkdir -p /usr/share/fonts/nanumfont - mv *.ttf /usr/share/fonts/nanumfont - fc-cache -r # korean font - pnpm install -g wait-on - pnpm install -g pm2 - pnpm install mocha mochawesome mochawesome-merge mochawesome-report-generator - pnpm pm2 start pnpm -- start - 'wait-on http://localhost:3000' test: commands: #baseUrl 추가 - 'pnpm cypress run --config baseUrl=http://localhost:3000 --reporter mochawesome --reporter-options "reportDir=cypress/report/mochawesome-report,overwrite=false,html=false,json=true,timestamp=mmddyyyy_HHMMss"' postTest: commands: - pnpm mochawesome-merge cypress/report/mochawesome-report/mochawesome*.json > cypress/report/mochawesome.json - pm2 kill
다음과 같이 test 단계가 추가되었다.
notion image
 
기능을 개발하고 해당 브랜치에 merge를 하면 Provision, Build 이후에 cypress test가 진행된다.
테스트가 통과하면 다음과 같이 배포가 완료된다.
notion image

References

 

댓글

guest