Notice
Recent Posts
Recent Comments
Link
관리 메뉴

윤일무이

[Test Code] 프론트엔드 TDD 본문

⚛️ React/📜 Test Code

[Test Code] 프론트엔드 TDD

썸머몽 2024. 7. 16. 21:37
728x90

TDD란

성공/실패 케이스를 작성한 테스트 코드를 먼저 구현하고 해당 테스트 케이스에 맞게 코드를 구현하는 것

이전까지 진행한 방식은 컴포넌트를 먼저 만들고 기능 구현을 한 다음에 테스트 코드를 붙인 거라 TDD라고 할 수는 없다고 한다.

 

회원가입 로직으로 TDD를 진행해보자.

SignupPage.tsx에 있던 ui는 모두 지워준다.

// signup.cy.js

describe('회원가입 테스트', () => {
  it('사용자는 이메일과 비밀번호를 사용해서 회원가입한다', () => {
    // given - 회원가입 페이지에 접근한다
    cy.visit('/signup');
    // when - 이메일과 비밀번호를 입력한다 + 비밀번호와 비밀번호 확인값이 일치한다
    // then - 회원가입 버튼이 활성화 되어 회원가입에 성공하고 로그인 페이지로 이동한다
  });
});

 

npm run ci, npm run cypress를 하면 cypress 화면이 뜬다.

정상적으로 회원가입 페이지에 접속했다.

// signup.cy.js

describe('회원가입 테스트', () => {
  it('사용자는 이메일과 비밀번호를 사용해서 회원가입한다', () => {
    // given - 회원가입 페이지에 접근한다
    cy.visit('/signup');
    cy.get('[data-cy=signupButton]').as('signupButton');
    cy.get('@signupButton').should('be.disabled');

    // when - 이메일과 비밀번호를 입력한다 + 비밀번호와 비밀번호 확인값이 일치한다
    cy.get('[data-cy=emailInput]').as('emailInput');
    cy.get('[data-cy=passwordInput]').as('passwordInput');
    cy.get('[data-cy=confirmPasswordInput]').as('confirmPasswordInput');

    cy.get('@emailInput').type('email@email.com');
    cy.get('@passwordInput').type('password');
    cy.get('@confirmPasswordInput').type('password');

    cy.get('@passwordInput')
      .invoke('val')
      .then(passwordValue => {
        expect(passwordValue.trim()).to.not.be.empty;

        cy.get('@confirmPasswordInput')
          .invoke('val')
          .should('eq', passwordValue);
        cy.get('@signupButton').should('not.be.disabled');
      });

    // then - 회원가입 버튼이 활성화 되어 회원가입에 성공하고 로그인 페이지로 이동한다

    cy.intercept(
      {
        method: 'POST',
        url: '/user/signup',
      },
      {
        msg: 'SUCCESS',
      }
    ).as('signup');
    cy.get('@signupButton').click();
    cy.url().should('include', '/login');
  });
});

 

이렇게 테스트 로직을 짰는데 현재 ui 부분을 모두 지웠기 때문에 해당 값을 가져오지 못해 에러가 발생한다.

이제 다시 ui를 그려주자.

 

  1. 회원가입 버튼 비활성화

  2. 이메일/비밀번호/비밀번호 확인 Input에 입력이 되면 그 값이 state에 저장되도록

  3. 비밀번호/비밀번호 확인 값 일치

  4. 회원가입 버튼 활성화

  5. 회원가입 버튼 클릭 시 useSignup 훅으로 회원가입 요청

  6. 회원가입 요청이 성공하면 alert 회원가입 성공 메세지 + 로그인 페이지로 이동

 

이 로직대로 진행한다.

 

// SignupPage.tsx

	<Wrapper>
      <input data-cy="emailInput" />
      <input data-cy="passwordInput" />
      <input data-cy="confirmPasswordInput" />
      <button data-cy="signupButton" disabled={true}>
        회원가입
      </button>
    </Wrapper>

 

우선 이렇게 ui를 구성하고 가면 버튼 부분에서 에러가 발생한다.

회원가입 버튼이 아직 비활성화 되어 있다고 한다.

활성화 시키려면 이메일/비밀번호/비밀번호 확인이 입력되고 비밀번호/비밀번호 확인 값이 같아야 한다.

 

const isSignupBtnActive = !!email && !!password && password === confirmPassword;

이 코드를 적어주고 button에 disabled={!isSignupBtnActive}를 걸어주자.

응 또 에러야~

이건 아까 위에서 적은 2번 (state에 저장되도록)이 되지 않아서 그렇다.

// SignupPage.tsx

   <Wrapper>
      <Input data-cy="emailInput" onChange={e => setEmail(e.target.value)} />
      <Input
        data-cy="passwordInput"
        onChange={e => setPassword(e.target.value)}
      />
      <Input
        data-cy="confirmPasswordInput"
        onChange={e => setConfirmPassword(e.target.value)}
      />
      <SignupButton data-cy="signupButton" disabled={!isSignupBtnActive}>
        회원가입
      </SignupButton>
    </Wrapper>

 

위 코드처럼 바꿔줬다.

응 아직도야~

이제 회원가입 버튼 클릭 시 로그인 화면으로 넘어가게 해준다.

      <SignupButton
        data-cy="signupButton"
        disabled={!isSignupBtnActive}
        onClick={() => handleSignup({ username: email, password })}
      >

 

위와 같이 코드를 수정해주면 진짜 끝!

이야 대단해~

 

chatGPT를 사용해서 마저 테스트하기

비밀번호/비밀번호 확인값이 같이 않을 때 에러 메세지가 뜨는 것까지 테스트 해보자.

이전에 삭제한 SignupPage의 ui를 다시 되돌리고 해야 에러가 안 난다 ㅎㅎ...

 

// signup.cy.js

it('비밀번호와 비밀번호 확인 값이 일치하지 않는 경우 에러 메세지가 나타난다', () => {
    // given - 가입 페이지로 이동
    cy.visit('/signup');
    // when - 비밀번호와 비밀번호 확인에 각각 다른 값 입력
    cy.get('[data-cy=passwordInput]').type('password123');
    cy.get('[data-cy=confirmPasswordInput').type('miss');
    // then - 에러 메세지 확인
    cy.get('[data-testid=error-message]')
      .should('be.visible')
      .and('have.text', '비밀번호가 일치하지 않습니다');
  });

 

이 케이스를 추가해준다.

끝!

 


 

참고 강의

 

2시간으로 끝내는 프론트엔드 테스트 기본기 강의 | 강병진 - 인프런

강병진 | 테스트코드! 어디서부터 시작해야할지 막막한 분들을 위해 준비했어요. 테스트 작성부터, 자동화를 통한 배포까지 한번에!, 테스트 코드를 작성하고 싶은 프론트엔드 개발자를 위한 강

www.inflearn.com

 

728x90