cypress로 API(비동기) 테스트하기

바다·2024년 4월 2일
0

test

목록 보기
1/1
post-thumbnail

우테코 레벨1 "영화 리뷰" 미션의 요구사항으로 cypress를 이용한 API 비동기 테스트가 있었습니다. cypress로 API 비동기 테스트 코드를 짜면서 알게 된 것들에 대해 정리해 보려 합니다.

접근 권한이 필요없는 경우

http 요청 시 접근 권한이 필요없다면 cy.request만 사용하면 됩니다.

const url ='get_요청을_보내는_url';
cy.request('GET', url).as('searchMovies');

접근 권한이 필요한 경우

http 요청 시 API key가 필요한 경우라면 어떻게 해야할까?

env파일에서 환경 변수로 API key를 설정했다는 가정하에서 설명하겠습니다.

1. cypress.env.json 에서 env 설정

아쉽게도 cypress는 root/env 파일에서 설정한 환경변수를 cypress.config.js에서 불러와 사용할 수 없습니다.

그래서 cypress에서 API key를 사용하기 위해서 별도의 조치를 해야 합니다. 다음에서 설명할 cypress.config.js에서 API key를 직접 설정하는 방법도 있지만, cypress.env.json을 사용하는 것이 더 나은 방법이라고 생각합니다.

  • root/cypress.env.json
{"apiKey":"apikey_값"}

cypress.config.js가 아닌 cypress.env.json에서 API key를 설정해야하는 이유

  1. API key를 cypress.config.js 에서 설정할 경우 보안 이슈로 cypress.config.js를 git에 올리지 못합니다. 팀 협업인 경우 cypress 설정 파일인 cypress.config.js를 팀원끼리 공유하지 못하며 추후 유지 보수 때 로컬 저장소에 해당 파일이 없으면 cypress.config.js를 다시 생성해야하는 번거로움이 있습니다.

  2. 값 이 긴 API key가 여러개 라면 cypress.config.js 파일의 가독성이 떨어집니다.

  3. cypress.config.js는 cypress의 환경 설정 파일로 API key값 이 직접적으로 들어있을 것을 예측하기 어렵습니다. 이는 파일 관리에 문제로 이어질 수 있습니다.

env에 설정한 환경변수를 cypress.env.json에서 사용할 수 없을까?

root/env에서 환경변수로 생서한 api key는 cypress.config.js에서 불러올 수 없지만 Node.js나 다른 도구를 사용하면 cypress.env.json 에서 사용할 수 있습니다.

Node.js에서 env 환경 변수를 사용해 cypress.env.json 파일을 생성하는 방법
const fs = require('fs');
const path = require('path');

// root/env 디렉토리의 환경 변수 읽기
const envVariables = require('./env');

// 환경 변수를 cypress.env.json 파일에 쓰기
const cypressEnv = {
  ...envVariables
};

const cypressEnvFilePath = path.join(__dirname, 'cypress.env.json');

fs.writeFileSync(cypressEnvFilePath, JSON.stringify(cypressEnv, null, 2));

console.log('cypress.env.json 파일이 생성되었습니다.');

2. cypress.config.js에서 환경 변수를 적용

cypress.env.json에서 설정한 API key를 다음과 같이 불러와서 cypress.config.js의 env로 설정해주면 됩니다.

import { defineConfig } from 'cypress';

import * as env from './cypress.env.json';

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:8080',
  },
  env: {
    API_KEY: env.apiKey,
  },
});
  • 💡 typescript로 진행 중이라면 d.ts 파일을 통해 json을 ts에서 사용할 수 있도록 해주어야 합니다.

mock data를 활용해야하는 경우

mock data가 필요한 이유

영화 리뷰 미션에서 무한 스크롤을 통해 영화 리스트 데이터를 받아오다가 더 이상 불러올 데이터가 없는 경우 관련된 문구를 보여주고 더 이상의 API 요청을 막아야 하는 기능을 구현해야 했습니다. 이를 테스트로 진행한다면 인기 영화 리스트의 페이지는 5000페이지가 넘기 때문에 API 요청을 할 수 있는 최대 페이지인 5000페이지에 도달할 때까지 스크롤을 계속해야 합니다.

이처럼, API 테스트를 진행하다 보면 테스트에 적합한 데이터를 받아오고 싶지만 어려울 경우가 있습니다.

이때 유용한 게 mock data입니다.
mock data는 실제 데이터 베이스나 시스템에서 사용되는 것이 아니라 테스트, 알고리즘 개발 등에서 사용하기 위해 만들어진 데이터입니다. mock data를 사용하면 원하는 테스트를 진행할 수 있고 테스트 진행 시 실제 서버가 있는 데이터가 변경되거나 손상되는 위험을 줄일 수 있습니다.

cypress에서 mock data 사용하기

1. fixture폴더에 mock data 저장하기

  • fixture?
    데스트 중에 사용되는 정적 데이터를 저장하는 용도로 사용됩니다.

  • 구현하고자 하는 테스트 케이스

  1. 페이지를 처음 방문하면 page가 1인 인기 영화 리스트 데이터를 받는다.
  2. 스크롤 시, 다음 영화 리스트 데이터인 pag e2가 불러와지며 해당 페이지가 마지막 인기 영화 리스트 페이지이다. (실제로는 더 많은 데이터가 존재한다.)
  3. 마지막 데이터가 불러와지면 화면에는 '더 이상 불러올 데이터가 없다.'는 의미가 담긴 아이콘과 문구가 나오며 스크롤을 하더라고 API 요청이 이루어지지 않는다.

위와 같은 테스트 케이스를 구현하기 위해서 실제 API 요청을 하는 것이 아니라 다음과 같은 mock data를 만들어서 API 요청을 가로채서 mock data를 response 하도록 하면 됩니다.

  • 마지막 인기 영화 리스트 mock data
{
"page":2,
  "results":[
  //영화 데이터,
  //영화 데이터,
  //....
  ],
   "total_pages": 2,
}

2.HTTP 요청 가로채기 및 mock data 적용

프로덕션 코드의 HTTP 요청을 가로채서 1에서 지정한 mock data를 response 하려면 cypress의 intercept,as를 사용하면 됩니다.

intercept에 가로챌 http 요청 url을 적어주면 됩니다. 만약 url이 파라미터값에 따라 변경되는 동적인 url이라면 정규표현식을 쓰는 것이 좋습니다. 정규표현식을 사용하면 동적url에 유연하게 대응할 수 있습니다.

//page에 따라서 다른 url이 생성되고, 해당 url에 대한 정규표현식 결과를 통과하는 http 요청을 가로챔
const getPopularURL = (page) =>
  new RegExp(
    `^https:\\/\\/api\\.themoviedb\\.org\\/3\\/movie\\/popular\\?.*page=${page}.*`,
  );

 cy.intercept(
      {
        method: 'GET',
        url: getPopularURL(1),
      },
   //staticResponse
      { fixture: 'movie-popular-page1.json' },
    ).as('getPopularMovies');

intercet의 옵션에서 가로챈 http요청에 대신 보내줄 mock data를 fixture:mock data파일 을 통해 지정해 주면 됩니다.

위의 intercept로 보면 'as'명령어를 사용해 intercetp로 대신 response를 보내주는 resource의 별칭을 지정해 주면 다음에서 설명한 wait에서 유용합니다.

3. intercept의 응답을 받을 후 테스트 진행

wait와 then을 사용하면 intecept로 지정한 요청을 기다린 후 원하는 테스트 코드를 작성할 수 있습니다.

cy.intercept(
     {
       method: 'GET',
       url: getPopularURL(1),
     },
     { fixture: 'movie-popular-page1.json' },
   ).as('getPopularMovies');
   
 cy.intercept(
     {
       method: 'GET',
       url: MOVIE_INFO_URL,
     },
     { fixture: 'movie-info.json' },
   ).as('getMovieInfo');


cy.wait('@getPopularMovies').then((intercept)=>{
	// getPopularMovies 응답 후, 진행할 테스트
	cy.wait('@getMovieInfo').then((intercept)=>{
	// getMovieInfo 응답 후, 진행할 테스트
	})
})

마무리

우테코를 하면서 처음 접한 cypress로 API 테스트 코드를 짜는 게 미션 구현보다도 더 힘들었습니다. 😥 하지만 코드를 수정하고 기능이 잘 돌아가는지 확인할 때 cypress를 돌리면 되어서 편했고 힘들었지만 보람 있었습니다.

profile
🐣프론트 개발 공부 중 (우테코 6기)

0개의 댓글