Front-End에서 BDD 간단 작성 방법

dev-won·2023년 4월 14일
2
post-thumbnail

BDD / 행동 주도 개발

front-end에서 TDD로 테스트 코드를 작성하면서 많은 고민을 했다.

  • 무슨 기준으로 작성해야하나?
  • 그냥 단순히 렌더링만 하는건데 테스트해야하나?

위 질문에 대한 궁금증을 해결하기 위해 검색하다가 BDD에 대해 알게 되었고, 가장 정답에 가까운 느낌을 받았다.

BDD란?

BDD(Behavior Driven Development)는 행동 주도 개발하는 방법이다.

즉, 프론트엔드에서는 사용자가 웹 페이지에서 버튼 클릭, 입력, 드래그 등 다양한 동작을 수행하고 난 후, 웹 페이지의 상태를 테스트 케이스로 작성하는 것이라고 생각한다.

어떻게 작성을 해야하나?

테스트 코드를 작성하는 방법은 자유지만, BDD에서는 기본적으로 템플릿이있다.

GIVEN ( 처음 상태 )
WHEN ( 결과를 만들기 위한 행위 )
THEN ( 결과 )

위 템플릿은 기본적으로 BDD 테스트 코드를 쉽게 작성하기 위한 템플릿일 뿐!! 꼭 지켜야한다고 생각하지 않고 해외 개발자들도 그렇게 말하고 있다.

BDD 예시

첫번째 ) InputText 컴포넌트 렌더링에 대한 BDD 테스트 케이스

  1. InputText.test.jsx를 작성한다.
  test('InputText 컴포넌트가 렌더링 되어야한다.', () => {
    //GIVEN
    render(<InputText />);

    //WHEN

    //THEN
    expect(screen.getByRole('textbox')).toBeInTheDocument();
  });

  1. InputText.jsx를 작성한다.
export const InputText = () => {
  return <input type="text" />;
};

위 테스트 케이스는 특별한 행위WHEN에 대한 코드없이 쉽게 결과를 만들 수 있기 때문에 WHEN을 작성하지 않았다. BDD 템플릿은 그냥 템플릿일 뿐 무조건 지키지 않아도 된다.

두번째 ) InputText 컴포넌트에 데이터 입력에 대한 테스트 케이스

  1. InputText.test.jsx를 작성한다.
  test('InputText에 데이터를 입력하면 value값이 변경이 되어야한다.', () => {
    //GIVEN
    render(<InputText />);

    //WHEN

    //THEN
	expect(screen.getByRole('textbox'))
  });

  1. 렌더링 에러를 해결하기 위해 InputText.jsx를 작성한다.
export const InputText = () => {
  return <input type="text" />;
};

  1. InputText의 테스트 시나리오에 대한 WHEN , THEN 작성
  test('InputText에 데이터를 입력하면 value값이 변경이 되어야한다.', () => {
    //GIVEN
    render(<InputText />);
    const inputBox = screen.getByRole('textbox');

    //WHEN
    fireEvent.change(inputBox, { target: { value: 'BDD테스트' } });

    //THEN
    expect(screen.getByRole('textbox')).toHaveValue('BDD테스트');
  });

input Tag 에 데이터를 입력하면 Value에 입력되기 때문에 추가적으로 코드를 작성하지 않아도 된다. 그렇다면 Custom Input Compoent를 예시로 들어보겠다.

세번째 ) Custom Input 컴포넌트에서 props로 value, onChange가 사용될 경우

  1. InputText.test.jsx를 작성한다.
  test('Custom InputText에 데이터를 입력하면 value값이 변경이 되어고, 변경된 데이터가 onChange로 callback 함수로 데이터를 받는다', () => {
    const handleChange = jest.fn();

    //GIVEN
    render(<InputText value="초기 데이터" onChange={handleChange} />);

    //WHEN

    //THEN
    expect(screen.getByRole('textbox'));
  });

  1. 렌더링 에러를 해결하기 위해 InputText.jsx를 작성한다.
export const InputText = (props: InputTextProps) => {
	return <input type="text" />;
};

  1. InputText의 테스트 시나리오에 대한 WHEN , THEN 작성
test('Custom InputText에 데이터를 입력하면 value값이 변경이 되고, 변경된 데이터가 onChange로 callback 함수로 데이터를 반환한다.', () => {
    const handleChange = jest.fn();

    //GIVEN
    render(<InputText value="초기 데이터" onChange={handleChange} />);
    const inputBox = screen.getByRole('textbox');
	expect(inputBox).toHaveValue('초기 데이터');

    //WHEN
    fireEvent.change(inputBox, { target: { value: 'BDD테스트' } });

    //THEN
    expect(handleChange).toHaveBeenCalledTimes(1);
    expect(handleChange).toHaveBeenCalledWith('BDD테스트');
  });

  1. WHEN , THEN에 대한 InputText 컴포넌트 작성
export const InputText = (props) => {
  return (
    <input
      type="text"
      value={props.value}
      onChange={(e) => props.onChange(e.target.value)}
    />
  );
};

위 예제 처럼 테스트 코드를 먼저 작성하고, 테스트 코드로 인해 발생한 오류를 최소한의 코드로 해결하기를 반복하며 테스트 시나리오를 작성한다.

어찌보면 TDD라고 생각할 수 있지만, BDD는 TDD와 많이 다르지 않다. 오히려 BDD는 추상적인 TDD를 구체화한 개발 방법론이라고 생각하면 될 거 같다.

마무리

이것 말고도 행위에 대한 css style 변화에 대한 테스트 코드도 작성할 수 있고, 렌더링시 server로 부터 data fetch 후 화면의 상태 등... BDD를 알고 나서 언제 어떨 때 테스트 코드를 작성해야 할지 명확해졌다.

  • 무슨 기준으로 작성해야하나?
    ㄴ 클라이언트의 행동(행위)의 결과를 테스트

  • 그냥 단순히 렌더링만 하는건데 테스트해야하나?
    ㄴ 정말 많이 고민했다.
    ㄴ 결론적으로 해야한다.
    ㄴ 그러면 예시로 어디서 해야할까? 약관조금이라도 변경되면 안되는분이라면 무조건 해야한다.

참고 자료
https://medium.com/@paulallies/bdd-style-of-tdd-with-jest-react-and-react-hooks-9eb68916efe8
https://medium.com/javascript-scene/behavior-driven-development-bdd-and-functional-testing-62084ad7f1f2

profile
화이팅

0개의 댓글