가독성 높은 테스트를 폭속으로 쓴 개인 템플릿

13961 단어 React
다음은 React 구성 요소의 테스트를 폭속으로 작성하는 개인이 따르는 모델을 소개합니다.예제에서는 Jest와 Enzyme를 사용했지만 토론 내용은 이러한 도구에 의존하지 않아야 합니다.
이 글은 이미지와 같은 2단계 로그인 화면을 소재로 테스트하는 것을 고려했다 .

이 구성 요소에 사용자 이름, 암호 및 현재 단계(1단계 또는 2단계)의 상태가 있다고 가정합니다.2단계 사용자가 로그인 단추를 누르면 사용자 이름과 비밀번호를 매개 변수로 호출합니다.구성 요소의 서명은 다음과 같습니다.
LoginForm.js
export default function LoginForm({ onLoginButtonClick }) {/*...*/}

모든 내용을 공장 함수에 밀어넣기


테스트를 작성하기 시작하면 공장 함수를 만들고 구성 요소 불러오기, 모델 함수 만들기 등 다양한 설정을 책임집니다.아날로그 사용자 상호작용의 모든 번거로움을 이 함수에 떠넘기십시오.
LoginForm.test.js
import React from "react";
import { mount } from "enzyme";
import LoginForm from "./LoginForm";

function createTestEnv() {
  // モックの作成
  const onLoginButtonClick = jest.fn();

  // コンポーネントのマウント
  const wrapper = mount(<LoginForm onLoginButtonClick={onLoginButtonClick} />);

  // ユーザインタラクションをシミュレートする便利関数
  function prompt() {
    return wrapper.text();
  }

  function enterUsername(username) {
    wrapper
      .find('input[name="username"]')
      .simulate("change", { target: { value: username } });
  }

  function enterPassword(password) {
    wrapper
      .find('input[name="password"]')
      .simulate("change", { target: { value: password } });
  }

  function clickNext() {
    wrapper.find('[children*="NEXT"]').simulate("click");
  }

  function clickLogin() {
    wrapper.find('[children*="LOGIN"]').simulate("click");
  }

  return {
    onLoginButtonClick,
    wrapper,
    prompt,
    enterUsername,
    enterPassword,
    clickNext,
    clickLogin
  };
}

테스트 주체에서 공장 함수만 호출하면


모든 테스트의 시작 부분에서 정의된 공장 함수를 호출합니다.간단해!
LoginForm.test.js의 후속
describe("LoginForm", () => {
  describe("the first step", () => {
    it("prompts for a username", () => {
      const { prompt } = createTestEnv();
      expect(prompt()).toContain("Enter your username");
    });
  });
  describe("the second step", () => {
    it("prompts for a password", () => {
      const { enterUsername, clickNext, prompt } = createTestEnv();
      enterUsername("alice");
      clickNext();
      expect(prompt()).toContain("Enter your password");
    });
  });
  describe("the onLoginButtonClick callback", () => {
    it("gets called with username and password", () => {
      const {
        enterUsername,
        enterPassword,
        clickNext,
        clickLogin,
        onLoginButtonClick
      } = createTestEnv();
      enterUsername("alice");
      clickNext();
      enterPassword("pAsSwOrD");
      clickLogin();
      expect(onLoginButtonClick).toBeCalledWith({
        username: "alice",
        password: "pAsSwOrD"
      });
    });
  });
});

왜 기꺼이 하지 않겠는가


테스트 본체의 가독성 향상


이 작법에서 좋아하는 것은 번거로운 일을 공장 함수에 넣고 테스트 주체의 가독성을 높이는 것이다.예에서 가장 긴 테스트라도 자연어로 읽을 수 있다.
      enterUsername("alice");
      clickNext();
      enterPassword("pAsSwOrD");
      clickLogin();
      expect(onLoginButtonClick).toBeCalledWith({
        username: "alice",
        password: "pAsSwOrD"
      });

설치 의존 집중


번거로움을 공장 함수에 미루는 두 번째 장점은 의존하는 코드를 한데 모으는 것이다.UI의 테스트로서 흔히'사용자가 볼 수 있는 것을 테스트하는 것'이 이상적이지만 현실적으로 어려운 장면도 있다.예를 들어, "플로피 디스크 아이콘 클릭"을 테스트 코드에 넣으면
wrapper.find('img[src="./icons/floppy-disk-icon.png"]').click();
어쩔 수 없이 이렇게 하다.그러나 여기에 등장한'플로피 아이콘의 파일 이름'은 설치의 상세한 내용임이 분명하다.이런 코드가 테스트 본체에 여러 번 나타나면 아이콘의 파일 형식을 png에서svg로 바꾸는 가벼운 변경만 하면 테스트에 일부 변경이 발생할 수 있다.힘들어.
다른 한편, 실현에 의존하는 코드를 공장 함수에 밀어넣으면 공장 함수 중 하나만 고치면 된다.실현에 의존하는 코드를 한데 모으면 변경의 영향 범위를 최소화할 수 있다.물론 이상적인 것은 의존이 적은 테스트 코드를 실현하는 것이다.

끝내다


나는 최근에 본고에서 소개한 스타일로 React 구성 요소의 테스트를 전문적으로 쓴다.고민의 시간을 줄이고 생산 효율을 높이기 위해서는 이런 규정을 따르는 것이 효과적이라고 생각합니다.세션을 활용하면 인코딩 속도를 한층 높일 수 있다.
아직 이런 양식으로 인한 큰 문제는 나타나지 않았다.그러나 비슷한 예를 잘 보지 못하기 때문에 이런 스타일은 문제가 있지만 내가 눈치채지 못했을 뿐이다.만약 이렇게 생각한다면 반드시 댓글란에서 저에게 통지해 주세요.
이 CodeSandbox에는 구성 요소와 테스트 코드가 포함되어 있습니다.

좋은 웹페이지 즐겨찾기