티스토리 뷰
# 이 게시글은 "토비의 스프링" 책을 보고 정리를 위해 기록해둔 게시글입니다.
[이전글]
볶음밥 1장 - 1,2,3: 자바빈, 디자인 패턴(템플릿 메소드, 팩토리 메소드, 전략 패턴), 관심사의 분리, SOLID 및 객체지향 약간
볶음밥 1장 - 4,5,6: 제어의 역전, 프레임워크 vs 라이브러리, 스프링 IoC 및 용어 정리, 싱글톤, 동일성 vs 동등성, 빈의 스코프
볶음밥 1장 - 7: 의존관계 주입(DI), DL, IoC
[2장] 테스트
변화하는 애플리케이션에 효과적으로 대응할 수 있는 전략
1. IoC/DI 컨테이너를 이용해 확장과 변화를 고려한 객체지향적 설계
2. 만들어진 코드를 확신할 수 있게 해주고 변화에 유연하게 대처할 수 있도록 자신감을 주는 "테스트"
[2-1] UserDaoTest 다시보기
테스트 = 내가 의도한 대로 코드가 정확히 동작하는지를 확인해 내가 만든 코드를 확신할 수 있도록 해주는 작업.
이 과정을 통해 코드나 설계의 결함을 발견하고, 디버깅을 통해 결함을 제거한다.
[웹을 통한 DAO 테스트의 문제점]
웹을 통해 DAO를 테스트하기 위해서는 DAO 뿐만 아니라 서비스 계층, 프론트엔드 작업, 컨트롤러도 만들고 등등 부가적으로 해야하는 일이 너무나도 많다. 오히려 배보다 배꼽이 더 커지는 느낌이다. 또한 이는 DAO 고유의 테스트가 아니다.
테스트 역시 관심사의 분리를 통해 가능하면 작은 단위로 쪼개는 것이 바람직하다.
-> 그래서 해야하는 것이 바로 "단위 테스트"(Unit Test)
[단위테스트]
- 일반적으로 단위는 작을수록 좋다
--> 여기서 단위의 범위는 상대적이다. 하나의 관심에 집중해서 효율적으로 테스트할 수 있는 범위의 단위.
- "통제할 수 없는" 외부의 리소스에 의존하는 테스트는 단위 테스트가 아니라고 볼 수도 있다 (= 썩 바람직하지는 않다)
- 단위테스트는 개발자가 설계하고 만든 코드가 원래 의도한 대로 동작하는지를 빨리 확인해보기 위해서이다.
- 테스트는 "자동"으로 수행되도록 하는 것이 중요하다 (Run만 해주면 따로 사용자 입력 없이 알아서 다 되야한다는 뜻)
--> 테스트는 자주 반복될 수 있기 때문
* 단위테스트는 항상 일관성 있는 결과가 보장되어야 한다
- DB에 남아있는 데이터 등 외부 환경에 영향을 받으면 안된다
- 테스트 실행 순서에 영향을 받으면 안된다
[2-2] UserDaoTest 개선
개선사항 = 테스트 검증의 자동화
- sout으로 찍어주는것은 내가 직접 출력 결과를 확인해보고 잘 됐는지 안됐는지를 확인해야한다
- 이것보다 그냥 테스트 성공 / 실패로 바로 알려주는 것이 훨씬 좋다. 테스트가 많아질수록 더더더욱..
[2-3] 테스팅 프레임워크 JUnit
자동화된 테스트를 도와주는 짱 프레임워크가 바로 jUnit(xUnit)!!
- jUnit도 프레임워크 = IoC 원리가 적용되어있다
토비의 스프링이 아무래도 오래된 책이다보니 프레임워크 버전이 좀 다른것 같긴 하다
그래서 난 이전에 사용했던 jUnit5로 사용하기로 했다. 스프링부트를 사용했을때는 테스트용 프레임워크까지 싹다 포함해주는데 스프링부트는 사용하지 않았기에 mavenRepository 사이트에서 프레임워크를 검색한 다음에 pom.xml에 추가해줘야한다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.21</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
<scope>test</scope>
</dependency>
assertj는 assertThat()을 사용하기 위해 추가.
스프링부트가 편한게 이런 dependency들을 스프링부트 스타터 한방에 만들어주니 내가 신경쓸 필요가 없다는 것이다
* 테스트를 안만드는 것도 위험하지만, 성의없는 테스트를 작성해 문제있는 코드를 테스트에 성공하게 만드는 것은 더더욱!!! 위험하다.
* 성공하는 테스트 케이스보다 실패하는 테스트 케이스를 만드는 것이 더더더욱 중요하다!!
* TDD(Test Driven Development): 실패하는 테스트 코드를 먼저 만들고 나서 테스트를 성공하게 해주는 코드를 나중에 작성하는 개발 방법.
TDD의 장점: 오류의 유무를 가장 빠르게 알아낼 수 있음, 불안정성 해소.
TDD의 단점: 생산성 저하. 귀찮음
[JUnit의 기본적인 동작 방식]
1. 테스트 클래스에서 @Test가 붙은 public이고 void형이며 파라미터가 없는 테스트 메소드를 모두 찾는다
2. 테스트 클래스의 오브젝트를 하나 만든다
3. @Before(-> jUnit5에서 @BeforeEach로 변경됨)가 붙은 메소드가 있으면 먼저 실행한다
4. @Test가 붙은 메소드를 하나 호출하고 테스트 결과를 저장해둔다
5. @After(-> @AfterEach)가 붙은 메소드가 있으면 실행한다
6. 나머지 테스트 메소드들에 대해 2~5번을 반복
7. 저장된 테스트 결과들을 종합해 출력
* @Before-, @After- 는 테스트 메소드가 직접 호출하는 것이 아니기 때문에 서로 주고받아야할 오브젝트가 있다면 인스턴스 변수를 사용해야 한다!
* 각 테스트 메소드를 실행할 때마다, 테스트 클래스의 오브젝트를 새로 만든다
-> 한번 만들어진 테스트 클래스의 오브젝트는 하나의 테스트 메소드를 실행하고 버려진다.
-> 각 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 보장해준다
* 테스트 메소드의 일부에서만 공통적으로 사용되는 코드가 있다면 메소드를 추출해서 사용하는 편이 좋다.
* 픽스쳐(fixture): 테스트를 수행하는 데 필요한 정보나 오브젝트.
- 주로 여러 테스트에서 반복적으로 사용되는 경우가 많기에 @Before 메소드를 이용해 생성해두고 돌려쓰는게 좋다.
class UserDaoTest {
// Fixture
private UserDao dao;
private User user1;
private User user2;
private User user3;
////
@BeforeEach
public void setUp() {
ApplicationContext ac = new AnnotationConfigApplicationContext(DaoFactory.class);
this.dao = ac.getBean("userDao", UserDao.class);
this.user1 = new User("id1", "name1", "pw1");
this.user2 = new User("id2", "name2", "pw2");
this.user3 = new User("id3", "name3", "pw3");
}
...
[2-4] 스프링 테스트 적용
이것도 책이랑 버전차이가 조금 있다.
스프링부트를 사용하면 @SpringBootTest 애노테이션 하나만 클래스 위에 붙여주면 된다.
근데 난 지금 스프링부트를 안쓰고 하고 있는 중이었어서
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {DaoFactory.class})
class UserDaoTest {
....
}
이렇게 붙여줘야 한다. @ContextConfiguration 내 class 이름은 애플리케이션 컨텍스트의 위치를 지정해주면 된다.
[2-5] 학습 테스트
학습 테스트: 자신이 만들지 않은 프레임워크다 다른 개발자들이 만든 라이브러리 등에 대해서도 테스트 해보는 것
- 다양한 조건에 따른 기능을 손쉽게 확인 가능
- 호환성 검증을 도와준다
- 새로운 기술을 공부하는 좋은 방법 중 하나
버그 테스트: 코드에 오류가 있을때 그 오류를 가장 잘 드러내줄 수 있는 테스트
- 일단 테스트를 실패하도록 만든 다음 -> 테스트가 성공할 수 있도록 애플리케이션 코드를 수정하는 방법.
- 테스트의 완성도를 높여준다
- 버그를 효과적으로 분석할 수 있게 해준다.
- 기술적인 문제를 해결하는데 도움을 준다.
[결론]
1. 테스트는 자동화 되어야 하고, 빠르게 실행될 수 있어야 한다.
2. 테스트 결과는 일관성이 있어야 한다
3. 테스트는 포괄적으로 상세하게 작성되어야 한다. 충분한 검증 없는 테스트는 없는것보다 더 안좋을 수도 있다
4. 단위테스트를 생활화하자
5. 테스트 하기 쉬운 코드가 좋은 코드다
테스트 섹션은 아무래도 버전 차이도 나고 하다보니 빠르게 넘겼다..junit은 따로 공부하자..
'웹 > Spring' 카테고리의 다른 글
스프링 볶음밥 - 4장 - 예외 (0) | 2022.07.04 |
---|---|
스프링 볶음밥 - 3장 - 템플릿/콜백 (0) | 2022.07.02 |
스프링 볶음밥 - 1장 - 7(IoC/DI/DL) (0) | 2022.07.01 |
스프링 볶음밥 - 1장 - 4,5,6 (0) | 2022.07.01 |
스프링 볶음밥 - 1장-1,2,3 (0) | 2022.06.29 |