Java Spring - 스프링 테스트

김재현·2022년 7월 25일
1

Programmers

목록 보기
6/28

소프트웨어 테스트

정의. 위키피디아

  • 소프트웨어의 결함이 있는지 찾는 테스트.
  • 소프트웨어 테스트(영어: software test)는 주요 이해관계자들에게 시험 대상 제품 또는 서비스의 품질에 관한 정보를 제공하는 조사 과정이다. 소프트웨어 테스트는 또한 소프트웨어에 대한 객관적이고 독립적인 시각을 제공하여 사업주체가 소프트웨어 구현의 위험성을 올바로 이해하도록 한다. 시험 기술에는 프로그램이나 응용 프로그램을 실행하여 소프트웨어 버그를 찾는 절차를 포함되나 이에 국한되지는 않는다.

Testing levels(테스트 수준)

  • 일반적으로 단위 테스트, 통합 테스트, 시스템 테스트의 세 가지 테스트가 사용되지만, 개발자에 의해 4번째 단계인 수락 테스트도 포함될 수 있다.

Unit test (단위 테스트)

  • 기능 수준에서 특정 코드 섹션의 기능을 확인하는 테스트. 객체 지향 환경에서는 일반적으로 클래스 수준에서 수행되며, 최소 단위 테스트에는 생성자와 소멸자가 포함됨.
  • 특정 기능이 예상대로 작동하는지 확인하기 위해 개발자가 코드에서 작업할 때 작성함.
  • 단위 테스트만으로는 소프트웨어의 기능을 확인할 수 없지만, 소프트웨어의 구성요소가 서로 독립적으로 작동하는지 확인하는 데 사용됨.
  • 단위 테스팅은 소프트웨어 개발 위험, 시간 및 비용을 줄이기 위해 광범위한 결함 예방 및 탐지 전략을 동기화하여 적용하는 개발 프로세스.
  • 코드의 구성 오류를 제거하는 것을 목표로 하며, 결과적으로 소프트웨어의 품질과 전체 개발 프로세스의 효율성을 높일 수 있음.
  • static code analysis(정적 코드 분석), data-flow analysis(데이터 흐름 분석), metrics analysis(메트릭 분석), peer code reviews(피어 코드 검토), code coverage analysis(코드 적용 범위 분석)와 기타 소프트웨어 테스트 관행이 포함될 수 있음.

Integration testing (통합 테스트)

  • 소프트웨어 설계에 대해 구성 요소 간의 인터페이스를 확인하려는 모든 유형의 소프트웨어 테스트. 소프트웨어 구성요소는 반복적인 방식으로 통합되거나, 모두 함께 통합될 수도 있다.(이를 "빅뱅"이라 부름.) 일반적으로 전자는 인터페이스 문제를 보다 신속하게 찾아 수정할 수 있으므로 더 나은 방법으로 간주됨.
  • 통합 구성 요소(모듈) 간의 인터페이스 및 상호 작용의 결함을 노출하는 작업.
  • 통합 테스트는 일반적으로 많은 코드를 포함하고 단위 테스트에서 생성된 것보다 더 큰 추적을 생성하며, 통합테스트가 실패할 때 오류를 쉽게 localizing하는데 영향을 줌.
  • 이 문제를 극복하기 위해 결함 위치 파악을 개선하기 위한 테스트를 작은 조각으로 자르는 것이 제안됨.

System testing (시스템 테스트)

  • 시스템이 요구 사항을 충족하는지 확인하기 위해 완전히 통합된 시스템을 테스트.
  • 예) 시스템 테스트에는 로그인 인터페이스 테스트, 항목 생성 및 편집, 결과 전송 또는 인쇄, 항목 요약 처리 또는 삭제(또는 보관), 로그오프가 포함될 수 있다.

Acceptance testing (수락 테스트)

  • User acceptance testing (UAT, 사용자 수락 테스트)
  • Operational acceptance testing (OAT, 운영 승인 테스트) :
    • 품질 관리 시스템의 일부로 제품, 서비스 또는 출시 전 시스템의 운영 준비를 수행하는 데 사용.
    • 소프트웨어 개발, 소프트웨어 유지 관리 프로젝트에서 주로 사용되는 일반적인 유형의 비기능 소프트웨어 테스트.
    • 시스템의 운영 준비에 중점을 둠.
    • operational readiness testing (ORT, 운영 준비 테스트) Operations readiness and assurance (OR&A, 운영 준비 및 보증) testing라고도 부름.
    • 시스템의 비기능적 측면을 확인하는 테스트로 제한됨.
  • Contractual and regulatory acceptance testing (계약 및 규제 승인 테스트)
    • 계약 수락 테스트 : 계약 시 정의된 계약의 수락 기준에 따라 수행되는지 확인.
    • 규제 수락 테스트 : 소프트웨어 제품에 대한 관련 규정에 따라 수행됨.
  • Alpha and beta testing (알파 및 베타 테스트)

Testing Pyramid

  • 테스트 자동화 관점의 테스트 피라미드.
  • 밑으로 갈수록 더 많은 양의 테스트를 작성해야 함. (unit 테스트 많이)
    위로 갈수록 양은 더 적어짐. (end to end 테스트)
  • UI 테스트는 작성이 어렵고 유지보수가 힘들기 때문에 작성량이 적음.
    단위 테스트는 실행속도도 빠르고 많은 양을 작성해서 커버리지를 높여야 함.
    • Coverage(커버리지) : 측정 범위. 수행한 테스트가 테스트의 대상을 얼마나 커버했는지를 나타내는 것이 테스트 커버러지. 커버러지율을 기준으로 애플리케이션이 릴리즈가 가능한 수준으로 검증이 되었는가를 판단하게 된다.
      TestPyramid

TestPyramid2

일반적인 애플리케이션의 구상도

summary

Integration test(통합 테스트)

  • 외부 서비스와의 연동, 외부에 노출되었을 때 실제로 내부 상태가 어떻게 변하는지를 테스트.
    외부 서비스(External Datastrore, External Service)과 연동되는 객체(Data Mappers/ORM, Live HTTP Clinent 등)의 연동성을 테스트한다.

Unit test(단위 테스트)

  • 가장 작은 단위의 테스트. 모든 서비스, 도메인, 레포지토리에 대해 단위 테스트 작성 가능.

Component test

  • 하나의 서비스 전체를 테스트.

End to end test

  • UI가 API를 호출, 데이터 베이스가 변경되고 화면에 출력되는 등 전체 서비스 구동과 출력을 를 테스트하는 것.

Unit test (단위 테스트)

  • 프로그램의 기본 단위인 모듈을 테스트하기 때문에 모듈 테스트(module test)라고도 함.
  • 구현 단계에서 각 모듈의 개발을 완료한 후 개발자가 명세서의 내용대로 정확히 구현되었는지 테스트함. 즉, 개별 모듈이 제대로 구현되어 정해진 기능을 정확히 수행하는지 테스트.
    모듈 내부의 구조를 구체적으로 들여다볼 수 있는 화이트박스 테스트 같은 구조적 테스트를 주로 시행한다.
  • 하나의 모듈을 테스트할 때 상위나 하위 모듈이 개발되지 않은 경우도 있고, 개발될 때까지 기다릴 수 없기 때문에 가상의 상위, 하위 모듈을 만들어 사용해야 한다.
    • 상위 모듈의 역할을 하는 가상 모듈이 테스트 드라이버(test dirver)라 하고 테스트할 모듈을 호출한다. 필요한 데이터를 인자를 통해 넘겨주고, 테스트가 완료된 후 결과 값을 받는 역할을 함.
    • 하위 모듈 역할을 하는 것을 테스트 스텁(stub)이라고 함. 스텁 모듈은 테스트할 모듈이 호출할 때 인자를 통해 받은 값을 가지고 수행한 후 그 결과를 테스트할 모듈에 넘겨주는 역할을 함.
    • 드라이버와 스텁 모듈은 테스트에 필요한 기능만 제공할 수 있도록 간단히 구현.

  • 단위 테스트를 수행하면 발견할 수 있는 오류.
    • 잘못 사용한 자료형
    • 잘못된 논리 연산자
    • 알고리즘 오류에 따른 원치 않는 결과
    • 틀린 계산 수식에 의한 잘못된 결과
    • 탈출구가 없는 반복문의 사용

네이버 - 단위테스트

  • 프로그램에서 가장 작은 단위를 테스트 함.
  • 일반적으로 클래스 하나 당 하나의 단위 테스트.
  • 실행이 빠르고, 특정 부분을 고립해서 테스트 함.

Unit Test

SUT(System Under Test, 테스트하는 대상)

  • 여기에서의 시스템은 단위 테스트의 한 대상을 지칭함. 일반적으로 하나의 클래스.
    SUT안에는 많은 메서드가 존재하기 때문에 Method Under Test(MUT)라고 부르기도 한다. 주로 메서드를 테스트하며, 메서드는 시스템이 제공하는 기능이기 때문에 그 기능을 테스트한다고 보면 됨.
  • 객체는 협력관계를 갖고 일을 하게 되며, 의존관계에 있는 다른 객체가 존재한다. 이를 협력관계자 라고 부른다.
    협력관계자를 같이 묶어서 테스트하지 않고, 테스트 더블로 대체해서 SUT만 고립된 테스트를 진행하는 것이 단위 테스트이다.
  • SUT라는 테스트를 진행하고자 하는 클래스. 그 클래스가 다른 클래스를 사용한다면, 협력관계가 형성되어 있다고 볼 수 있음. 만약 객체를 생성해 전달해야하는 경우가 생긴다면, 테스트 더블로 대체해서 전달하게 됨.

테스트 더블

  • 의존 구성 요소를 사용할 수 없을 때 테스트 대상 코드와 상호작용하는 객체.
    • stub. Mock객체.
  • 실제 객체를 사용할 수 없을 때 가짜로 만들어서 전달하는 객체.
  • 위 그림의 Mocked Dependency로 Mocked Object, test double라고도 함.

단위 테스트 코드를 작성하는 목적

  1. 소프트웨어를 개발하다보면 지속적으로 변경이 발생하는데, 변경되다보면 오류가 발생할 수 있음. 테스트코드에 의해 오류에게서 보호를 받을 수 있음.
    단위 테스트 코드가 있을 경우 기존의 코드를 변경했을 때 이전의 기능들이 단위 테스트에 의해 정상적 동작하는 것이 확인된다면, 배포 전에 테스트 코드를 실행하기 때문에 새로 추가된 것이 기존 것을 잘 커버하고 있다, 코드 추가작업이 기존 것을 망치지 않았다는 확신을 갖을 수 있게 됨.
  2. 구현 내용을 모두 읽어보지 않더라도, 테스트 코드, 테스트 케이스만 보고도 기능이나 메서드, 결과를 쉽게 파악할 수 있다. 기능 명세서로의 기능.
    단위 테스트코드 읽어봄으로써 무슨 일을 하는지, 기능이 어떤지 알 수 있음.
  • 백엔드 엔지니어는 단위 테스트 코드를 잘 작성해야 하고, 무조건 작성해야 한다.
  • 단위 테스트는 클래스 하나하나에 개별 단위로 작성해야하기 때문에 복잡하게 만들 필요가 없고, 하나의 클래스의 기능에 집중해서 만들어야 한다. 상호작용이 있다면 테스트 더블을 이용하자.

Integration test(통합 테스트)

  • 테스트하고자 하는 코드가 다른 의존관계 연동이 잘 되어 있는지 테스트하는데 사용.
  • 각각의 단위 테스트가 끝나면 끝난 모듈 간의 연동을 테스트하거나, 시스템 밖의 외부 시스템의 연동 테스트도 통합테스트.

end to end

  • 처음부터 끝까지 다 잘되는지 확인하는 것.
    • API 호출부터 DB데이터 적재까지.

What are Unit Testing, Integration Testing and Functional Testing?

Unit test(단위 테스트)

  • 일반적으로 개별 기능과 같은 작은 코드 조각을 단독으로 격리하여 테스트하는 방법.
    테스트에서 네트워크나 데이터베이스와 같은 일부 외부 리소스를 사용하는 경우 단위 테스트가 아니다.
  • 단위 테스트 작성은 간단해야 함.
    어려운 단위 테스트 코드는 좋은 디자인이 아님.
    테스트된 함수에 일부 입력을 제공한 다음 함수 출력이 올바른지 확인해야 함.
  • 단위 테스트는 backbone(뼈대)
    단위 테스트를 사용해 코드를 설계하고 변경할 때 안정망으로 유지할 수 있으며, 동일한 방법을 다른 유형의 테스트에도 적용할 수 있음.
    단위 테스트는 다른 테스트 유형보다 덜 복잡하고 더 정확함.
  • 단위 테스트는 반복적으로 발생하는 버그인 회귀를 방지하는데도 좋음.
    특정 버그를 확인하는 단위테스트를 추가하면 번거로운 버그를 쉽게 방지할 수 있음.
    다른 테스트도 사용이 가능하지만, 단위 테스트는 매우 구체적이기 때문에 훨씬 더 유용하게 문제를 쉽게 찾아내고 수정할 수 있다.
  • 단위 테스트를 사용할 때.
    • 항상. 테스트 주도 개발을 하자.
    • 좋은 단위 테스트 세트는 버그를 방지하고, 코드 디자인을 개선하며, 코드의 리팩토링 여부를 확인할 수 있음.

Integration test(통합 테스트)

  • 시스템의 일부가 함께 작동하는 방식, 부품의 통합을 테스트하는 것.
    단위 테스트는 다른 구성 요소와 격리되지만, 통합 테스트는 그렇지 않음.
    • 예) 데이터베이스 엑세스 코드에 대해 :
      단위 테스트 - 실제 데이터베이스와 통신하지 않음.
      통합 테스트 - 통신함.
  • 단위 테스트가 충분하지 않은 상황에 유용.
    때로 두 개의 개별 시스템이 올바르게 함께 작동하고 통합 테스트가 필요한지 확인하기 위한 테스트가 필요하다.
  • 통합 테스트는 복잡성이 추가되기 때문에 일반적으로 단위 테스트보다 느림.
    일부 설정 혹은 구성이 필요할 수도 있다.
    단위 테스트보다 작성 및 유지 관리가 더 어려워지므로 통합 테스트가 절대적으로 필요한 경우가 아니면 단위 테스트에 집중해야 함.
  • 단위 테스트보다 통합 테스트가 적어야 한다.
    두 개의 개별 시스템을 함께 테스트, 혹은 코드 조각이 단위 테스트에 너무 복잡한 경우 사용해야 함.
    • 후자의 경우 코드를 수정해 단위 테스트를 하기 쉽도록 하는 것이 더 좋음.

Functional Testing(기능 테스트)

  • E2E(End to End) 테스트, 브라우저 테스트.
  • 일부 응용 프로그램의 완전한 기능을 테스트.
    실제로 웹 앱에서 브라우저를 자동화하기 위해 일부 도구를 사용하거나, 페이지를 클릭해서 애플리케이션을 테스트하는 것을 의미.
  • 수 많은 단위 테스트를 갖는 프로그램도, 기능 테스트는 적게 필요함.
    기능 테스트가 매우 복잡하여 작성 및 유지 관리가 어렵기 때문이며, 실제 사용자 상호 작용을 시뮬레이션하기 때문에 매우 느림(페이즈 로드 시간도 그 요인이 된다.)
  • 아주 세밀한 기능 테스트를 하려고 하면 안 됨.
    기능 테스트는 일반적인 사용자 상호 작용을 테스트하는 데에 사용해야 함.
  • 단위, 통합 테스트와 다르게 기능 테스트 결과는 페이지 사용자인 경우와 동일한 방식으로 검증해야 함.
  • 브라우저에서 수동으로 수행하는 몇 가지 반복 테스트가 있는 경우 기능 테스트를 사용해야 하지만, 유지관리하는 것이 쉽게 악몽처럼 어려워질 수 있기 때문에 너무 세분화하지 않도록 주의하여야 한다.

JUnit

  • 가장 많이 사용되는 오픈소스 프레임워크.
  • 버전 5가 최신.

기능

  • 매 단위 테스트마다 테스트 클래스의 인스턴스가 생성되어, 독립적인 테스트가 가능함.
    • 이전 테스트가 다음 진행되는 테스트에 간섭하지 못함.
  • 애노테이션을 제공, 테스트 라이프 사이클을 관리하게 해주고 테스트 코드를 간결하게 작성하도록 지원해줌.
    • @BeforeAll, @BeforeEach, @AfterAll, @AfterEach 같은 애노테이션 제공.
    • 테스트 코드를 작성할 때마다 매번 해야할 일들을 한 곳에서 통합적으로 할 수 있게 지원.
  • 테스트 러너를 제공해서 인텔리제이/이클립스/메이븐 등에서 테스트 코드를 쉽게 실행하게 해준다.
  • assert로 테스트 케이스의 수행 결과를 판별하게 해 줌. -> assertEquals(예상 값, 실제 값)
    • 결과는 성공(녹색), 실패(붉은색) 중 하나로 표시.

JUnit 4

  • 2006년도에 하나의 .jar파일로 배포.
  • .jar 하나만 받아도 되지만, 확장성이 너무 떨어졌다.

JUnit 5

  • 확장성이 늘어났다.

JUnit Platform

  • JVM 상에 테스팅 프레임워크를 런칭하기 위한 근간 제공.
  • 테스트를 발견, 계획을 생성하고 TestEngine인터페이스를 가지고 있으며 TestEngine을 통해 테스트를 실행하고 결과를 보고함.

JUnit Jupiter

  • TestEngine의 실제 구현체. 별도 모듈로 제공된다. jupiter-engine이 포함되어 있다.
  • 라이브러리가 추가될 때 JUnit Jupiter의 식으로 추가된다.
  • jupiter-api를 사용해서 작성한 테스트코드를 발견하고 실행해준다.
  • Jupiter API는 JUint 5에 새롭게 추가된 테스트 코드용 API로, 개발자는 Jupiter API를 사용해서 테스트 코드를 작성할 수 있다.

JUnit Vintage

  • 기존 JUnit 4 버전으로 작성된 코드를 실행할 때는 vintage-engine 모듈을 사용한다.

  • platform launcher를 통해 platform engine이 구동되는데, 이 platform engine의 구현체로는 vintage engine과 jupitor engien이 있다.

JUnit 실습

  • 테스트 성공 시 그린라이트 출력.
  • test 메서드는 추상메서드면 안되고 void여야만 한다.
    @Disabled를 사용하면 스킵할 수 있다.
  • BeforeAll 은 테스트 코드 전체가 실행되기 전에 한번만 실행.
    afterAll 은 테스트 코드 전체가 실행된 후 한번만 실행.
    • static으로 작성해야 함.
  • beforeEach 매 메서드 실행 전에 실행됨.
    afterEach 매 메서드 실행 후에 실행.
  • 구현을 해 놓고 테스트 코드를 작성할 수도, 테스트 코드 작성 후 구현을 할 수도 있다.
  • 테스트코드만 보고도 기능을 짐작할 수도 있다.

HamcrestAssertion

  • 맞는 값에
    assertEquals(2, 1+1);
    assertThat(1 + 1, equalTo(2));
    assertThat(1 + 1, is(2));
    assertThat(1 + 1, anyOf(is(1), is(2)));
  • 틀린 값에
    assertNotEquals(1, 1+1);
    assertThat(1+1, not(equalTo(1)));
    assertThat(1+1, not(1));
  • 컬렉션에 쓰기
    assertThat(prices, hasSize(3));
    assertThat(prices, everyItem(greaterThan(1)));
    assertThat(prices, containsInAnyOrder(3,4,2));
    assertThat(prices, hasItem(greaterThanOrEqualTo(2)));
    assertThat(prices, hasItem(2));

Mock Object(목 객체, 모의 객체)

  • 테스트 더블
    테스트 하고자 하는 객체와 의존 관계에 있는 객체를 사용할 수 없을 때 테스트 하는 대상 코드, SUT와 상호작용을 하기 위해 만든 객체.
  • 종류 : Mock, Stub
  • Mock 객체는 호출에 대한 기대를 명시, 어떻게 동작해야 하는지에 대한 내용이 기술된 객체.
    • Mock은 행위에 집중.
  • Stub은 가짜 객체. (dummy, fake)
    실제 동작하는 것처럼 보이게 만드는 객체. 인터페이스를 구현하는 stub을 만들어서 제공한다.

  • 행위 검증 : 목 객체가 메서드가 호출되어질 것이라는 기대하는 테스트를 짜는 것. 특정 메서드의 호출, 특정 동작이 수행되는지 확인하는 것.

  • 상태 검증 : 검증하고자 하는 객체, SUT에 대해 상태를 확인하며 올바르게 동작하는지 확인.

  • 개별 스탭별로 코드 작성하는 법.
    Given : 상황이 주어졌을 때 메서드가 호출됨.
    When : 객체가 생성됨. SUT.
    Then : 생성된 객체에 집중.

  • Spring Boot Starter Test를 이용하면 바로 Mockitor이용 가능.

  • 행위에 집중해서 어떤 메서드가 호출되는지 알려줘야 함.
  • When : 정의를 한 것만 리턴이 됨.
  • 어떤 메서드가 호출되는지, 어떤 행동을 하는지 검사.
    • inOrder : 특정한 순서를 보장해서 호출함.
      특정 mock에 대해 순서를 보장하려고 할 때 쓰는 방법.

Spring의 JUnit 5 지원

공식문서

  • Spring에서 지원하는 기능으로 단위 테스트 작성에 도움을 받을 수 있다.
    하지만 의존관계 없이 핵심 로직을 작성하는 것이 중요하다. 비즈니스 로직은 framework에 의존적이지 않은 것이 좋다.
    • Mock Objects 지원
    • General Testing Utilities
    • Spring MVC Testing Utilities
  • 통합 테스트에 많은 지원을 해준다.
  • 스프링 익스텐션을 익스텐드 with 과 함께 사용하면 스프링 테스트 컨텍스트 프레임웍을 사용하게 해줌.

0개의 댓글