좌충우돌 개발

Toby 스프링3 1부 2장 테스트

|

2장 테스트

테스트란 내가 예상하고 의도 했던 대로 코드가 정확히 동작하는 지를 확인해서, 만든 코드를 확신할 수 있게 해주는 작업이다.

@Test
@Test expected : 보통의 테스트와 반대로, 정상적으로 테스트 메소드를 마치면 테스트가 실패하고, expected로 지정한 예외가 던저지면 테스트는 성공하게 된다.

포괄적인 테스트
네거티브 테스트를 먼저 만들어라

테스트가 이끄는 개발

  • 기능설계를 위한 테스트
  • 조건 / 행위 / 결과
테스트 주도 개발 (TDD: Test Driven Development)
  • ‘실패한 테스트를 성공시키기위한 목적이 아닌 코드는 만들지 않는다’ 는 것이 TDD의 기본 원리이다.
  • 테스트 작성하고 이를 성공시키는 코드를 만드는 작업의 주기를 가능한 한 짧게 가져가도록 권장한다.
Junit의 테스트 수행 방식
  1. 테스트 클래스에서 @Test가 붙은 public 이고 void형이며 파라미터가 없는 테스트 메소드를 모두 찾는다.
  2. 테스트 클래스의 오브젝트를 하나 만든다.
  3. @Before가 붙은 메소드가 있으면 실행한다.
  4. @Test가 붙은 메소드를 하나 호출하고 테스트 결과를 저장해둔다.
  5. @After가 붙은 메소드가 있으면 실행한다.
  6. 나머지 테스트 메소드에 대해 2~5번을 반복한다.
  7. 모든 테스트의 결과를 종합해서 돌려준다.

기억할 점 :
각 테스트 메소드를 실행할 때마다 테스트 클래스의 오브젝트를 새로 만든다는 점이다.
한번 만들어진 테스트 클래스의 오브젝트는 하나의 테스트 메소드를 사용하고 나면 버려진다.
각 테스트가 독립적으로 실행 됨을 보장하기 위해서 새로 오브젝트를 생성하여 테스트를 진행한다.

픽스처 : 테스트를 수행할 때 필요한 정보나 오브젝트를 픽스처(fixture)라고 한다. 일반적으로 픽스처는 여러 테스트에서 반복적으로 사용되기 때문에 @Before 메소드를 이용해 생성해두면 편리하다.

@BeforeClass

@RunWith 는 JUnit 프레임워크의 테스트 실행 방법을 확장할 때 사용하는 애노테이션이다. @ContextConfiguration 은 자동으로 만들어줄 애플리케이션 컨텍스트의 설정 파일 위치를 지정한 것이다. @Autowired 가 붙은 인스턴스 변수가 있으면 텍스트 컨텍스트 프레임워크는 변수 타입과 일치하는 컨텍스트 내의 빈을 찾는다. 타입이 일치하는 빈이 있으면 인스턴스 변수에 주입해준다.
@Autowired는 같은 타입의 빈이 두 개 이상 있는 경우에는 타입만으로는 어떤 빈을 가져올지 결정할 수 없다.

스프링 애플리케이션 컨텍스트는 초기화할 때 자기 자신도 빈으로 등록한다.

Interface를 두고 DI를 해야하는 이유
  1. 소프트웨어 개발에서 절대로 바뀌지 않는 것은 없기 때문이다.
  2. 클래스의 구현 방식은 바뀌지 않더라도 인터페이스를 두고 DI를 적용하게 되면 다른 차원의 서비스 기능을 도입할 수 있기 때문이다.
  3. 테스트 때문이다. DI는 테스트가 작은 단위의 대상에대해 독립적으로 만들어지고 실행되게 하는데 중요한 역할을 한다.

@DirtiesContext: 테스트 메소드에서 애플리케이션 컨텍스트의 구성이나 상태를 변경한다는 것을 테스트 컨텍스트 프레임워크에 알려준다.

  • Test시 테스트용 설정파일을 두고 하는게 좋다
  • 컨테이너 없는 DI 테스트

침투적 기술과 비침투적 기술 침투적 기술은 기술을 적용했을 때 애플리케이션 코드에 기술 관련 API를 등장하거나, 특정한 인터페이스나 클래스를 사용하도록 강제하는 기술을 말한다. 침투적 기술을 사용하면 애플리케이션 코드가 해당 기술에 종속되는 결과를 가져온다. 반면에 비침투적인기술은 애플리케이션 로직을 담은 코드에 아무런 영향을 주지 않고 적용이 가능하다. 따라서 기술에 종속적이지 않은 순수한 코드를 유지할 수 있게 해준다. 스프링은 이런 비침투적인 기술의 대표적인 예이다.

DI를 이용한 테스트 방법 선택 항상 스프링 컨테이너 없이 테스트할 수 있는 방법을 가장 우선적으로 고려하자. 이 방법이 테스트 수행 속도가 가장 빠르고 테스트 자체가 간결하다. 테스트를 위해 필요한 오브젝트의 생성과 초기화가 단순하다면 이 방법을 먼저 고려해야 한다.

여러 오브젝트와 복잡한 의존관계를 갖고 있는 오브젝트를 테스트해야 할 경우가 있다. 이때는 스프링의 설정을 이용한 DI 방식의 테스트를 이용하면 편리하다. 테스트에 애플리케이션 설정 파일을 사용하는 경우는 테스트 전용 설정파일을 따로 만들어 사용하는 편이 좋다.

테스트 설정을 따로 만들었다고 하더라도 때로는 예외적인 의존관계를 강제로 구성해서 테스트해야 할 경우가 있다. 이때는 컨텍스트에서 DI를 받은 오브젝트에 다시 테스트 코드로 수동 DI해서 테스트하는 방법을 사용하면 된다. 테스트 메소드나 클래스에 @DirtiesContext 애노테이션을 붙이는 것을 잊지 말자

학습 테스트(learning test) 로 배우는 스프링 학습 테스트의 목적 : 자신이 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용 방법을 익히려는 것이다.

학습 테스트의 장점

  • 다양한 조건에 따른 기능을 손쉽게 확인해 볼 수 있다.
  • 학습 테스트 코드를 개발 중에 참고할 수 있다.
  • 프레임워크나 제품을 업그레이드 할때 호환성 검증을 도와준다.
  • 테스트 작성에 대한 좋은 훈련이 된다.
  • 새로운 기술을 공부하는 과정이 즐거워진다.

Static import 란 : 다른 class에 정의된 static filed나 static method를 현재 class에서 정의 된것처럼 사용하기 위해 사용한다.

Import static org.junit.Assert.assertThat\*
assertThat(is(not(sameInstance(testObject))  /* 클래스 내의 메소드처럼 사용 가능하다*/

sameInstance(object)
or(is())

is()는 equals() 비교를 해서 같으면 성공하지만 is(not())은 반대로 같이 않아야 성공한다.

버그 테스트 : 코드에 오류가 있을 때 그 오류를 가장 잘 드러내줄 수 있는 테스트를 말한다

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

정리

  • 테스트는 자동화되어야 하고, 빠르게 실행할 수 있어야 한다
  • main() 테스트 대신 JUnit 프레임워크를 이용한 테스트 작성이 편리하다
  • 테스트 결과는 일관성이 있어야 한다. 코드의 변경 없이 환경이나 테스트 실행 순서에 따라서 결과가 달라지면 안 된다.
  • 테스트는 포괄적으로 작성해야 한다. 충분한 검증을 하지 않는 테스트는 없는 것보다 나쁠 수 있다.
  • 코드 작성과 테스트 수행의 간격이 짧을수록 효과적이다
  • 테스트하기 쉬운 코드가 좋은 코드이다.
  • 테스트를 먼저 말들고 테스트를 성공시키는 코드를 만들어가는 테스트 주도 개발 방법도 유용하다.
  • 테스트 코드도 애플리케이션 코드와 마찬가지로 적절한 리텍토링이 필요하다.
  • @Before @After를 사용해서 테스트 메소드들의 공통 준비 작업과 정리 작업을 처리할 수 있다
  • 스프링 테스트 컨텍스트 프레임워크를 이용하면 테스트 성능을 향상시킬 수 있다.
  • 동일한 설정파일을 사용하는 테스트는 하나의 애플리케이션 컨텍스트를 공유한다.
  • @Autowired를 사용하면 컨텍스트의 빈을 테스트 오브젝트에 DI할 수 있다.
  • 기술의 사용 방법을 익히고 이해를 돕기 위해 학습 테스트를 작성하자
  • 오류가 발견될 경우 그에 대한 버그테스트를 만들어두면 유용하다.

Comments