티스토리 뷰

테스트

스프링이 개발자에게 제공하는 가장 중요한 가치는 객체지향테스트이다. 애플리케이션의 복잡성을 대응하는 첫 번째 전략은 확장과 변화를 고려한 객체지향적 설계와 그것을 효과적으로 담아낼 수 있는 IoC/DI 같은 기술이고, 두 번째 전략은 만들어진 코드를 확신할 수 있게 해주고, 변화에 유연하게 대처할 수 있는 자신감을 주는 테스트 기술이다.

또한 테스트는 스프링을 학습하는 데 있어 가장 효과적인 방법 중 하나다. 테스트의 작성은 스프링의 다양한 기술을 활용하는 방법을 이해하고 검증하고, 실전에 적용하는 방법을 익히는 데 효과적으로 사용될 수 있다.

테스트의 유용성

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

기존에 수행하던 웹을 통한 테스트는 많은 문제가 있었다. DB Access 로직을 검증하기 위해서 수많은 계층들이 준비가 되고 참여해야만 한다. 웹의 폼에서 값을 입력해 요청을 하고, MVC 프레젠테이션 계층과 서비스 계층을 거쳐 DAO 로직까지 도달해야만 비로소 DAO의 테스트가 가능했다. 하나의 로직을 테스트하기 위해서 만들어야 하는 기능들이 너무 많고, 만약 문제가 발생하면 어디에서 문제가 발생했는지를 찾아내야 하는 수고를 해야 한다. 하나의 테스트를 수행하는 데 참여하는 클래스와 코드가 너무 많은 것이다.

단위 테스트

테스트하고자 하는 대상이 명확하다면 그 대상에만 집중해서 테스트하는 것이 바람직하다. 테스트는 가능하면 작은 단위로 쪼개서 집중해서 할 수 있어야 한다. 관심사의 분리라는 원리가 여기에도 적용된다. 테스트의 관심이 다르다면 테스트할 대상을 분리하고 집중해서 접근해야 한다. 이렇게 작은 단위의 코드에 대해 테스트를 수행한 것을 단위 테스트라고 한다.

테스트는 자동으로 수행되도록 코드로 만들어지는 것이 중요하다. 자동으로 수행되는 테스트의 장점은 자주 반복할 수 있다는 것이다.

테스트를 이용하면 새로운 기능도 기대한 대로 동작하는지 확인할 수 있을 뿐 아니라, 기존에 만들어뒀던 기능들이 새로운 기능을 추가하느로 수정한 코드에 영향을 받지 않고 여전히 잘 동작하는지를 확인할 수도 있다.

테스트 습관

개발자가 테스트를 직접 만들 때 자주 하는 실수가 하나 있다. 바로 성공하는 테스트만 골라서 만드는 것이다. 스프링의 창시자인 로드 존슨은 항상 네거티브 테스트를 먼저 만들라는 조언을 했다. 테스트를 작성할 때는 부정적인 케이스를 먼저 만드는 습관을 들이는 게 좋다.

TDD

TDD, Test Driven Development

만들고자 하는 기능의 내용을 담고 있으면서 만들어진 코드를 검증도 해줄 수 있도록 테스트 코드를 먼저 만들고, 테스트를 성공하게 해주는 코드를 작성하는 방식의 개발 방법이다.

TDD는 아예 테스트를 먼저 만들고 그 테스트가 성공하도록 하는 코드만 만드는 식으로 진행하기 때문에 테스트를 빼먹지 않고 꼼꼼하게 만들어낼 수 있다. 또한 TDD는 코드에 대한 피드백을 매우 빠르게 받을 수 있도록 한다. 게다가 매번 테스트가 성공하는 것을 보면서 작성한 코드에 대한 확신을 가질 수 있어, 가벼운 마음으로 다음 단계로 넘어갈 수가 있다.

TDD의 장점 중 하나는 코드를 만들어 테스트를 실행하는 그 사이의 간격이 매우 짧다는 점이다. 개발한 코드의 오류는 빨리 발견할수록 좋다. 빨리 발견된 오류는 쉽게 대응이 가능하기 때문이다.

스프링 테스트

픽스처

테스트를 수행하는 데 필요한 정보나 오브젝트를 픽스처라고 한다.

@Autowired

@Autowired는 스프링의 DI에 사용되는 특별한 어노테이션이다. @Autowired가 붙은 인스턴스 변수가 있으면, 테스트 컨텍스트 프레임워크는 변수 타입과 일치하는 컨텍스트 내의 빈을 찾는다. 타입이 일치하는 빈이 있으면 인스턴스 변수에 주입해준다.

인터페이스를 두고 DI를 적용해야 하는 이유

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

테스트에서만 사용될 클래스가 빈으로 정의된 테스트 전용 설정파일을 따로 만들어서 사용하는 방법도 있다.

침투적 기술과 비침투적 기술

  • 침투적 기술 : 기술을 적용했을 때 애플리케이션 코드에 기술 관련 API가 등장하거나, 특정 인터페이스나 클래스를 사용하도록 강제하는 기술
  • 비침투적 기술 : 애플리케이션 로직을 담은 코드에 아무런 영향을 주지 않고 적용이 가능하다. 스프링은 비침투적인 기술의 대표적인 예이다.

학습 테스트

학습 테스트

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

학습 테스트의 목적은 자신이 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용 방법을 익히려는 것이다. 테스트이지만 프레임워크나 기능에 대한 검증이 목적이 아니다. 자신이 테스트를 만들려고 하는 기술이나 기능에 대해 얼마나 제대로 이해하고 있는지, 그 사용 방법을 바로 알고 있는지를 검증하려는 게 목적이다. 또, 테스트 코드를 작성해보면서 빠르고 정확하게 사용법을 익히는 것도 학습 테스트를 작성하는 하나의 목적이다.

학습 테스트의 장점

  • 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다
    • 학습 테스트는 자동화된 테스트 코드로 만들어지기 때문에 다양한 조건에 따라 기능이 어떻게 동작하는지 빠르게 확인할 수 있다.
  • 학습 테스트 코드를 개발 중에 참고할 수 있다
    • 학습 테스트는 다양한 기능과 조건에 대한 테스트 코드를 개별적으로 만들고 남겨둘 수 있다.
    • 실제 개발에서 샘플 코드로 참고할 수 있다
  • 프레임워크나 제품을 업그레이드할 때 호환성 검증을 도와준다
  • 테스트 작성에 대한 좋은 훈련이 된다
  • 새로운 기술을 공부하는 과정이 즐거워진다

버그 테스트

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

버그 테스트의 장점

  • 테스트의 완성도를 높여준다
    • 기존 테스트에서 불충분한 부분이 있었기 때문에 버그가 발생한 것이다. 이에 대해 테스트를 만들기 때문에 테스트를 보완해줄 수 있다.
  • 버그의 내용을 명확하게 분석하게 해준다
  • 기술적인 문제를 해결하는 데 도움이 된다

동등분할(equivalence partitioning)

같은 결과를 내는 값의 범위를 구분해서 각 대표 값으로 테스트를 하는 방법을 말한다.

경계값 분석(boundary value analysis)

에러는 동등분할 범위의 경계에서 주로 많이 발생한다는 특징을 이용해서 경계의 근처에 있는 값을 이용해 테스트하는 방법


참고

토비의 스프링 3.1 Vol. 1 스프링의 이해와 원리