본문 바로가기

TIL(Today i learned)

[TIL - 2022.10.02] 아주 조금씩 익숙해지는 테스트코드 |

1.HTTP 글쓰기 : 

아침에 일어나서 1시간 정도 자료를 조사하고 글을 썼다. 오늘 조사하면서 글을 쓴 내용은 http/1.1버전에 대한 내용이었다. 이 버전의 내용 중에서도 특히 keep-alive에 대한 기능을 조사하고 글을 썼다. 1.0과 1.1의 중대한 차이점을 이야기하자면 바로 이 keep-alive 기능이라고 할 수 있을 것이다. 

 

 

2.TagInput 옮기고, test코드 작성하기 : 

어제 TagInput을 기존의 코드베이스에 리베이스 하다가 에러가 생겼다. 그래서 그대로 TagInput 코드를 복사해서 기존의 코드베이스에 붙였다. 다행히 큰 의존성이 없었기 때문에 한번에 복사가 되고 정상 동작했다. 

그 다음은 테스트 코드를 작성했다. 역시나 테스트 코드 작성은 쉽지 않았다. 

  describe('태그를 클릭하면', () => {
    it('태그가 지워진다.', async () => {
      const tags = { values: ['태그1', '태그2'] };
      const tagInput = renderTagInput(tags);
      const tag1 = tagInput.getByText('태그1');
      expect(tag1).toBeInTheDocument();

      fireEvent.click(tag1);

      const removedTag = await tagInput.queryByText('태그1');

      expect(removedTag).not.toBeInTheDocument();
    });
  });

이렇게 테스트 코드를 작성했었다. 음 그런데, 이게 TagInput이 제대로 동작하기 위해서는 부모에서 onChange 이벤트를 내려줘야한다. 이 onChange 이벤트는 useState를 사용한다. 그러면 이것이 제대로 동작하기 위해서는 test할 때도 useState를 내려줘야 하는 것일까? 

 

https://stackoverflow.com/questions/67155636/how-to-test-side-effect-when-state-hook-is-passed-to-a-child-component-using-rea

 

How to test side-effect when state hook is passed to a child component using React and jest?

I want to test a child component, but it relies on state (hooks) from the parent. the child receives isModalOpen and setIsModalOpen as properties. Each time isModalOpen changes, the useEffect inside

stackoverflow.com

이 글에서 useState를 부모에서 내려준 자식 컴포넌트를 테스트할 때 어떻게 하면 되는지 알려주고 있다. 그래서 나도 이 글을 참고해서 다음과 같이 테스트를 작성했더니 통과했다. 

 

  describe('태그를 클릭하면', () => {
    it('태그가 지워진다.', async () => {
      const tags = { values: ['태그1', '태그2'] };
      const tagInput = renderTagInput(tags);
      const tag1 = tagInput.getByText('태그1');

      expect(tag1).toBeInTheDocument();
      fireEvent.click(tag1);
      expect(onChange).toBeCalledWith(['태그2']);
    });
  });

tag1을 클릭해서 지워지면, tag2만 인자로 받아서 onChange 이벤트가 발생할 것이다. 그렇게해서 테스트를 했더니 통과했다. 

 

 

검색을 하다가 hook 테스트를 도와주는 라이브러리를 발견했다. 

https://react-hooks-testing-library.com/

 

Introduction

Simple and complete React hooks testing utilities that encourage good testing practices.

react-hooks-testing-library.com

근데 아마도 이 라이브러리는 커스텀 훅을 테스트하려는 경우 사용할 수 있는 것 같다. 

 

 

3.pr 템플릿을 찾아봤다 : 

pr을 올릴 때, 리뷰해주는 사람이 조금 더 알아보기 쉽게 만들 수는 없을까 고민이 들었다. 그래서 이것저것 검색을 해봤다. 

검색하면서 느낀 점. 우선 pr의 크기가 작아야 한다. 가능하면 pr의 크기를 1000 줄이상 넘기지 않도록 한다. 뱅크샐러드가 1000 줄 이상 넘기지 않는 pr 만들기 정책을 펼치고 있다고 한다.  또한 이 pr이 어떤 내용을 담고 있는지 리뷰어가 한눈에 알아볼 수 있도록 해야한다. 

 

https://medium.com/prnd/%ED%97%A4%EC%9D%B4%EB%94%9C%EB%9F%AC-%EA%B0%9C%EB%B0%9C%ED%8C%80-%EB%AA%A8%EB%91%90%EA%B0%80-%ED%96%89%EB%B3%B5%ED%95%9C-%EA%B0%9C%EB%B0%9C-pr%EA%B4%80%EB%A6%AC-%EB%B0%A9%EB%B2%95-7%EA%B0%80%EC%A7%80-1d4cd5d091f0

 

헤이딜러 개발팀 모두가 행복한 개발/PR관리 방법 7가지

헤이딜러에서 팀으로 개발하면서 효율적으로 코딩하고 PR을 만들고 이 PR들을 관리하는 방식에 대해서 소개합니다.

medium.com

 

내가 검색을 하면서 주로 초점을 맞췄던 부분은 템플릿을 무엇으로 구성할 것인가이다. 몇가지 예시들을 찾아봤다.

## 개요
## 작업사항
## 변경로직
### 변경전
### 변경후
## 사용방법
## 기타
무슨 이유로 코드를 변경했는지
어떤 위험이나 장애가 발견되었는지
어떤 부분에 리뷰어가 집중하면 좋을지
관련 스크린샷
테스트 계획 또는 완료 사항
What is the feature?
How you implemented the solution?
Does it impact any other area of the project?
Any changes in the UI (Screenshots)?
How to test the feature (A test scenario or any new setup)?

음 이렇게 저렇게 찾아보다가 나는 이렇게 템플릿을 정하기로 했다. 

 

## 개요 
## 작업사항 
## 스크린샷 
## 테스트 
 ### 테스트 시나리오 
 ### 테스트코드 여부 

대충 아래와 같이 pr 템플릿을 구성했다. 

 

지금... pr 코드 길이가 10000줄인데ㅜㅜㅜ 아무래도 리뷰어에게 너무 했다는 생각이 든다... 많이 반성하는 중이다. 다음부터는 가능하면 1000줄 이상을 넘기지 않는 선에서 코드를 작성하고 pr을 올려야 할 것 같다. 반성하자!

 

 

4.onChange가 제대로 작동하지 않던 테스트 코드 : 

 

나와 비슷한 문제를 겪는 사람을 발견.

https://github.com/testing-library/react-testing-library/issues/637

 

onChange event not firing · Issue #637 · testing-library/react-testing-library

@testing-library/react version: ^9.3.2 react version: ^16.13.1 node version: v8.12.0 npm (or yarn) version: 6.4.1 Relevant code or config: Input.js import React, { useState } from 'react' f...

github.com

kentcdodds 가 userEvent를 소개해주었다. 몇일전에 찾게 되었던 라이브러리인데, 이게 해결책이 될지도 모르겠다. 한번 사용해보자. 

 

그래도 안된다ㅡㅡ

  it('인풋에 입력하면 onChange가 호출된다.', () => {
    const user = userEvent.setup();
    renderTitleInput();
    const placeholder = '제목을 입력하세요.';
    const title = '제목';
    const titleInput = screen.getByPlaceholderText(
      placeholder,
    ) as HTMLInputElement;
    expect(titleInput).toBeInTheDocument();
    screen.debug();

    user.type(titleInput, title);

    expect(titleInput.value).toBe('제목');
  });

멘토님이 알려주신 방법대로 하니 해결. 문제는 내가 change할 때 target 지정하는 부분을 잘못했다는 것이다. 

  it('인풋에 입력하면 onChange가 호출된다.', () => {
    renderTitleInput();
    const placeholder = '제목을 입력하세요.';
    const title = '제목';
    const titleInput = screen.getByPlaceholderText(placeholder);
    expect(titleInput).toBeInTheDocument();

    fireEvent.change(titleInput, {
      target: { value: title },
    });

    expect(onChange).toBeCalled();
  });

기존에는 저 부분을 이렇게 작성하고 있었다. 

    fireEvent.change(titleInput, {
      target: { title },
    });

아마 내가 fireEvent를 어떻게 사용해야하는지에 대한 정확한 이해가 없이 사용했기 때문이지 않을까. fireEvent에 대해서 조금만 찾아보자. 공식문서를 확인해보니, 문서에서도 fireEvent보다는 userEvent를 사용하는 것을 권하고 있다. 

 

아래는 공식문서에서 소개해주는 페이지인데, 여기에 event에 대한 리스트들이 전부다 나열되어 있다. 

https://github.com/testing-library/dom-testing-library/blob/main/src/event-map.js

 

GitHub - testing-library/dom-testing-library: 🐙 Simple and complete DOM testing utilities that encourage good testing practic

🐙 Simple and complete DOM testing utilities that encourage good testing practices. - GitHub - testing-library/dom-testing-library: 🐙 Simple and complete DOM testing utilities that encourage good te...

github.com

fireEvent를 호출할 당시에 target 인자(2번째 인자)에 특정 프로퍼티를 넣어주면, 첫번째 인자에 지정했던 node에 해당 프로퍼티가 할당된다. 

 

 

5.fileupload 테스트하기 : 

https://github.com/testing-library/react-testing-library/issues/93

 

Simulating uploading file · Issue #93 · testing-library/react-testing-library

Is there a way to simulate or fire event to trigger change event on input that is used for uploading files?

github.com

좋은 자료가 있어서 따라해봤는데, 잘 안된다. 

 

  describe('이미지를 선택하면', () => {
    // jest.mock('src/hooks'); NOTE : usePreview 모킹해서 확인하기
    it('preview 이미지가 보여야한다.', async () => {
      renderImageUpload();
      const imageInput = screen.getByTestId('fileinput');
      fireEvent.change(imageInput, {
        target: {
          files: [
            new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' }),
          ],
        },
      });

      const preview = screen.queryByAltText('preview image');
      // expect(preview).toBeInTheDocument();
    });

    it('UploadBox가 사라져야한다.', () => {});
  });

이런식으로 작성했는데, 잘 되지 않는 것 같다. 그리고 빨간줄로 에러가 나타나지는 않는데, 뭔가 문제가 있음을 알려주고 있다. 

이미지를 생성하는 부분에서 뭔가 문제가 있는 것 같다. 

 

6.Slider 만들기 : 

slider를 만들 때 로컬에 있는 JSON 파일을 가져와야 한다. 아래는 로컬 JSON 파일을 nextjs에서 사용하기 위한 방법이다. 

https://www.kindacode.com/article/next-js-reading-and-display-data-from-a-local-json-file/

 

Next.js: Reading and Display Data from a Local JSON File - Kindacode

This short and straight-to-the-point article shows you how to read and display data from a local JSON file in Next.js. This is useful if you want to build a small web app quickly without having to...

www.kindacode.com

 

현재 여기까지 css 작업을 했다. 

아직 남아있는 작업은 많다. 

1) nextjs에서 로컬 JSON 파일 불러오기 

2) 프로그래스바 만들기 

3) 인용구 애니메이션 만들기 - 슬라이드 

4) 인용구에 폰트 입히기