Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
env: {
browser: true,
es6: true,
node: true,
jest: true,
},
parserOptions: {
ecmaVersion: 2022,
},
extends: ['airbnb-base', 'plugin:prettier/recommended', 'prettier'],
rules: {
'max-depth': ['error', 2],
'max-lines-per-function': ['error', 16],
'operator-linebreak': ['error', 'before'],
'no-unused-expressions': ['error', { allowTernary: true }],
},
};
12 changes: 12 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always",
"proseWrap": "never",
"endOfLine": "auto"
}
80 changes: 68 additions & 12 deletions __tests__/ApplicationTest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import App from "../src/App.js";
import { MissionUtils } from "@woowacourse/mission-utils";
import App from '../src/App.js';
import { MissionUtils } from '@woowacourse/mission-utils';
import Car from '../src/Car.js';

const mockQuestions = (inputs) => {
MissionUtils.Console.readLineAsync = jest.fn();
Expand All @@ -18,18 +19,18 @@ const mockRandoms = (numbers) => {
};

const getLogSpy = () => {
const logSpy = jest.spyOn(MissionUtils.Console, "print");
const logSpy = jest.spyOn(MissionUtils.Console, 'print');
logSpy.mockClear();
return logSpy;
};

describe("자동차 경주 게임", () => {
test("전진-정지", async () => {
describe('자동차 경주 게임', () => {
test('전진-정지', async () => {
// given
const MOVING_FORWARD = 4;
const STOP = 3;
const inputs = ["pobi,woni", "1"];
const outputs = ["pobi : -"];
const inputs = ['pobi,woni', '1'];
const outputs = ['pobi : -'];
const randoms = [MOVING_FORWARD, STOP];
const logSpy = getLogSpy();

Expand All @@ -46,17 +47,72 @@ describe("자동차 경주 게임", () => {
});
});

test.each([
[["pobi,javaji"]],
[["pobi,eastjun"]]
])("이름에 대한 예외 처리", async (inputs) => {
test('우승자가 여러 명', async () => {
// given
const MOVING_FORWARD = 4;
const inputs = ['pobi,woni', '1'];
const output = 'pobi, woni';
const randoms = [MOVING_FORWARD, MOVING_FORWARD];
const logSpy = getLogSpy();

mockQuestions(inputs);
mockRandoms([...randoms]);

// when
const app = new App();
await app.play();

// then
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(output));
});

test.each([[['pobi,javaji']], [['pobi,eastjun']]])('이름에 대한 예외 처리', async (inputs) => {
// given
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.play()).rejects.toThrow("[ERROR]");
await expect(app.play()).rejects.toThrow('[ERROR]');
});

test('자동차가 0대일 때 예외 처리', async () => {
// given
mockQuestions(['']);

// when
const app = new App();

// then
await expect(app.play()).rejects.toThrow('[ERROR]');
});

test.each([[['banana,cherry,banana']], [['orange,orange,apple,cake']]])(
'자동차의 이름 중복 예외 처리',
async (inputs) => {
// given
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.play()).rejects.toThrow('[ERROR]');
},
);

test.each([[['banana,cherry,banana']], [['orange,orange,apple,cake']]])(
'실행 횟수 타입 예외 처리',
async (inputs) => {
// given
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.play()).rejects.toThrow('[ERROR]');
},
);
});
40 changes: 40 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 🚗 자동차 경주 게임
> 우아한테크코스 프리코스 2주차

## ✨ 기능 명세
### 게임 플로우
- ✅ 경주할 자동차 이름 입력 안내 텍스트 출력
- ✅ 사용자로부터 경주할 자동차 이름 입력 받기
- ✅ 시도할 횟수 입력 질문 텍스트 출력
- ✅ 사용자로부터 시도할 횟수 입력 받기
- ✅ 각 차수 별 실행 결과 출력
- ✅ 자동차 별로 0에서 9사이의 무작위 값 생성
- ✅ 무작위 값이 4 이상인 경우
- ✅ 전진
- ✅ 무작위 값이 4 미만인 경우
- ✅ 멈춤
- ✅ 최종 우승자 출력
- ✅ 여러 명일 때 쉼표로 구분


### 에러 처리
- ✅ 경주 자동차 이름 입력
- ✅ 이름이 5자 이하인지 확인
- ✅ 자동차가 0대인 경우
- ✅ 자동차의 이름이 각각 다른 지 확인
- ✅ 이동하는 횟수 입력
- ✅ 입력 값이 숫자인지 확인


### 기타
- ✅ 코드 컨벤션 체크
- ✅ 코드 리팩토링
- ✅ indent depth 2까지
- ✅ 테스트 코드 추가

## ✨ 느낀 점 (소감)
`indent는 최대 2`라는 조건을 맞추기 위해서 최대한 함수를 분리했다. 함수를 많이 분리하려고 하다 보니 함수명을 명확하게 짓는 것이 중요하다는 것을 알게 되었다. 특히 이번 과제에서는 `get` 을 함수명 앞에 붙이는 것이 맞는지에 고민을 많이 했다. 저번 과제에서는 사용자에게 입력을 받을 때마다 `get${역할}` 로 함수명을 작성했는데, 이번 과제를 하며 `get`을 쓴다는 것은 해당 함수를 사용해 데이터를 반환할 때만 쓰는 것이 코드의 흐름을 파악할 때 더 좋다는 것을 깨달았다. 또한, 확실히 여러 개의 함수로 나누어 로직을 짜다 보니 에러가 났을 때 디버깅하기 쉬웠다.

테스팅 라이브러리인 Jest를 처음 사용해보았는데, 아직은 다 이해하지 못해서 거의 에러 처리 관련 테스트만 작성하였다. Jest 사용 전에는 에러 처리 테스트를 위해 여러 번 실행하여 직접 에러가 나도록 플로우를 진행했는데, Jest를 사용하면 직접 실행을 해보지 않아도 결과를 알 수 있어서 좋았다.

다음 과제에서는 기능 단위의 테스트도 더 많이 작성해보고 싶다.
Loading