2021 02 08(월) TIL - 272 cypress(자동차 경주 게임 미션 PR)

15362 단어 TILcypressTIL

Today I Learned

cypress 실패 사례(*의존성 있는 함수)

어제에 이어 기능 구현을 모두 마쳤다. 기능 구현을 마치고 작성해놓은 테스트를 모두 통과하는 줄 알았는데 착각이었다.

  it('자동차 경주를 마쳤을 때 우승자를 정상적으로 출력하는지 테스트 한다.', () => {
    let winner;
    typeCarNameAndSubmit();
    typeRacingCountAndSubmit();


    winner = getWinner();
    cy.get('#game-result-text').should(`🏆 최종 우승자: ${winner} 🏆`);
  });

위와 같은 테스트 코드를 작성했다. 기능 구현에 사용한 getWinner()함수를 테스트 코드에서도 사용해 간단하게 테스트를 할 계획이었다. 그러나 위와 같이 코드를 작성하면 typeCarNameAndSubmit(), typeRacingCountAndSubmit() 함수가 실행되기 전에 getWinner()가 실행되는 시점에서 자동차 목록과 게임 진행 상황을 불러오지 못 했다.

  it('랜덤 함수가 정상적으로 동작하는지 테스트 한다.', () => {
    const possibleScores = Array.from({
      length: GAME.MAX_SCORE - GAME.MIN_SCORE + 1,
    }).map((v, i) => i);

    for (let i = 0; i < 100; i++) {
      expect(possibleScores).to.include(getRandomNumber());
    }
  });

비슷하게 getRandomNumber() 함수를 호출해서 테스트한 경우에는 getRandomNumber() 같은 경우는 의존성 없이 독립적으로 실행되는 모듈이지만 getWinner()의 경우 실행되기 위해서는 DOM에 있는 요소들이 필요하기 때문에 생기는 문제였다. async/await 사용을 시도했지만 테스트가 실패했다. setTimeOut() 을 통해 아래와 같이 테스트를 고쳤다.

  it('자동차 경주를 마쳤을 때 우승자를 정상적으로 출력하는지 테스트 한다.', () => {
    let winner;
    typeCarNameAndSubmit();
    typeRacingCountAndSubmit();

    setTimeout(() => {
      winner = getWinner();
      cy.get('#game-result-text').should(`🏆 최종 우승자: ${winner} 🏆`);
    }, 1000);
  });

이 때 테스트의 ✅만 보고 테스트 코드가 맞게 수정된 줄 알고 넘긴게 화근이 됐다.

테스트가 정상적으로실행된게 아니고 setTimeOut() 가 동작하지 않고 넘어가고 있었다. get.clock()등을 사용해보면서 getWinner()를 사용할 여러 방법을 시도해봤지만 모두 실패했다. 결국 DOM을 직접 파싱해와서 다음과 같이 코드를 수정했다.

  it('자동차 경주를 마쳤을 때 우승자를 정상적으로 출력하는지 테스트 한다.', () => {
    typeCarNameAndSubmit();
    typeRacingCountAndSubmit();

    cy.get('.car').then(($cars) => {
      const counts = [...$cars].map(($car) => {
        return $car.querySelectorAll('.forward-icon').length;
      });
      const maxScore = Math.max(...counts);
      const winners = [];

      counts.forEach((carCount, index) => {
        if (carCount === maxScore) {
          winners.push(carNames[index]);
        }
      });

      cy.get('#game-result-text').should(
        'have.text',
        `🏆 최종 우승자: ${winners.join(', ')} 🏆`,
      );
    });
  });

코드를 수정하고 다시 테스트를 했을 때 의도한대로 테스트가 동작하는걸 확인할 수 있었다.

테스트코드의 비용

아직 cypress에 익숙하지 않아 그런것도 있겠지만 테스트 코드 구현과 기능 구현을 놓고 봤을 때 테스트 코드를 구현하는데 더 오랜 시간이 걸리는거 같다. 물론 테스트 코드를 미리 구현함으로써 기능을 구현할 때 빠르게 작성 가능한 부분도 있다. 하지만 결국 테스트 코드가 모든 예외사항을 100% 커버할 수는 없기 때문에 어느 정도 수준까지 커버할 수 있게 테스트 코드를 작성해야 할지에 대한 고민이 있다.

이제 막 cypress를 처음 사용해보면서 테스트 코드를 처음 작성했기 때문에 생기는 고민인거 같기도 하다. 앞으로 구현하는 프로그램들에 TDD, BDD를 적용해서 구현하면서 계속 고민 해봐야겠다.

첫번째 PR

페어 프로그래밍으로 함께 구현하는 부분을 모두 마쳤다. 1주일이라는 짧은 시간 동안 페어와 함께 프로그래밍 하면서 많이 배울 수 있었다. 페어 프로그래밍을 진행하면서 특히 막히는 부분이 있을 때마다 페어가 해결사 역할을 해줘서 비교적 빠르게 끝낼 수 있었다.첫 페어로 다시 함께 페어를 하고 싶은 좋은 페어를 만나서 즐겁게 페어 프로그래밍을 진행할 수 있었다.

처음으로 PR을 보냈는데 필드에서 활약하고 계신 개발자 분들에게 리뷰를 받을 생각을 하니 너무 설레고 떨린다. 리뷰어 분들의 피드백을 잘 흡수해야겠다!

Thanks To Pair : 하루


Today Commit Review

  • woowacourse-projects
    • 자동차 경주 게임 미션의 step1과 step2를 분리했다.
  • javascript-racingcar
    • PR을 제출했다. 처음 올린 PR의 브랜치 이름을 깃헙 아이디와 다르게 설정해서 close후 다시 PR했다.

Today Review

  • 드디어 미션이 하나 끝났다. 리뷰를 받을 생각에 두근두근 하다. 리뷰가 빨리 달렸으면 좋겠다.
  • 다른 크루들의 PR도 올라오고 있는데 다른 크루들의 PR도 꼼꼼하게 읽어보고 배워가야겠다.

좋은 웹페이지 즐겨찾기