Spring/토비의 스프링 3.1

2.5 학습 테스트로 배우는 스프링

다비드박 2019. 1. 17. 19:24


2.5 학습 테스트로 배우는 스프링

학습 테스트
자신이 만들지 않은 프레임워크나 다른 개발팀에서 만들어서 제공한 라이브러리 등에 대해서 작성한 테스트

학습 테스트의 목적

  • 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용 방법을 익히기 위함
  • 자신이 테스트를 만들려고 하는 기술이나 기능에 대해 얼마나 제대로 알고 있는 지를 검증
  • 빠르고 정확하게 사용법을 익히기 위함

테스트 대상보다 테스트 코드 자체에 관심을 가져야 함

2.5.1 학습 테스트의 장점

  1. 다양한 조건에 따른 기능을 손쉽게 확인 가능
    • 자동화된 테스트 코드로 만들어지기 때문에 다양한 조건에 따라 기능이 어떻게 동작하는지 빠르게 확인이 가능
  2. 학습 테스트 코드를 개발 중 참고 가능
    • 예제를 만드는 방법의 경우 최종 수정 예제만 남게 된다.
    • 학습 테스트는 코드를 개별적으로 만들고 남겨둘 수 있으므로 개발 중 좋은 참고 자료가 된다.
  3. 프레임워크 또는 제품 업그레이드 시 호환성 검증을 도와줌
    • 기존에 사용하던 API가 기능에 문제가 없다는 사실을 미리 확인해 볼 수 있음.
    • 기능에 변화가 있거나 업데이트 된 제품에 버그가 있다면, 미리 확인할 수 있음
    • 사용법에 변화가 생긴 경우 그에 맞춰 애플리케이션 코드를 수정할 계획을 세울 수 있음
  4. 테스트 작성에 좋은 훈련이 된다.
    • 테스트 코드 작성을 연습할 수 있다,
    • 학습 테스트의 경우 한두 가지 간단한 기능에만 초점을 맞추면 되기 때문에 테스트도 대체로 단순하다.
  5. 새로운 기술을 공부하는 과정이 즐거워진다.

스프링 학습 테스트 시 참고할 수 있는 가장 좋은 소스 : 스프링 자신에 대한 테스트 코드

  • 스프링 배포판을 열어보면 테스트 코드가 함께 포함되어 있음

2.5.2 학습 테스트 예제

JUnit 테스트 오브젝트 테스트

JUnit은 테스트 메소드를 수행할 때마다 새로운 오브젝트를 생성한다.

  1. 새로운 테스트 클래스를 작성
  2. 세 개의 테스트 메소드 추가
  3. 테스트 클래스 자신의 타입으로 스태틱 변수를 하나 선언
  4. 매 테스트 메소드에서 스태틱 변수에 담긴 오브젝트와 자신을 비교하여 같지 않음을 확인 후 현재 오브젝트를 스태틱 변수에 저장
public class JUnitTest {
    public static JUnitTest testObject;
    
    @Test
    public void test1() {
        assertThat(this, is(not(sameInstance(testObject))));
        testObject = this;
    }
    
    @Test
    public void test2() {
        assertThat(this, is(not(sameInstance(testObject))));
        testObject = this;
    }
    
    @Test
    public void test3() {
        assertThat(this, is(not(sameInstance(testObject))));
        testObject = this;
    }
}

assertThat()의 매처

  • not() : 뒤에 나오는 결과를 부정
  • sameInstance() : 같은 오브젝트인지 비교(동일성 비교)

문제점

  • 직전 테스트에서 만들어진 테스트 오브젝트와만 비교
  • 첫 번째, 세 번째 오브젝트가 같을 경우, 검증이 안 됨

해결책

  1. 스태틱 변수로 테스트 오브젝트를 저장할 수 있는 컬렉션을 만듦
  2. 현재 테스트 오브젝트가 컬렉션에 이미 등록되어 있는지 확인
  3. 없으면, 자기 자신을 추가
  4. 2~3 반복

스프링 테스트 컨텍스트 테스트

스프링 테스트 컨텍스트 프레임워크에 대한 학습 테스트

  • 스프링 테스트용 애플리케이션 컨텍스트는 테스트 개수와 상관없이 한 개만 만들어짐
  • 생성된 컨텍스트는 모든 테스트에서 공유됨
  • 테스트용 설정파일이 필요함. applicationContext.xml이 있지만 독립적으로 만드는 것이 좋음
  • 해당 설정파일에는 아무런 빈을 등록할 필요가 없음

junit.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

JUnitTest

  • RunWith와 ContextConfiguration 애노테이션 추가
  • Autowired로 주입된 context 변수가 같은 오브젝트인지 확인
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/junit.xml")
public class JUnitTest {
    @Autowired ApplicationContext context;

    static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();
    static ApplicationContext contextObject = null;

    @Test
    public void test1() {
        assertThat(testObjects, not(hasItem(this)));
        testObjects.add(this);

        assertThat(contextObject == null | contextObject == this.context, is(true));
        contextObject = this.context;
    }

    @Test
    public void test2() {
        assertThat(testObjects, not(hasItem(this)));
        testObjects.add(this);

        assertTrue(contextObject == null | contextObject == this.context);
        contextObject = this.context;
    }

    @Test
    public void test3() {
        assertThat(testObjects, not(hasItem(this)));
        testObjects.add(this);

        assertTrue(contextObject == null | contextObject == this.context);
        contextObject = this.context;
    }
}

매번 동일한 애플리케이션 컨텍스트가 context 변수에 주입됐는지 확인

  1. contextObject가 null인지 확인 (첫번째 테스트인지)
  2. contextObject에 현재 context 저장
  3. 다음부터는 contextObject와 현재 context를 비교
    • asserThat() : 첫 번째 파라미터에 Boolean 타입 조건문, 결과를 is() 매처와 비교
    • assertTrue() : 조건문을 받아 그 결과가 true인지를 확인
    • assertThat(either()) : Deprecated 됨

기타 학습 테스트를 할 수 있는 내용

  • 스프링이 싱글톤 방식으로 빈의 오브젝트를 만드는 것이 사실일까?
  • @Autowired로 가져온 빈 오브젝트가 어플리케이션 컨텍스트에서 직접 getBean()으로 가져온 것과 동일한가?
  • XML에서 스트링 타입의 프로퍼티 값을 설정한 것이 정말 빈에 잘 주입되는가?

2.5.3 버그 테스트

버그 테스트
코드에 오류가 있을 때 그 오류를 가장 잘 드러내줄 수 있는 테스트
버그 테스트는 일단 실패하도록 만들어야하며, 버그 테스트가 성공할 수 있도록 애플리케이션 코드를 수정한다.

버그 테스트의 필요성과 장점

  1. 테스트의 완성도를 높여준다.
  2. 버그의 내용을 명확하게 분석하게 해준다.
  3. 기술적인 문제를 해결하는 데 도움이 된다.

테스트 기법
동등분할(Equivalence Partitioning) : 같은 결과를 내는 값의 범위를 구분해서 각 대표 값으로 테스트하는 방법
경계값 분석(Boundary Value Analysis) : 경계의 근처에 있는 값을 이용해 테스트하는 방법