테스트란? (feat. TDD, BDD)

Nine·2022년 2월 24일
0

Test

목록 보기
1/2

우아한 테크 코스에서 배운 내용을 정리해봤습니다.

😀테스트?

  • 제품의 품질을 확인하고 보장하기 위한 작업이예요.

  • 이걸 코드를 써서 하면 테스트 코드 입니다. → 자동화된 테스트!

😀TDD란?

  • Test Driven Development

  • 테스트를 먼저 작성하고 그 후 실제 코드를 작성하는 방법입니다.

TDD 사이클

Test fails → Test passes → Refactor 무한 반복

  • 일단 실패하는 코드를 작성합니다.

  • 테스트가 성공하도록 코딩을 진행합니다.

  • 빠르게 파란불(pass)을 보고 리팩토링을 진행합니다.

😀왜 테스트를 해야할까요?

개발을 하고 나면 어떤 방법으로든 테스트는 해봐야 해요.

- 기대했던 요구 사항들이 제대로 되나?
  • 이후 유지 보수 할 때에는 변동되는 요구 사항에 대응하면서 동시에 안정적인 품질을 유지해야 해요.
    - 변동되는 요구 사항이 뭔데요?
        - 새 기능
        - 기존 기능 변경
        - 기능 그대론데 기술적 변경
        - 기능 그대론데 디자인 변경
        - 기타 등등
  • 전문적인 QA 가 팀에 있을 수도 있어요.
    • 그래도 개발자로서 QA단계까지 가기 전에 개발 / 수정한 부분에 대한 검증은 기본적으로 해야할 책임이 있겠죠?
    • (그래도 QA가 있으시다면... 해야하나?ㅎㅎ;;)

피드백이 필요해 1) 작동하는 + 깔끔한 코드

clean code that works

1) 한 번에 좋은 코드를 쓰기는 힘드니

2) 일단 쓰고

3) 리팩토링

-> 작동하는 깔끔한 코드 완성!

피드백이 필요해 2) 두려움 → 용기

  • 리팩토링 : 겉으로 보이는 동작과 기능은 그대로, 내부 구현만 개선

  • 리팩토링을 해도 기능이 그대로 잘 동작하는 것을 어떻게 보장할 수 있을까?

  • 두려움은 여러분을 까다롭게 만듭니다!

테스트가 있다면 리팩토링이 두렵지 않을 수 있어요.

테스트 종류와 범위

  • E2E - Integration - Unit

  • 각 각은 아래 글을 읽으면서 이해가 될 거예요.

😀웹 프론트엔드에서 주로 하는 일

  • Network / 외부 어플리케이션 서버,외부 API

  • 상태 / 도메인 데이터, 비즈니스 로직

  • UI / 브라우저 렌더링, 사용자 인터렉션

테스트 대상 범위

E2E는 처음부터 끝까지 전부 왔다갔다 테스트입니다. (End to End)

  • UI -> 상태 -> Network -> 상태 -> UI
// 사용자의 시나리오를 그대로 작성하면 되기 때문에 직관적이고 쉽게 작성할 수 있어요.

it("5자보다 긴 자동차 이름을 입력하면 에러 메세지",()=>{
	// DOM 구조를 가져와서 입력과 클릭 같은 유저 행위르 작성합니다.
	// 결과값이 일치하는지 확인해요.
})

Unit Test는 각 각 하나씩을 체크하는 테스트입니다.

it("Car 인스턴스를 새로 만들 때 이름은 5자 이하여야한다. ",()=>{
	// const car = new Car("이름");
	// (예를 들면) 이름이 5자 이상이면 eror를 throw하는 방식
})
// 그럼 Car라는 클래스는 잘 작동하는구나~

😀어떻게 익숙해질까요?

TDD는 익숙하지 않다!

삐빅! 정상입니다~ 😀

  • 코드 전부하고 테스트 작성한다! 도 막막할 수 있어요.

  • 그러니, 기능 구현 사항을 docs로 정리하고 하나 구현하고 TDD를 하나 작성하는 방식으로 연습해보세요.

😀BDD

  • 테스트를 작성할 때 Give/When/Then 패턴으로 테스트 케이스해볼까요?

실제 행동! 이라고 생각해볼게요. Behavior 단위

// 자동차 이름은 5자 이하면 가능한지 테스트해봐요
it('5자보다 긴 자동차 잉름을 입력한 경우 / 에러 메세지를 확인할 수 있어야 한다.'.()=>{
	// 1. Given - 주어진 상황, 환경 세팅
	const alertStub = cy.stub();

	cy.visit("index.html");
	cy.on("window:alert", alertStub); //윈도우 알러트를 alertStub으로 바꿔서 테스트한다

	// 2. When - behavior, 액션, 동작
	cy.get("#car-names-input").type("코카콜라자동차,펩시차");
	cy.get("#car-names-submit").click(); // 시간을 주기 위해 사실 아래처럼 체이닝을 사용해야해요.
	
	// 3. Then - 기대 결과 확인
	expect(alertStub).to.be.called;
})

😀똑같은 거 같은데요...?

  • 용어라는 결과물이 중요한게 아니라, 왜 이런 용어와 방식이 나왔을지에 대한 그 과정에 대한 고민이 더 중요해요~

  • 나만의 생각으로 만들어 내재화해볼 수 있겠죠 [NDD 나인 주도 개발처럼?ㅎㅎ]

  • 사실 저도 처음이라 테스트들이 다 비슷한 것 같아요.

😀test 꿀팁!

관련있는 테스트들을 describe로 묶어보세요!

  • 중복 제거에도 효과적이겠죠?
describe("기능 테스트", ()=>{
	// 각 it 테스트 하기 전에 beforeEach가 실행됩니다!
	beforeEach(()=>{
		cy.visit("index.html");
	})

	it 어쩌구..

	it 어쩌구..
});

random은 어쩌죠?

하.. 랜덤은 어렵습니다ㅎㅎ;;

  • 더군다나 E2E테스트(사용자가 써보는 것처럼 테스트)면 거의 할 수가 없어요.

할 수는 있는데 보실래요? 저라면 넘깁니다.

  • 강제로 조절하는 겁니다. 첫번째 콜은 0.1리턴하고, 두번째 콜은 0.8을 리턴하세요.

  • 위처럼 하면 되는데 E2E에서의 랜덤은 확실히 어려워요.

😀사실 E2E와 TDD는 사이가 썩 좋지 않아요.

  • 프론트엔드라면 E2E 테스트가 익숙할겁니다.

  • 하지만 이벤트 바인딩, 로직, UI에 그리기를 전부해야 테스트 하나가 통과할텐데요 → E2E는 피드백 주기가 엄청 긴 편이죠. → 그러니 TDD가 어렵죠!

  • 스스로의 기준을 만들어 봅시다.

    • 위의 랜덤을 그냥 포기하는 것도 방법이 될 수 있겠쬬?

😀테스트 코드도 코드다!

  • 테스트 코드도 유지보수가 필요한 코드예요.

  • 잘못된 테스트나 불필요한 테스트는 없는 게 낫죠.

  • 작성하는 비용 대비 효율을 생각해봐요~

    • eg) 랜덤 테스트 포기

😀결론

  • 테스트 코드에 대한 나만의 생각을 정리해봐요

    • 아니 이거 쓸모 없는데 왜 해? → OK!
    • TDD 생각보다 편한데? → OK!
    • 그냥 내가 편한 테스트가 짱이야 → OK!
  • 여태까지 테스트없이 잘 코딩해왔잖아요~

profile
함께 웃어야 행복한 개발자 장호영입니다😃

0개의 댓글