본문 바로가기
기타

Cypress로 E2E 테스트 시작하기

by 유세지 2022. 2. 21.

프로그램을 만들며 기능이 정상적으로 동작하는지, 의도에서 벗어난 점은 없는지 테스트하는 것은 매우 중요합니다. 지난 번에 작성한 Jest 기본 사용법에서는 테스팅 프레임워크인 Jest를 사용해 간단한 단위 테스트를 진행하는 법을 알아보았습니다. 이번 글에서는 E2E 테스트에 특화된 프레임워크인 Cypress를 이용하여 테스트를 시작하는 과정을 보겠습니다.

 

 

E2E 테스트란?

테스트에 앞서, E2E 테스트란 무엇일까요? 지난번에 진행한 단위 테스트의 경우 하나의 기능을 테스트 하는 수준에서 그쳤습니다. 이처럼 큰 프로그램 내에서 하나의 작은 기능 (함수, 클래스 등)을 테스트 하는 것을 단위 테스트(Unit test)라고 부르고, 반대로 유저가 프로그램을 이용하는 시나리오를 따라 프로그램 전체를 테스트 해보는 것을 E2E 테스트 (End-to-End)라고 부릅니다.

 

 

설치 및 테스트 작성

 

명령어를 통해 프로젝트에 cypress를 설치해줍니다.

 

npm install cypress --save-dev

 

설치가 끝나면 곧바로 실행해 볼 수 있습니다.

 

cypress open

 

cypress open 후 todo.spec.js 첫 실행 화면

 

위처럼 직접 크롬창에 띄워놓고 테스트가 가능합니다. 물론 Jest 테스트에서 본 것처럼 CLI 환경에서도 테스트가 가능합니다. 이번 글에서는 후자의 방법으로 해보겠습니다.

 

cypress open 시 생성되었던 integration 폴더에 새로운 테스트 파일을 만들어 넣어주겠습니다. 이름은 app.spec.js 으로 지정해주세요. 기존에 생성된 1-getting-started 와 2-advanced-examples 는 지우셔도 무방합니다.

 

new file : app.spec.js

 

Jest에서 한 것과 유사하게 테스트를 작성해줍니다.

 

describe('기본 동작 확인', () => {
  before(() => {
    cy.visit('./');
  });

  it('이름을 입력하면 경고창에 이름이 표시되어야 한다', () => {
    const stub = cy.stub();

    cy.on('window:alert', stub);

    cy.get('#name-input').type('손흥민');
    cy.get('#name-button').click().then(() => {
      expect(stub).to.be.calledWith('손흥민');
    });
  });
});

 

describe()

describe() 는 테스트 할 동작들을 묶어주는 키워드입니다. 위의 예시처럼 '기본 동작 확인' 과 같은 큰 범위를 지정해주고, 그 내부에 테스트 할 동작들을 각 동작별로 작성해줍니다.

 

it()

it()은 테스트 할 동작의 단위입니다. '이름을 입력하면 경고창에 이름이 표시되어야 한다' 처럼 구체적인 사용자의 동작을 정의해주고 테스트 해주시면 됩니다.

 

before()

before()은 테스트에 들어가기 전, cypress가 준비해야 할 것들을 정의해주는 영역입니다. cy.visit(url) 이 대표적입니다.

 

cy.on()

cy.on() 은 브라우저의 이벤트 객체를 나타냅니다. 위 예시에서는 'window:alert' 속성으로 stub에 경고창을 입력해주었습니다.

 

cy.get()

cy.get()은 DOM 요소를 가져옵니다. document.querySelector의 개념으로 보셔도 괜찮습니다.

 

expect()

테스트가 어떻게 동작해야할지를 나타내는 부분입니다. .to.be 또는 .not.to.be 등의 메서드를 붙여 활용할 수 있습니다.

이 외에도 다양한 테스트 메서드가 있습니다. Cypress는 공식 문서가 정말 잘 정리되어 있는 편이니 꼭 공식 문서를 참고하시면 좋을 것 같습니다.

 

 

설정

테스트를 CLI로 실행하기 위해선 몇 가지 준비가 필요합니다. 먼저 테스트 파일의 기본 경로를 설정해주겠습니다.

자동 생성된 cypress.json 파일을 열면 아무 속성도 없는 빈 파일임을 알 수 있는데, 아래와 같이 수정해줍니다.

 

{
  "integrationFolder": "cypress/integration",
  "testFiles": "*.spec.js"
}

 

testFilesapp.spec.js로 정확히 지정해 줄 수도 있으나, 위처럼 와일드카드(*) 를 이용할 수도 있습니다.

다음은 명령어를 설정할 차례입니다. package.json으로 들어가서 script 부분을 다음처럼 수정해주겠습니다.

 

"scripts": {
  "cypress:run": "cypress run",
  ...
},

 

이것으로 CLI에서 실행할 준비가 모두 끝났습니다. 콘솔창에 npm run cypress:run 을 입력하여 실행해봅시다.

 

실패 시 (index.html을 만들지 않아서 생긴 404 오류)

 

 

성공시

 

가독성 향상을 위한 팁

 

1. given-when-then 패턴

given, when, then 주석을 이용하면 테스트 별로 어떤 의미를 갖고있는지 쉽게 알려줄 수 있습니다.

 

describe('기본 동작 확인', () => {
  before(() => {
    cy.visit('./');
  });

  it('이름을 입력하면 경고창에 이름이 표시되어야 한다', () => {
    // given (준비)
    const stub = cy.stub();

    cy.on('window:alert', stub);

    // when (사용자가 동작을 했을때)
    cy.get('#name-input').type('손흥민');
    cy.get('#name-button').click().then(() => {
      // then (이렇게 동작할 것이다)
      expect(stub).to.be.calledWith('손흥민');
    });
  });
});

 

이렇게 역할에 따라 주석을 붙여주면, 테스트 코드를 보는 입장에서 파악하기 한결 수월해지는 효과가 있습니다.

 

 

2. 함수화 및 상수화

많은 분들이 놓치는 부분 중 하나가 테스트 코드도 코드라는 점입니다. 따라서 우리가 사용하는 패턴이나 기법들도 얼마든지 적용해 줄 수 있습니다.

 

const NAME_INPUT = '#name-input';
const NAME_BUTTON = '#name-button';
const TEST_STRING = '손흥민';

describe('기본 동작 확인', () => {
  before(() => {
    cy.visit('./');
  });

  it('이름을 입력하면 경고창에 이름이 표시되어야 한다', () => {
    // given (준비)
    const stub = cy.stub();

    cy.on('window:alert', stub);

    // when (사용자가 동작을 했을때)
    cy.get(NAME_INPUT).type(TEST_STRING);
    cy.get(NAME_BUTTON).click().then(() => {
      // then (이렇게 동작할 것이다)
      expect(stub).to.be.calledWith(TEST_STRING);
    });
  });
});

 

위처럼 DOM 요소의 경우 상수화를 시켜 다른 파일로 분리시켜 줄 수도 있고, 많이 반복되는 코드라면 따로 함수로 꺼내줄 수도 있습니다.

 

 

 

마무리

여기까지 Cypress를 사용한 E2E 테스트 방법을 알아보았습니다. 생각보다 어렵지 않고, 공식 페이지에도 친절한 설명과 예시가 많으니 금방 익숙하게 사용할 수 있을 것 같습니다. 읽어주셔서 감사합니다.

 

반응형

댓글