Search

낙서장3

주제
원리, 개념
방법
정리
결론
토비의 스프링 내용
UserDaoTest
특징
웹을 통한 테스트 방법의 문제 → 서버 재가동
단위테스트
자동수행 테스트 코드
지속적인 개선과 점진적인 개발을 위한 테스트
UserDaoTest의 문제점
수동확인
실행작업의 번거로움
UserDaoTest 개선
테스트 자동화
테스트의 효율적인 수행과 결과 관리
JUnit을 활용한 테스트로 전환
테스트 메서드 전환 @Test
검증코드 전환
Junit 테스트 실행
Junit?
실행방법
테스트 결과 일관성
동일결과 보장 테스트
포괄적 테스트
테스트를 성공시키기 위한 코드의 수정
포괄적인 테스트
테스트가 이끄는 개발 TDD
기능설계를 위한 테스트
테스트 주도 개발
테스트 코드 개선
픽처스?
스프링 테스트 적용
테스트를 위한 애플리케이션 컨텍스트 관리
스프링 테스트 컨텍스트 프레임워크 적용 ApplicationContext의 분리 test용 product용
테스트 메서드 컨텍스트 공유
컨테이너 없는 DI테스트
DI를 이용한 테스트 방법 선택
결과적으로 테스트를 어떻게 작성할지
테스트를 위해서는 어떻게 오브젝트를 설계 해야하는지
테스트를 쉽게 도와주는게 뭐가 있는지
개념
방법
사용
결과적 테스트를 위한 프레임워크
1장 내용을 정리해보자!
나보다 더 잘하는 개발자 “백기선”님의 블로그에서 가져온 내용이다.
IOC는 제어권을 프레임웤에 넘기는 포괄적인 개념이다. 여기서 제워권이란 새로운 객체의 생성, 트랜잭션, 보안에 대한 제어들을 이야기 한다. AOP는 IOC를 실현하는 하나의 기술이다. DI또한 IOC를 실현하는 하나의 기술이다.
DI는 종속성을 필요로 하는 코드 없이 여러 클래스들을 묶는데 사용하는 기술입니다. 클라이언트는 프레임웤에게 종속성의 생명주기 관리를 넘겼습니다. 이렇게 함으로써 클라이언트는 테스트하기 용이해 집니다.
Dependency Injection은 Inversion Of Control의 한 종류이다. 이것은 코드에 종속성을 주입하는 원리이다. 이것을 사용하면 객체 생성 또는 그것을 위치시키는 일을 프레임웍에게 전가 시키기 때문에 코드 자체의 테스트가 용이해진다. ApplicationContext는 Spring의 주요 객체 레지스트리와 통합 포인트다. 주로 XML파일을 통해서 bean과 그들의 종속성을 설정한다. 많은 기능이 있지만 그 중에 객체 생성과 DI가 핵심 기능이다. 마지막으로 POJO 스타일로 개발이 가능하다는 것이다. 따라서 객체 지향 개발 기술의 사용이 가능하며 POJO로 개발 된 시스템은 테스트가 용이하고 유연하다. 또한 개발자들이 프레임웤을 어떻게 다루는지 보다는 문제 영역과 비즈니스 로직에 집중하여 개발이 가능해진다.
음... 우리가 바라보는 토비의 스프링 내용이 맞나...
여튼 백기선님의 생각에서 많이 언급되는 내용은 테스트다. 무려 3번이나 언급되었다. 그만큼 spring이 지향하는 가치에는 테스트가 포함되어있다는 것이다. 그럼 도대체 테스트는 뭘까?
필자가 생각하는 테스트의 정의는 코드를 짜기위한 공식이다.
2X + X = 3 이라는 공식이 있다면 X 의 값은 1이 될 것이다. 이처럼 테스트라는 것은 내 코드를 공식에 대입해보고 그 공식을 통하여 정답을 평가할 수 있는 하나의 장치다.
이러한 공식을 어떻게 하면 짤 수 있을까?
일단은 잘 모른다. 하지만 우리같이 테스트 케이스를 잘 못만드는 사람들을 위하여 테스트를 짤 수 있는 몇 가지 팁이 존재한다.
개념적으로는
항상 실패하는 테스트를 먼저 작성
테스트에 통과하는 프로덕션 코드 작성
테스트가 통과하면 프로덕션 코드를 리팩토링
이라는 큰 맥락을 가지고 테스트 코드를 먼저 작성한다. 그럼 이제 실패하는 테스트를 먼저작성하면된다는 건 알았다.
그럼 이제 막 코드를 치면되는 것일까? 아니다. 이것도 몇 가지 팁이 있다.
방법적으로 메서드를 실제로 작성할때는
given (준비) 테스트에 필요한 데이터를 셋팅하는 단계
when (실행) 직접 실행하는 단계
then (단언, 결과확인) 단언문(asserT,assertThat 등)을 통해 success, fail결과를 유도, 판단하는 단계
라는 단계를 지켜 테스트 메서드를 작성하면된다.
허허 너무 쉽네 저렇게 하면 되겠네! 해보자
코드
아하 대충 이렇게 만들면 되는 거구나!
그럼 전체적으로 다 만들어 보자. (사칙연산)
사칙연산만들고 여기에 오브젝트 분리, 뭐 단위 분리 등등 내가 할 수 있는걸 다해보자
죽어보자
오호 이제 대충 감을 알겠다.
이러한테스트가 주는 장점?
만약 요구사항 또는 오류가 발견되었다고 가정해보자
0/0 이 오류나요 고쳐줘요...
그럼 테스트가 없는 상황에서는? 문제 파악이 어렵다. 모든 케이스를 만들어야한다. 하지만 우리는 테스트를 잘 작성했기 때문에 given만 바꿔서 테스트를 해보면 된다.
만약 테스트가 없다면?
public static void main(String[] args) { Calculator calculator = new Calculator(); calculator.addRegistry("/", new Div()); double calculation = calculator.calculation("/", 0, 0); System.out.println(calculation); } 이 작업을 매번 만들어 줘야한다.
Java
복사
// 요구 사항을 위한 테스트 public static void main(String[] args) { divTest(); } static void divTest(){ //given 준비 단계 double prev = 0; double next = 0; //when 실행 단계 double result = div.operate(prev, next); //then 단언, 판단 단계 System.out.println(result); System.out.println(result==(prev / next)); } // result - NaN
Java
복사
고쳐보자
class Div implements Operator{ @Override public double operate(double prev, double next) { if (next == 0) return 0; // 아주 빨리 대처할 수 있다. return prev / next; } }
Java
복사
이 외에도 테스트가 주는 장점
서버를 실행하는 등의 시간을 절약할 수 있다(당연히 테스트 코드만 돌리니깐).
필요한 데이터를 미리 기입하고, 테스트가 끝나고 정리하는 등의 행동이 자동화되어 있다.
단위 테스트의 경우 테스트가 매우 빠르다(계산기 기준 메서드 단위로 테스트 하기 때문에 테스트 속도가 매우 빠르다).
문서로서의 역할이 가능하다(코드의 동작이 given, when, then의 순서로 이루어져 코드의 흐름과 결과 파악이 용이해진다).
테스트 코드 F.I.R.S.T 원칙
fast 빠르게 실행 되어야 한다(잘 분리해서 베이스케이스에서 실행되도록 만들어야한다).
independent 단위 테스트는 객체의 상태, 메서드, 이전 테스트 상태, 다른 메서드의 결과 등에 의존해서는 안된다. 따라서 단위테스트는 어떠한 순서로 실행하더라도 성공해야 한다(plus,minus 의 순서가 바뀌어도 테스트 결과에 영향이 있어선 안된다. 즉, 단위로 쪼갠 테스트 케이스의 순서가 바뀌어도 결과는 보장되어야 한다.).
repeatable 반복 가능해야한다.
sellf-validating 자체 검증이 가능해야한다. 수동 확인이 불필요하고 테스트가 실행성공 여부를 판단할 수 있어야한다.
timely 단위 테스트가 선행되고 난 이후 제품 코드를 작성해야한다(현실적으로는 어려울 수 있다).
물론 테스트 코드는 이것보다 더 많은 과정이 필요하다. 하지만 생략한 점이 많다. 필자가 보여주고 싶었던 것은 테스트 코드의 대략적인 작성방법과 테스트 코드의 효용이다. 이 예제를 통하여 테스트 코드를 대충 어떻게 작성하고 어떻게 활용하고 내 코드에 어떤 영향을 주는지 알았다.
스프링은 이렇게 길고 긴 과정을 생략할 수 있게 도와준다. 스프링을 쓰는 것 만으로도 충분히 오브젝트를 관심사 별로 잘 분리할 수 있다. 또한 DI를 통하여 기존 계산기에서 만든 static한 변수들을 제거할 수 있다. 더더더더더 좋은 테스트 코드를 만들 수 있다는 것이다. 이제부터는 스프링이 지원해주는 Junit을 좀 더 알아보자
Junit?
Junit5?
테스트 작성해보기
더 자세하게 알아보기
이게 끝일까? 아니다... Mockito가 남아있다.
기존 junit을 사용하면서 좋았던 점은 spring과 연계한 DI기능의 활용과 컨테이너 사용이다. 근데 생각해보면 단위 테스트에서 모든 빈을 등록하고 이를 통하여 객체를 평가하려니 작업이 많았다. 그래서 Mock 을 이용한 가짜 객체를 이용하여 junit의 테스트에 더욱 힘을 실어 준 것이다.
Mockito?
예시 상황?
Mock을 통해서 이룰 수 있는 것?