[Cypress] Firebase를 활용한 회원가입 자동화 테스트 트러블 슈팅

김가희·2024년 5월 7일

문제 상황

  1. 사용자는 이메일과 비밀번호를 사용해서 회원 가입 한다.
  2. 이미 사용 중인 이메일로 가입을 시도하면 에러 메시지를 보여 준다.

Cypress를 이용하여 위 두 가지의 상황으로 회원 가입 테스트 코드를 작성하려고 했는데 문제가 발생했다.
input type을 하다가 자꾸만 로그 중간에 (new url) http://localhost:5173/ 이 뜨면서 메인 화면으로 이동하였고, input을 찾을 수 없다면서 오류가 떴다.



문제 원인

문제의 원인은 1번 상황을 테스트 할 때 회원 가입 후 자동으로 로그인이 되면서, 두 번째 테스트에서 /signup 페이지로 접속하면 이미 로그인된 상태로 간주되어 메인 페이지로 리다이렉트되었기 때문이었다. 첫 번째 테스트의 로그인 상태가 두 번째 테스트에 영향을 미치게 된 것이다.



문제 해결

이 문제를 해결하기 위해서는 두 가지 방법이 있을 것 같았다.

  1. 파일 나누어 독립적인 테스트로 실행하기
  2. 로그아웃 명령 추가로 구현하여 한 파일에서 테스트하기

1번을 선택하면 추가 구현을 하지 않아도 되어서 더 간편할 것 같았지만, 나는 실행 효율성을 위하여 2번 방법을 선택했다.


문제 해결 과정

로그인 상태인지 확인하고 로그인 상태인 상태일 땐 로그아웃을 시켜 주어 회원 가입을 할 수 있게 코드를 추가해 주어야 했다.

  • Firebase 설정 추가
// cypress/support/index.ts

import { initializeApp } from 'firebase/app';

const firebaseConfig = {
  apiKey: Cypress.env('FIREBASE_API_KEY'),
  authDomain: Cypress.env('FIREBASE_AUTH_DOMAIN'),
  projectId: Cypress.env('FIREBASE_PROJECT_ID'),
  storageBucket: Cypress.env('FIREBASE_STORAGE_BUCKET'),
  messagingSenderId: Cypress.env('FIREBASE_MESSAGING_SENDER_ID'),
  appId: Cypress.env('FIREBASE_APP_ID'),
};

export const app = initializeApp(firebaseConfig);
  • Firebase Auth 로그아웃 명령 실행: Cypress 테스트에서 직접 Firebase Auth의 로그아웃 함수를 호출하여 사용자를 로그아웃시키기
    -> 커스텀 Cypress 명령 추가하여 로직 호출
// cypress/support/commands.ts

/// <reference types="cypress" />

import { getAuth, signOut } from 'firebase/auth';
import { app } from './index.ts';

Cypress.Commands.add('firebaseLogout', () => {
  const auth = getAuth(app);
  return signOut(auth);
});
// cypress/support/cypress.d.ts

declare namespace Cypress {
  interface Chainable {
    firebaseLogout(): Promise<void>;
  }
}

cypress에서 쓰이는 env 파일은 프로젝트 루트 폴더(기존 .env 파일이랑 같은 위치)에 위치해야 적용된다!

완성된 테스트 코드

const { user } = require('../fixtures/user');

describe('회원가입 테스트', () => {
  const { buyer } = user;

  beforeEach(() => {
    // Given - 회원가입 페이지로 접속한다.
    cy.visit('/signup');

    cy.get('input[name="userType"]').as('userTypeInput');
    cy.get('input[name="email"]').as('emailInput');
    cy.get('input[name="nickname"]').as('nicknameInput');
    cy.get('input[name="password"]').as('passwordInput').should('be.visible');
    cy.get('input[name="passwordConfirm"]').as('passwordConfirmInput');
    cy.get('input[name="phone"]').as('phoneInput');
    cy.get('[data-cy="signup-button"]')
      .as('signupButton')
      .should('be.disabled');
  });

  it('사용자는 이메일과 비밀번호를 사용해서 회원가입 한다.', () => {
    // When - 사용자 유형, 이메일, 닉네임, 비밀번호, 비밀번호 확인, 전화번호를 입력하고 회원가입 버튼을 클릭한다.
    cy.get('@userTypeInput').check(buyer.userType);
    cy.get('@emailInput').type(buyer.email);
    cy.get('@nicknameInput').type(buyer.nickname);
    cy.get('@passwordInput').type(buyer.password);
    cy.get('@passwordConfirmInput').type(buyer.password);
    cy.get('@phoneInput').type(buyer.phone);

    cy.get('@signupButton').should('not.be.disabled');
    cy.get('@signupButton').click();

    // Then - 회원가입이 완료되고 메인 페이지로 이동한다.
    cy.url().should('eq', `${Cypress.config().baseUrl}/`);
    cy.get('[data-cy="alert-dialog-title"]').should('contain', '환영합니다!');
  });

  it('이미 사용 중인 이메일로 가입을 시도하면 에러 메시지를 보여 준다.', () => {
    // When - 이미 사용 중인 이메일로 회원가입을 시도한다.
    cy.get('@userTypeInput').check(buyer.userType);
    cy.get('@emailInput').type('test@test.com');
    cy.get('@nicknameInput').type(buyer.nickname);
    cy.get('@passwordInput').type(buyer.password);
    cy.get('@passwordConfirmInput').type(buyer.password);
    cy.get('@phoneInput').type(buyer.phone);

    cy.get('@signupButton').should('not.be.disabled');
    cy.get('@signupButton').click();

    // Then - 에러 메시지를 보여 준다.
    cy.get('[data-cy="alert-dialog-title"]').should(
      'contain',
      '다시 시도해 주세요.',
    );
  });

  afterEach(() => {
    cy.firebaseLogout();
  });
});

0개의 댓글