우당탕탕 기술블로그

[회고록] 우아한 테크코스 6기 프리코스 2주차 회고 본문

Project

[회고록] 우아한 테크코스 6기 프리코스 2주차 회고

hyzzzy 2023. 11. 2. 13:38

목차

1. 자동차 경주 코드 구조

   1.1. 게임 시작

   1.2. 게임 진행

   1.3. 게임 종료

   1.4. 폴더 구조

2. 구현 기능 목록

3. 테스트 케이스 목록

4. 테스트 결과

5. 느낀점

   5.1. 드디어 jest로 단위 테스트를 적용하다

   5.2. 오늘도 관심사 분리하기

 

GitHub - hyzzzzy/javascript-racingcar-6

Contribute to hyzzzzy/javascript-racingcar-6 development by creating an account on GitHub.

github.com

🏎️ 자동차 경주 코드 구조


1.1 게임 시작

  • 경주할 N대의 자동차 이름 입력
  • 이름 유효성 검사
  • 시도할 횟수 입력
  • 횟수 유효성 검사

1.2. 게임 진행

  • 1대마다 랜덤값을 부여
  • 랜덤값이 4이상이면 전진
  • N대의 결과를 출력
  • 시도할 횟수만큼 반복

1.3. 게임 종료

  • 가장 많이 전진한 자동차 계산
  • 우승자 출력
    • 여러 대 가능

1.4. 폴더 구조

__tests__
 ┣ ApplicationTest.js
 ┣ CarRaceTest.js
 ┣ CarTest.js
 ┣ InputTest.js
 ┣ StringTest.js
 ┗ UtilTest.js
src
 ┣ domain
 ┃ ┣ Car.js
 ┃ ┗ CarRace.js
 ┣ utils
 ┃ ┣ consoleOperations.js
 ┃ ┣ index.js
 ┃ ┣ numberOperations.js
 ┃ ┗ validation.js
 ┣ App.js
 ┣ constants.js
 ┗ index.js

🏎️ 구현 기능 목록


  • 입력 함수
  • 출력 함수
  • 입력한 이름 유효성 검사 함수
    • 쉼표(,)를 기준으로 2개 이상의 이름이 작성되었는지?
    • 각 이름이 1이상 5이하의 글자 수를 가졌는지?
    • 중복된 이름이 없는지?
  • 입력한 횟수 유효성 검사 함수
    • 숫자로 이루어졌는지?
    • 1이상의 숫자를 입력했는지?
  • 랜덤값 부여 함수
    • 0 ~ 9 사이의 랜덤값 지정
  • 랜덤값 판별 함수
    • 0 ~ 9 사이의 랜덤값 중 4이상이 나왔는지 판별
  • 판정 함수
    • 각 자동차마다 나온 랜덤값에 따라 판정
    • 4이상의 랜덤값이라면 전진횟수 증가
  • 출력할 판정 결과 함수
    • ${이름} : - 형식으로 출력
    • `` 는 전진한 횟수만큼 출력
    • 마지막 공백 라인 추가
  • 우승자 계산 함수
    • 가장 많이 전진한 자동차 이름 계산
  • 출력할 우승자 결과 함수
    • 한 명일 경우, 최종 우승자 : ${이름} 형식으로 출력
    • 여러 명일 경우, 최종 우승자 : ${이름}, ${이름} 형식으로 출력

 

🏎️ 테스트 케이스 목록


3.1 게임 시작

  • 경주할 N대의 자동차 이름 입력
    • 공백만 있다면 예외 처리되어야 한다.
    • 2개 미만의 이름이 있다면 예외 처리되어야 한다.
    • 1자 미만인 이름이 있다면 예외 처리되어야 한다.
    • 5자 초과인 이름이 있다면 예외 처리되어야 한다.
    • 중복된 이름이 있다면 예외 처리되어야 한다.
  • 시도할 횟수 입력
    • 숫자로만 이루어진 값이 아니라면 예외 처리되어야 한다.
    • 1미만의 숫자로 이루어진 값이면 예외 처리되어야 한다.
    • 자연수가 아니라면 예외 처리되어야 한다.
    • Number.MAX_SAFE_INTEGER보다 큰 값은 예외 처리 되어야 한다.

3.2. 게임 진행

  • 랜덤값이 4이상이면 전진
    • 4이상이 나오면 true를 반환해야 한다. 
    • forward 메서드가 실행되면 Car 객체의 position이 1 증가해야 한다.
  • 시도할 횟수만큼 반복
    • 시도할 횟수가 0 미만이면 false를 반환해야 한다.

3.3. 게임 종료

  • 가장 많이 전진한 자동차 계산
    • 가장 많이 전진한 우승자 배열을 반환해야 한다. 

🏎️ 테스트 결과


직접 작성한 테스트 13개..뿌듯

🏎️ 느낀점


드디어 jest로 단위 테스트를 적용하다

처음으로 제대로 테스트 코드를 공부하고 작성했다. 그동안 엘리스 부트 캠프에서 팀 프로젝트를 했었을 때, 테스트 코드를 작성하는 것이 얼마나 중요한 것인지 깨달았다. 시간이 촉박한 프로젝트들이었어서 기능 개발이 우선이었고 일주일마다 혹은 매일 배포를 하고 QA 과정을 거치면서 테스트를 수동적으로 진행했었다. 수동적으로 진행하는 것이 비용이 크기도 하고 미쳐 발견 못하는 에러 상황이 있을 수도 있다는 점에서 테스트 코드에 대한 필요성은 느꼈지만 이미 도입하기에는 시간이 너무 부족한 상황이어서 적용하지 못했었다.

 

이번 우테코 과제만큼은 요구 사항에 있기도 하고 테스트를 꼭 작성해보기 위해 가장 먼저 고민했던 건 어떤 테스트 종류들이 있는 지 파악하고 이번 과제에선 어떤 테스트가 적용하기 괜찮을 지 판단하는 것이었다. 여러 종류의 테스트 중 가장 작은 단위의 함수나 메서드를 테스트 하는 것이 적합했고 단위 테스트를 채택하여 테스트 케이스를 작성했다.

테스트 케이스를 작성해보니 부족한 예외 처리를 찾을 수 있었다. 처음부터 설계를 조금 더 명확하게 하면 좋았었겠지만 테스트 케이스를 작성해서 좀 더 견고하게 기능을 구현할 수 있게 되어 좋은 경험이 되었다고 생각한다.

 

또한, 테스트 코드를 작성해보니 중간에 리팩토링 해야 할 부분도 찾게 되는 경험도 할 수 있었다. 예를 들어 숫자 관련 유틸 함수를 필요한 CarRace 클래스에서 사용하게 되니 전부 클래스 안 메서드로 정의하였는데 생각해보면 클래스 안에 있는 메서드보다 독립적인 유틸 함수로 가져가는 것이 관심사 분리가 되기도 하고 그로 인해 유틸 함수 자체로도 별도의 테스트를 진행할 수 있을 것 같다는 생각에 리팩토링을 진행하게 되었다.

 

아래는 작성한 InputTest.js 일부 테스트 코드이다. 아래와 같은 걸 신경써서 작성했다.

  • describe() 테스트 명은 어떤 테스트를 하는 것인지 명확하게 작성한다.
  • test()에 작성한 문구는 ~ should 의 의미를 담은 형태로 작성한다.
  • 각각의 테스트는 독립적이며 서로 의존해서는 안된다. 

예외 처리되어야 할 값을 지정하고 실제 코드에서 해당하는 에러 문구를 던지는 지 확인하는 테스트코드로 작성해보았다.

describe('자동차 경주 횟수 테스트', () => {
  test('숫자로만 이루어진 값이 아니라면 예외 처리되어야 한다.', () => {
    const names = '12a';

    expect(() => { 
      getValidInputNumber(names);
    }).toThrow(NOT_NUMBER);
  });

  test('1미만의 숫자로 이루어진 값이면 예외 처리되어야 한다.', () => {
    const names = '0';

    expect(() => { 
      getValidInputNumber(names);
    }).toThrow(NOT_RANGE);
  });

  test('자연수가 아니라면 예외 처리되어야 한다.', () => {
    const names = '3.5';

    expect(() => { 
      getValidInputNumber(names);
    }).toThrow(NOT_NATURAL_NUMBER);
  });

  test('Number.MAX_SAFE_INTEGER보다 큰 값은 예외 처리 되어야 한다.', () => {
    const names = String(Number.MAX_SAFE_INTEGER + 1);

    expect(() => { 
      getValidInputNumber(names);
    }).toThrow(NOT_SAFE_INTEGER);
  });
});

이번 경험을 통해 테스트 코드의 이점을 직접 체감할 수 있는 뜻 깊은 경험이 되었다. 이 과정이 익숙해진다면 TDD 방법론도 적용해서 설계 후 기능 구현보다 테스트 코드 작성을 먼저 진행해보고 싶다.

오늘도 관심사 분리하기

이번 과제는 “어쩌다 보니 점점 MVC 패턴에 맞춰지고 있다” 라고 말할 수 있을 것 같다. 학부 때부터 MVC 패턴에 대해 익히 들어왔지만 최근에 자바스크립트로 프로젝트를 해왔었을 때는 해당 디자인 패턴을 적용한 적이 없어서 잊혀졌을 찰나에 다시 MVC 패턴을 공부하게 되었다. 저번 주, 이번 주 과제 자체가 요구 사항이 복잡한 편이 아니어서 “굳이 디자인 패턴을 명확하게 지켜가며 코드를 짜야 하나?” 하는 생각도 있었다. 하지만 코드의 확장성 면에서 혹은 나중에 프로젝트 규모가 더 커지게 된다면 처음부터 관심사 분리와 코드의 결합도를 낮춰질 수 있도록 코드를 짜는 것이 적용하지 않는 것보단 확연히 이점이 많다.

물론 이번 코드들이 model, view, controller를 완벽하게 나눠서 분리했다고는 할 수 없다. 아직은  MVC와는 거리가 많이 멀지만 정답이 없는 과제이기도 하고 공부해서 관심사 분리를 적절히 하는 것만으로도 도움이 많이 되는 시간이었다.