재사용 가능하고 복잡한 테스트 객체를 자동으로 생성해주는 자바 라이브러리
테스트 수행에 필요한 픽스쳐를 간편하게 바인딩해주고 랜덤한 값을 넣어줄 수 있는 라이브러리
테스트코드의 중요성은 제쳐두고, 테스트코드를 작성하는데 소요되는 시간이 너무 많이든다
개발하다보면 편협한 시야로, 엣지케이스를 놓치는 경우가 생긴다
다양한 테스트로 커버리지를 높이기 위해 다양한 객체생성으로 코드가 길어진다
길어진 given 단계 때문에 코드의 가독성이 떨어진다
등등 다양한 이유가 있는데, Fixture Monkey
를 사용한 코드와 그렇지 않은 코드의 차이는 다음과 같다
Fixture Monkey
미사용@Test
public void getEntryCreatePostDtoTest01() throws Exception
//given
PostCreateDto.Survey survey =
PostCreateDto.Survey
.builder()
.title("survey title")
.question(List.of("a", "b", "t"))
.build();
PostCreateDto.CreatePostRequest createPostRequest =
PostCreateDto.CreatePostRequest
.builder()
.title("post title")
.text("wanna text!")
.isNotice(false)
.isRecentNotice(false)
.tagId(1L)
.uuid("1234-qwer-asdf-zxcv")
.hasSurvey(true)
.survey(survey)
.build();
//when
EnterPostCreateDto.Response result = createPostPageBusiness.getEntryCreatePostDto(createPostRequest, 1L);
//then
assertThat(result.getIsNotice()).isEqualTo(false);
assertThat(result.getTime()).isEqualTo(3);
assertThat(result.getUuid()).isEqualTo("1234-qwer-asdf-zxcv");
}
Fixture Monkey
사용@Test
public void getEntryCreatePostDtoTest02() throws Exception
//given
PostCreateDto.Survey survey = MonkeyUtil.monkey().giveMeOne(PostCreateDto.Survey.class);
PostCreateDto.CreatePostRequest createPostRequest =
MonkeyUtil.monkey().giveMeBuilder(PostCreateDto.CreatePostRequest.class).set("survey", survey).sample();
//when
EnterPostCreateDto.Response result = createPostPageBusiness.getEntryCreatePostDto(createPostRequest, 1L);
//then
assertThat(result.getIsNotice()).isEqualTo(createPostRequest.getIsNotice());
assertThat(result.getTime()).isEqualTo(3);
assertThat(result.getUuid()).isEqualTo(createPostRequest.getUuid());
}
given 파트에서 임의의 객체를 만들어서 넣어줬었던 기존방식에서 Fixture Monkey
를 활용하여 코드량이 현저하게 줄어든것을 볼 수 있다
개인적으로 생각한 Fixture Monkey
의 장점은 다음과 같다
Fixture Monkey
에서 자동으로 만들어주니 노동력이 감소한다// 임의 Integer 생성
Integer number = FixtureMonkey.create().giveMeOne(Integer.class);
// 100 이상 임의 Integer 생성
Integer number = FixtureMonkey.create().giveMeBuilder(Integer.class)
.set(Arbitraries.integers().greaterOrEqual(100))
// 임의 객체 생성
Sample sample = FixtureMonkey.create().giveMeOne(Sample.class);
// 조건있는 임의 객체 생성
Sample sample = FixtureMonkey.create().giveMeBuilder(Sample.class)
.set("title", Arbitraries.strings().ofMinLength(1))
.set("age", notNull());
객체는 Bean Validation에 정의되어있는 대로 범위 내 객체가 자동으로 생성된다
다음과 같은 Bean Validation을 설정한 Entity가 있다고 가정한다
@Data
public class Sample {
@NotNull
private Long id;
@NotBlank
private String orderNo;
@Size(min = 2, max = 10)
private String productName;
@Min(1)
@Max(100)
private int quantity;
@Min(0)
private long price;
@Size(max = 3)
private List<@NotBlank @Size(max = 10) String> items = new ArrayList<>();
@PastOrPresent
private Instant orderedAt;
}
Fixture Monkey
를 활용하여 자동으로 객체를 생성한다면 제공되는 필드값은 다음의 테스트를 만족한다
@Test
@RepeatedTest(100)
void test() {
Sample sample = FixtureMonkey.create().giveMeOne(Sample.class);
then(sample.getId()).isNotNull(); // @NotNull
then(sample.getOrderNo()).isNotBlank(); // @NotBlank
then(sample.getProductName().length()).isBetween(2, 10); // @Size(min = 2, max = 10)
then(sample.getQuantity()).isBetween(1, 100); // @Min(1) @Max(100)
then(sample.getPrice()).isGreaterThanOrEqualTo(0); // @Min(0)
then(sample.getItems()).hasSizeLessThan(3); // @Size(max = 3)
then(sample.getItems()).allMatch(it -> it.length() <= 10); // @NotBlank @Size(max = 10)
then(sample.getOrderedAt()).isBeforeOrEqualTo(Instant.now()); // @PastOrPresent
}
Fixture Monkey Github 또는 공식문서에서 훨씬 많은 정보를 얻을 수 있다
공식문서가 약간 불친절하다고 한다
좋은 내용 잘 보고 갑니다!