[React] 벨로퍼트와 함께하는 React Testing - TDD

2023. 1. 5. 14:48·React/실험실
반응형

들어가며

벨로퍼트님의 테스팅 튜토리얼을 공부한 내용을 정리하는 글입니다. 

 

TDD ? 

TDD는 테스트를 통해서 개발을 이끌어나가는 형태의 개발론이다. 

먼저 테스트 코드를 작성하고, 구현을 하는 방식이라고 보면 된다. 

 

TDD에는 3가지 절차가 있다. 

실패 

첫 번째 절차로 실패이다. 말 그대로 실패하는 테스트 케이스를 먼저 만드는 것이다. 

상황에 따라 다르지만, 먼저 구현할 기능부터 하나씩 테스트 케이스를 작성한다. 

 

성공

두 번째 절차로 성공이다. 

앞서 작성한 실패하는 테스트 케이스를 통과시키기 위해서 코드를 작성하는 것을 말한다. 

 

리팩토링 

구현한 코드가 테스트를 통과한다면, 중복되는 코드 또는 개선시킬 방법이 있는 코드를 리팩토링 시킨다. 

리팩토링을 했을 때 테스트 케이스가 성공하면 다른 기능을 다시 첫 번째 절차부터 수행한다. 

 

즉,

실패 => 성공 => 리팩토링 => 실패 => 성공 ... 방식으로 개발하는 것이다. 

 

TDD의 장점 

TDD를 진행하면서 테스트 케이스를 작성할 때 작은 단위로 개발하기 때문에 

테스트 코드가 방대해지지 않고, 코드의 모듈화가 잘 이루어진다. 

 

또, TDD를 통해서 자연스럽게 테스트 커버리지가 높아진다. 

기능을 구현할 때 테스트를 먼저 작성하기 때문에 당연한 결과라고 볼 수 있다. 

테스트 커버리지가 높아진다는 것은 리팩토링이 쉬워지고 유지보수도 쉬워진단는 뜻이다.  

 

TDD 연습해보기

배열이 주어졌을 때 최댓값, 최솟값, 평균, 중앙값, 최빈값을 구하는 함수를 구현해보자! 

벨로퍼트님의 게시글에는 바로 정답이 나오기 때문에 이부분은 해당 코드를 보지 않고 

내가따로 작성해보겠다!

 

최댓값

import { max } from "./stats";

describe("stats", () => {
  test("Max Value : [1, 2, 3] = 3", () => {
    const array = [1, 2, 3];

    expect(max(array)).toBe(3);
  });
});

다음과 같이 작성했다. 

당연히 아직 stats에 아무것도 작성하지 않았기 때문에 max가 없다는 오류가 뜨고, 이제 max를 구현하자!

 

export const max = (array) => {
  const sorting = [...array].sort((a, b) => b - a);

  return sorting[0];
};

sort를 사용해서 내림차순으로 정렬한 배열에서 첫 번째 값을 return한다. 

아~ 주 문제없이 동작하는데, 더 쉬운 방법이 있었다... 

 

export const max = (array) => {
  return Math.max(...array);
};

 

최솟값

import { max, min } from "./stats";

describe("stats", () => {
  const array = [1, 2, 3];

  test("Max Value : [1, 2, 3] = 3", () => {
    expect(max(array)).toBe(3);
  });

  test("Min Value : [1, 2, 3] = 1", () => {
    expect(min(array)).toBe(1);
  });
});

최댓값과 크게 다르지 않다. 

 

export const min = (array) => {
  return Math.min(...array);
};

그리고 난 애송이가 아니다. 

max가 있다면 당연히 min이 있을 것이기 때문에 min을 사용해서 작성했다. 

 

평균값

  test("Average : [1, 2, 3] = 2", () => {
    expect(avg(array)).toBe(2);
  });

평균을 구하는 테스트 케이스를 작성했다. 

 

export const avg = (array) => {
  const sum = array.reduce((prev, curr) => prev + curr, 0);
  return sum / array.length;
};

reduce를 활용해서 풀었다. 

그런데 좀 더 깔끔하게 만드는 방법이 있었다. 

 

export const avg = (array) => {
  return array.reduce((prev, curr, _, { length }) => prev + curr / length, 0);
};

(1 + 2 + 3 ) / 3이 1 / 3 + 2 / 3 + 3 / 3과 똑같다는 사실을 생각안하고 있었다. 

이런 방식으로 해결하면 보다 깔끔하게 만들 수 있다.

 

중앙값

describe("stats", () => {
  // ...

  describe("Median", () => {
    const array1 = [1, 2, 3];
    const array2 = [1, 2, 3, 4];

    test("case 1 : [1, 2, 3] = 2", () => {
      expect(median(array1)).toBe(2);
    });

    test("case 2 : [1, 2, 3, 4] = 2.5", () => {
      expect(median(array2)).toBe(2.5);
    });
  });
});

 

중앙값은 배열의 개수에 따라 구하는 방법이 달라진다. 

배열이 홀수개라면 단순하게 가운데 값인 2가 중앙값이지만,

짝수개라면 2 + 3 / 2 인 2.5가 중앙값이 된다. 

 

그래서 describe 안에 다시 describe으로 케이스를 나눠주었다. 

하지만 test 안에서 describe을 사용할 순 없다.

export const median = (array) => {
  const sorting = [...array].sort((a, b) => a - b);

  const center = Math.floor(sorting.length / 2);

  return center % 2
    ? sorting[center]
    : (sorting[center - 1] + sorting[center]) / 2;
};

 

최빈값 

  describe("Mode", () => {
    const array1 = [1, 2, 2, 2, 3];
    const array2 = [1, 2, 3];
    const array3 = [1, 2, 2, 3, 3];

    test("case 1 : [1, 2, 2, 2, 3] = 2", () => {
      expect(mode(array1)).toBe(2);
    });
    test("case 2 : [1, 2, 3]", () => {
      expect(mode(array2)).toBe(null);
    });
    test("case 3 : [1, 2, 2, 3, 3] = [2, 3]", () => {
      expect(mode(array3)).toEqual([2, 3]);
    });
  });

최빈값은 배열에서 빈도가 가장 높은 값을 나타낸다. 이때 상황에 따라 결과가 3가지로 나눠진다. 

 

1. 주어진 값 중 가장 자주 나타난 값이 하나인 경우 가장 높은 값이 최빈값이다. 

[1, 2, 2, 2, 3] => 2

 

2. 모든 값이 빈도가 같은 경우 최빈값은 없다. 

[1, 2, 3] => null

 

3. 빈도가 같은 값이 여러개인 경우, 모두 최빈값이다. 

[1, 2, 2, 3, 3] => [2, 3]

 

export const mode = (array) => {
  const frequency = new Map();
  const set = new Set(array);

  array.forEach((value) => {
    frequency.set(value, frequency.get(value) ? frequency.get(value) + 1 : 1);
  });

  const maxValue = Math.max(...frequency.values());

  const result = [...frequency.keys()].filter(
    (number) => frequency.get(number) === maxValue
  );

  if (result.length === set.size) return null;
  else if (result.length === 1) return result[0];
  else return result;
};

 map과 set을 사용해서 문제를 해결했다. 

여기서 forEach를 대신해서 reduce를 사용하면 더 깔끔하게 해결이 가능하다. 

 

export const mode = (array) => {
  const set = new Set(array);
  const frequency = array.reduce(
    (acc, cur) => acc.set(cur, acc.get(cur) ? acc.get(cur) + 1 : 1),
    new Map()
  );

  const maxValue = Math.max(...frequency.values());

  const result = [...frequency.keys()].filter(
    (number) => frequency.get(number) === maxValue
  );

  if (result.length === set.size) return null;
  else if (result.length === 1) return result[0];
  else return result;
};

정리 

TDD를 사용했을 때 확실히 테스트 코드가 존재하기 때문에 리팩토링이 편하다. 

하지만 아직 이것을 프론트엔드에서 어떤 방식으로 사용하면 좋을지는 감이 잡히지 않는다. 

 

추후, 공부할 내용이 기대된다!

반응형
저작자표시 비영리 변경금지 (새창열림)

'React > 실험실' 카테고리의 다른 글

[React] 벨로퍼트와 함께하는 React Testing - Todo List  (0) 2023.01.07
[React] 벨로퍼트와 함께하는 React Testing - react-testing-library  (0) 2023.01.06
[React] 성능 개선기  (0) 2022.12.21
[React] form 태그를 사용해서 value 가져오기 feat. TypeScript  (0) 2022.12.18
[React] React-Query - useQuery  (0) 2022.12.13
'React/실험실' 카테고리의 다른 글
  • [React] 벨로퍼트와 함께하는 React Testing - Todo List
  • [React] 벨로퍼트와 함께하는 React Testing - react-testing-library
  • [React] 성능 개선기
  • [React] form 태그를 사용해서 value 가져오기 feat. TypeScript
잉여개발자
잉여개발자
풀스택 개발자를 목표로 잉여롭게 개발 공부도 하면서 다양한 취미 생활도 즐기고 있는 잉여 개발자입니다.
  • 잉여개발자
    잉여로운 개발일지
    잉여개발자
    • 분류 전체보기 (789)
      • 개발정보 (36)
      • 개발환경 (7)
      • 개발생활 (19)
      • React (141)
        • 이론 (23)
        • 기능 (12)
        • 실험실 (88)
        • 버그 (6)
        • 패스트캠퍼스 (9)
        • Npm (3)
      • React Native (28)
        • 공통 (6)
        • TypeScript (3)
        • JavaScript (18)
        • 버그 (1)
      • Next.js (30)
        • 이론 (13)
        • 실험실 (13)
        • 버그 (3)
      • Web (35)
      • 알고리즘 (202)
        • 풀이 힌트 (39)
      • JavaScript (47)
      • TypeScript (29)
        • 기초 (27)
        • 실험실 (2)
      • Node.js (13)
        • 이론 (0)
        • 기능 (3)
        • 실험실 (9)
        • 버그 (1)
      • 도커 (4)
      • CCNA (22)
        • 이론 (4)
        • 문제 (18)
      • 취미생활 (167)
        • 잉여로운 칵테일 (2)
        • 잉여의 식물키우기 (130)
        • 잉여로운 여행기 (11)
        • 잉여의 제2외국어 (21)
        • 잉여로운 책장 (2)
      • Java (1)
        • Java의 정석 (1)
      • 꿀팁 공유 (3)
  • 태그

    redux
    javascript
    프로그래머스
    webpack
    다이소
    typescript
    영어독학
    영어회화
    네트워크
    바질 키우기
    자바스크립트
    타일러영어
    next.js
    Babel
    바질
    ChatGPT
    CSS
    CCNA
    리얼클래스
    react
    식물
    Node.js
    네이버 부스트캠프
    타입스크립트
    Docker
    덤프
    리얼학습일기
    ReactNative
    리액트
    알고리즘
  • hELLO· Designed By정상우.v4.10.1
잉여개발자
[React] 벨로퍼트와 함께하는 React Testing - TDD
상단으로

티스토리툴바