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

김가희·2024년 5월 7일
0

문제 상황

  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개의 댓글