๐ฆ TDD๋ฅผ ์ฒ์ ์ ํ๊ฒ์ ์ฑ์ฉ ๊ณต๊ณ ์์์๋ค. ์ฐ๋์ฌํญ์๋ TDD๋ฅผ ์ด๋ค๋ ์๊ธฐ๊ฐ ์๋นํ ์์ฃผ ๋ณด์๋ค.
์ต๊ทผ TDD๋ ์ฃฝ์๋ค๋ผ๋ ์๋์์ฑ์ด ๋ณด์ด๋ ๊ฒ์ ๋ณด๋ฉด TDD์ ๋ํ ํ์๊ฐ์ด ๋๋ ๊ฐ๋ฐ์๊ฐ ๋ง์ ๋ณด์ธ๋ค.
์ ์ ํํ๋ ์ง, ๋นํ๋ฐ๋ ์ง, ๊ถ๊ธํ๋๊น ์ง์ ํด๋ณธ๋ค.
TDD ?
TDD(Test Driven Development) ์ํํธ์จ์ด ๊ฐ๋ฐ ๋ฐฉ๋ฒ ์ค ํ๋๋ก, ํ ์คํธ๋ฅผ ๋จผ์ ์์ฑํ๊ณ ์ด๋ฅผ ํต๊ณผํ๊ธฐ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ.
์ํํธ์จ์ด ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ํจ์จ์ ์ด๊ณ ์์ ์ ์ผ๋ก ๋ง๋ค๋ฉฐ, ํ์ง์ ๋์ด๋ ๋ฐ์ ๊ธฐ์ฌํ๋ค.
์ ์ฐจ๋ ๋ค์๊ณผ ๊ฐ๋ค.
1.ํ ์คํธ ์์ฑ
- ๋จผ์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ ํ ์คํธ๋ ์คํจํ๋ ๊ฒ์ ๊ธฐ๋ํ๋ค.
- ํ ์คํธ ์ผ์ด์ค๋ ์ฝ๋ ์์ฑ ์ ์ ๋ฏธ๋ฆฌ ์์ฑ๋๋ฉฐ, ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ์๊ตฌ์ฌํญ์ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋ค.
2.์ฝ๋ ์์ฑ
- ํ ์คํธ๋ฅผ ํต๊ณผํ๊ธฐ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
- ์ด๋ ์์ฑํ ์ฝ๋๋ ํ ์คํธ ์ผ์ด์ค๊ฐ ํต๊ณผ๋ ์ ์๋๋ก ํ๋ ์ต์ํ์ ์ฝ๋์ฌ์ผ ํ๋ค
3.ํ ์คํธ ์คํ ๋ฐ ํต๊ณผ ์ฌ๋ถ ํ์ธ
- ์์ฑํ ์ฝ๋๋ฅผ ์คํํ์ฌ ํ ์คํธ ์ผ์ด์ค๋ฅผ ํต๊ณผํ๋์ง ํ์ธํ๋ค.
- ์ด๋ ํ ์คํธ๊ฐ ์คํจํ๋ค๋ฉด ์ฝ๋๋ฅผ ์์ ํ์ฌ ๋ค์ ํ ์คํธ๋ฅผ ์คํํ๊ณ , ํ ์คํธ๊ฐ ํต๊ณผํ ๋๊น์ง ์ด๋ฅผ ๋ฐ๋ณตํ๋ค
4.์ฝ๋ ๋ฆฌํฉํ ๋ง
- ํ ์คํธ๊ฐ ํต๊ณผ๋ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ์ฝ๋์ ๊ฐ๋ ์ฑ, ์ ์ง๋ณด์์ฑ, ํ์ฅ์ฑ ๋ฑ์ ๊ฐ์ ํ๋ค.
์ด๋ฌํ ๋ฐฉ์์ผ๋ก TDD๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ๋์ฑ ์์ ์ ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ฉฐ, ์ฝ๋์ ํ์ง์ ๋์ผ ์ ์๋ค. ๋ํ, TDD๋ ์ฝ๋ ๋ณ๊ฒฝ์ฌํญ์ ๋ํ ์ ์ํ ํผ๋๋ฐฑ์ ์ ๊ณตํ์ฌ ๋ฒ๊ทธ๋ฅผ ๋ฏธ๋ฆฌ ์๋ฐฉํ ์ ์๋๋ก ๋์์ค๋ค.
๐ฅ ํ์์ ํ ์คํธ ์ผ์ด์ค ๋ฌธ์๋ฅผ ๋ง๋ ์ ์ด ์์ง๋ง,
์ ๋ํ ์คํธ ์ฌ์ฉํ ๊ฒฝํ์ ๊ทนํ ์ ์๋ค.
TDD์ 1๋ฒ ๋ถํฐ ์ฐจ๋ก๋ก ํด๋ณด๋ ค๊ณ ํ๋ค.
์คํจํ๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ๋ค. ๊ทธ๋ฆฌ๊ณ ์คํจํ๋ ๊ฒ์ ๊ธฐ๋ํ๋ค๋ ๊ฒ ๋ฌด์จ ๋ง์ธ์ง ์ดํด๋ฅผ ๋ชปํ์ง๋ง, ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ผ๋ ์ด์ผ๊ธฐ ๊ฐ๋ค.
1. ์คํจํ๋ ์ผ์ด์ค
TDD๋ฅผ ํด๋ณธ ๊ฒฝํ์ด ์๊ธฐ ๋๋ฌธ์ ์ ์ด๋ฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ ์๊ฐ์ด ๋ ๋ค. ํด๋์ค๋ถํฐ ์์๋๋ก ์ปดํ์ผ์ด ๋๋ ์์ผ๋ก ์์ฑํ๊ณ ์ถ์ ๋ง์์ด ๋ค์๋ค. ์ปดํ์ผ๋ ์๋๊ณ ๋นจ๊ฐ์ค๋ง ๋จ๊ฒ๋ํ๋ ํ์๋ฅผ ์น๋๊ฒ ์คํธ๋ ์ค๋ฅผ ์ค๋ค.
๊ทธ๋๋, ์ด๋ฐ ์์ผ๋ก, ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๋ฉ์๋๋ฅผ ๋ง๋ค์๋ผ๊ณ ์์ํ๋ฉฐ ์ต๋ํ ์์ฑ์ ํด๋ณธ๋ค.
2. ํต๊ณผํ๊ธฐ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๊ณ
๋ชจ๋ก ๊ฐ๋ ์์ธ๋ก ๊ฐ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
// 3๋ง ๋ฆฌํดํ๋ฉด ํ
์คํธ๋ ํต๊ณผํ๋ค.
class Calculator {
public int calculate(int a, int b) {
return 3;
}
}
3. ํ ์คํธ ์ผ์ด์ค๋ฅผ ํต๊ณผํ๋ ์ง ํ์ธํ๋ค.
3. ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ๋ค.
๋จ์ํ ์ฝ๋๋ง ์์ ํ๋ ๊ฒ ์๋ ๊ฐ๋ ์ฑ, ์ ์ง๋ณด์์ฑ, ํ์ฅ์ฑ ๋ฑ์ ๊ฐ์ ํ๊ฒ๋ ํด์ผ ํ๋ค.
์ฐ์ตํ ๊ฒ์ ๋ฐํ์ผ๋ก ์ค์ ๊ฒ์ํ์ ๊ธ์ ์ฐ๊ธฐ ์ํด ์ฐ์ตํ๋ฉฐ TDD๋ฅผ ์ตํ๋ ค ํด๋ณด์๋ค.
ํ์ด์ง์ ์ํ ์กฐํ๋ฅผ TDD๋ก ์ฐ์ตํ๋ค๋ฉด,
1. ์คํจํ๋ ํ ์คํธ
2. ํต๊ณผ๋ฅผ ์ํ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ ,
// PostRepositoryCustom.java
public List<PostDto> getPostsWithSearchPaging(Pageable pageable, String search) {
List<PostDto> posts = new ArrayList<>();
posts.add(new PostDto(10L
,"title"
,"content"
, new UserDto("name","email","1123")
,null));
return posts;
}
3. ํ ์คํธ ํ์ธํ๊ณ ,
4. ๋ฆฌํฉํ ๋งํ๋ค.
public List<PostDto> getPostsWithSearchPaging(Pageable pageable, String search) {
BooleanBuilder booleanBuilder = new BooleanBuilder();
if (StringUtils.hasText(search)) {
booleanBuilder.or(qPost.postTitle.contains(search));
booleanBuilder.or(qPost.postContent.contains(search));
booleanBuilder.or(qPost.user.nickname.contains(search));
}
booleanBuilder.and(qPost.isDeleted.eq('N'));
return queryFactory.select(Projections.fields(PostDto.class
,qPost.id
,qPost.postTitle
,qPost.postContent
,qPost.createdBy
,qPost.createDt
,qPost.recommendCount
)).from(qPost)
.where(booleanBuilder)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(qPost.createDt.desc())
.fetch();
}
// TDD
// ์์ฑํ ์ฝ๋๊ฐ ๋ ๋๊น์ง ํ
์คํธํ๋ฉฐ ๋ฆฌํฉํ ๋ง.
๊ฐ์ธ์ ์ผ๋ก ๋๋ ์๊ฐ์ ํ์ JUnit์ ์ ์ฌ์ฉํ์ง ์์๊ธฐ์ Swagger-ui๋ฅผ ํตํ ํ ์คํธ๋ postMan์ ํตํ ํ ์คํธ๋ฅผ ์์ฃผ ํ์๋ค.
Swagger-ui๋ฅผ ํตํ ํ ์คํธ ํน์ postMan์ ํตํ ํ ์คํธ๋ณด๋ค, ์ฌ๋ฌ๋ฒ์ ํ ์คํธ๋ฅผ ํ๊บผ๋ฒ์ ํ๊ฑฐ๋, ๊ฐ๊ธฐ ๋ค๋ฅธ ํ ์คํธ๋ค์ ๋ฐ๋ก๋ฐ๋ก ํ ๊ฒฝ์ฐ ์๊ฐ์ด ๋ง์ด ๋จ์ถ๋จ์ ๋๊ผ๋ค.
--> ๋ฌผ๋ก ์ด๋ TDD์ ์ฅ์ ์ด๊ธฐ๋ ํ์ง๋ง, Junit์ ํ์ฉํ ํ ์คํธ์ ์ฅ์ ์ด ๋ ํฌ๋ค๊ณ ์๊ฐํ๋ค.
TDD ๋ฐฉ์์ ๋จ์ ?
๊ฐ๋ฐ ์๋๊ฐ ๋๋ ค์ง๋ค.
SI ํ๋ก์ ํธ์์๋ ์ํํธ์จ์ด์ ํ์ง๋ณด๋ค ๋ฉ๊ธฐ์ผ ์ค์๊ฐ ํจ์ฌ ์ค์ํ๊ธฐ ๋๋ฌธ์ TDD ๋ฐฉ์์ ์ ์ฌ์ฉํ์ง ์๋๋ค.
Test๋ฅผ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ์๊ฐ๋ ๊ฐ๋ฐ ์๊ฐ์ ํฌํจ๋๋ค.
TDD is dead. Long live testing ?
ํ์ฐธ ์ง๋ TDD ๋ ผ์์ธ๋ฐ ์ด์ ์ผ ์๋ค๋ ๊ฒ์ด ๋ถ๋๋ฝ๋ค.
๐ tdd๋ ์ฃฝ์๋ค: Google ๊ฒ์
www.google.com
querydsl ์ฌ๋ผ์ด์ฑ ํ ์คํธ ์ค์ ?
Junit ๋ฒ์ : 5. xx ์ ๋๋ค.
TestClass ์ค์ :
TestConfig ์ค์ :
์์ ๊ฐ์ ์ค์ ์,
Junit ์์ ์์ฑ์ ์ฃผ์ ๋ฐฉ์์ ์ธ์ํ์ง ๋ชปํด์์ด๋ค.
๋ฐ๋ผ์ Spring์๊ฒ ์์ํ์ฌ Autowired๋ฅผ ํตํด ๊ฐ์ฒด ์์กด์ฑ์ ์ฃผ์ ๋ฐ์์จ๋ค.
๋ฐ๋ผ์, TestConfig๋ฅผ ํตํด ์ค์ ์ ์ฃผ์ ํ์ง ์๊ณ ์ฐ๋ฉฐ, ์์ ๊ฐ์ ์ปค์คํ Repository์์ JPAQueryFactory๋ฅผ ์์ฑ์ ๋ฐฉ์์ผ๋ก ์ธ ๊ฒฝ์ฐ,
Junit Test ์์ ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๋ฅผ ๋ง๋๊ฒ ๋๋ค.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.org.lessortalk.post.service.PostServiceImplTest': Unsatisfied dependency expressed through field 'postRepositoryCustom'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.org.lessortalk.post.repository.PostRepositoryCustom' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Bean ๊ฐ์ฒด๋ฅผ ์ฐพ์ง ๋ชปํ๋ฏ๋ก ํ ์คํธ ํด๋์ค์ ๋ชจ๋ ํ ์คํธ๊ฐ ์คํจํ๋ค๋ฉด, ์ ์ค์ ์ ๋จผ์ ํ์ธํด๋ณด์์ผ ํ๋ค.
์ฐธ๊ณ : https://jyami.tistory.com/124
QueryDSL ์ฌ๋ผ์ด์ฑ ํ ์คํธ(@DataJpaTest) / Test Bean ๋ฑ๋ก
QueryDSL ์ฌ๋ผ์ด์ฑ ํ ์คํธ ๋ฐฉ๋ฒ์ ๋ํด ๊ธฐ๋ก์ ๋จ๊ธด๋ค. ๋ด๊ฐ ์ฃผ๋ก ์ฌ์ฉํ๋ Querydsl ํจํด์ CustomRepository๋ฅผ ๋ง๋๋ ๋ฐฉ์์ด๋ค. docs.spring.io/spring-data/jpa/docs/2.1.3.RELEASE/reference/html/#repositories.custom-implementa
jyami.tistory.com
'JAVA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JAVA] compareTo (0) | 2023.06.27 |
---|---|
[JAVA] JSP์ ์๋ฒ์ฌ์ด๋๋ ๋๋ง(SSR) (0) | 2023.04.19 |
[JAVA] Gabage Collection (0) | 2022.12.13 |
java directory copy / progress bar (0) | 2022.06.11 |
springboot / querydsl ์ค์ (0) | 2022.05.31 |