Post

테스트

3. 테스트

테스트를 하는 가장 큰 이유는 자신의 코드에 확신을 갖기 위해서

용어 정리

  • 커버리지(코드 커버리지 또는 테스트 커버리지)

    테스트로 측정되며 테스트 코드에서 쓰는 유용한 측정 범위

  • 고수준 및 저수준

    보통 고수준: 종단 간 테스트/저수준: 단위 테스트

  • 복잡성

    코드 경로들의 측정 결과

  • 확신

    완전한 테스트 커버리지는 의도한 것처럼 전체 코드 베이스가 잘 동작한다는 확신

  • 실행

    테스트 군에 의해 코드가 실행되면, 해당 코드는 커버리지를 갖게 됨

  • 기술적 부채

    코드 기반에서 확신과 신뢰의 결여가 더 많은 생각과 더 느린 개발 결과를 가져오는 상황

  • 피드백 루프

    코드를 작성하는 것과 제대로 작성되었는지 사이의 간극(결과를 자동적으로 재투입하면서 지속/반복적 테스트 진행)

  • 목업(mockup)과 스텁(stub)

    테스트를 모형으로 대체하여 기능을 직접 행사하는 것을 피하는 두가지 방법

    목업을 할 때는 assertion 생성

    스텁은 asssertion 생성하지 않음

3.1 테스트를 해야 하는 많은 이유

  1. 이미 많은 테스트를 하고 있음

    코드를 콘솔에 입력할 때나 웹 브라우저를 열 때 이미 테스트를 하고 있는 것임

  2. 리팩토링은 테스트 없이 불가능

    리팩토링은 동작을 보장하지 않으면 완전히 불가능, 동작 보장은 테스트 없이 불가능

  3. 팀과 쉽게 작업 가능

    동료가 깨진 코드를 작성하면 테스트 집합에서 잠재적인 문제가 있음을 알 수 있음

  4. 기능을 증명할 때 테스트가 이상적(문서화하지 않음)

    준비된 문서가 없다면, 테스트로 코드에서 원하는 동작 확인 가능

    코드를 문서화하는 테스트에만 의존하는 것은 좋은 생각이 아니지만, 참조용으로는 도움이 됨

  5. 단지 코드 동작을 검증만 하는 것이 아님

    의도하지 않게 나쁜 버전이나 충돌하는 버전으로 업그레이드하는 것을 방지 가능

  6. 테스트는 대규모 업그레이드에 중요

    책임감 있게 구현하려면 가능한 모든 코드 경로를 수작업으로 확인하고 필요한 데이터 객체를 구성하면 모든 작업이 수행하는지 확인해아 함 -> 테스트 집합 필요

  7. 버그를 일찍 발견 가능

    버그를 초기에 발견하면 수정하기 수월함

  8. 테스트는 위기가 아니라 개발 과정을 원활하게 함

    적은 양의 기술 채무는 빠르게 진행해야 할 때와 난처한 상황에서 시간을 확보하는 데 도움을 줌

  9. 피드백 루프가 더 엄격해짐

    테스트 없이 개발하면 개발과 코드가 작동하는지 확인하는 시간이 길어짐

    테스트가 없다면 코드가 작동한다고 가정하거나 수동으로 확인해야 함

3.2 여러 가지 테스트 방법

각 테스트마다 3가지 단계가 있음

  1. 설치(setup)
  2. 어설션(assertion)
  3. 해체(teardown)

3.2.1 수동 테스트

3.2.2 문서화된 수동 테스트

3.2.3 승인 테스트

테스트 설정 및 해체를 자동화할 수 있지만 어설션은 사람이 직접 입력해야 함

모든 테스트에 승인이 나지 않았다면 코드는 실패한 테스트와 동일하게 취급됨

프로그래밍 방식으로 검사할 때 어설션 작성하기가 어려움

수동 테스트가 개인적인 테스트를 위한 유기적 절차라면, 승인 테스트는 그룹에서 자연스럽게 테스트할 수 있는 방법

팀 간의 기본 환경이 다양하고 프레임워크를 이용하여 어떤 절차의 유형으로 바꾸어야 하는지에 대해 이미 제품화된 결정이라면 어려움

3.2.4 종단 간 테스트

수동 테스터가 최종 사용자에게 제공되는 환경, 실제 상호 작용을 자동화

느리지만 사용자 경험을 시뮬레이션 가능

3.2.5 단위 테스트

빠르고 ‘단위’에 집중

단위: 파일, 모듈, 클래스, 객체, 패키지

각 단위에 대한 함수의 입력 및 출력 동작에 초점 -> 저수준 테스트

목업이나 스텁을 사용하는 데 자유로움

3.2.6 비기능적 테스트

코드의 품질 향상과 제대로 작동한다는 확신에 기여하지 않음

성능/사용성/실행/보안/접근성/현지화

3.2.7 기타 유익한 테스트 환경

  • 기능 테스트: 새로 만든 기능 테스트 (TDD)

  • 회귀 테스트: 초기에 버그를 재현하려고 진행하는 테스트, 그 후에 수정하여 버그가 다시 나타나지 않도록 함

  • 특성화 테스트: 아직 테스트가 진행되지 않은 코드에 커버리지를 추가하려고 작성하는 테스트

    TDD를 따르고 싶지만 구현 코드를 이미 작성했다면 특성화 테스트를 작성하거나 일시적으로 코드를 되돌려야 함

3.3 도구와 절차

3.3.1 품질 절차

  • 표준 코딩과 스타일 가이드

  • 개발자 만족도 회의

  • 짝 프로그래밍(pair programming)

    작은 버그나 오탈자를 잡아내기 수월함

    품질 관련 질문을 자주 하기 때문에 높은 품질 기대 가능

    다양한 지식을 조직으로 확산하는 데 도움이 됨

    선행 비용 산정 어려움

    강한 집중력 필요(25분 집중 후 5분 쉬는시간 -> 포모도로 기법)

    수준 차이가 클때 좌절감과 모욕감을 느낄 수 있음

  • 코드 검토

  • 테스트 주도 개발(TDD)

    좋은 테스트 커버리지와 함께 품질 있는 코드를 만들 수 있음

    구현된 코드 후에 진행되는 테스트 절차와 크게 다름

    TDD를 하면 적색/녹색/리팩토링 주기를 사용하여 개발 전반적인 지침을 세울 수 있음

    참고: 링크.

3.3.2 품질 도구

  • 버전 관리

  • 테스트 프레임워크

    테스트 파일을 작성하는 방법과 실행 파일 제공

    Mocha/Tape

  • 어셜션, 기대 구문 라이브러리

    wish

  • 특정 분야의 라이브러리

  • 팩토리와 픽스처

    위조 또는 위조자와 관련

  • 목업과 스터빙 라이브러리

    목업/목킹, 스텁/스터빙, 더블, 스파이

    특정 함수가 호출되는 테스트들을 설정할 수 있게 함

  • 빌드, 작업, 패키지 도구

  • 로더와 와처

    로더는 애플리케이션을 메모리에 유지하여 프로세스 속도를 높여줌

    와처 스크립트가 지능적으로 저장된 파일과 관련 있는 테스트만 실행할 때 피드백 루프 강화 가능

  • 테스트 병렬 실행기

    시스템이 여러 코어를 사용하여 테스트 실행을 병렬화하고 테스트 집합의 실행 속도를 높임

  • 지속적 통합(CI) 서비스

  • 커버리지 관찰자

  • 린터, 스타일 검토 도구

    코드를 실행하지 않으면서 파일을 검사하여 다양한 유형의 오류나 코드 스타일 위반을 잡아낼 수 있음

  • 디버거와 로거

  • 준비 단계와 QA 서버

참고자료

리팩토링 자바스크립트(Refactoring JavaScript)

링크.

This post is licensed under CC BY 4.0 by the author.