들어가기 앞서
이번 글에서는 네이버의 Fixture Monkey 라이브러리에 대해 설명 드릴 예정입니다. Fixture Monkey는 테스트 코드 작성시 fixture 생성을 편리하게 해주는 라이브러리 입니다. Java와 Kotlin을 사용하는 개발자 분들이시라면 꼭 추천 드리며, 블로그 글 읽기가 귀찮으신 분들은 Naver D2 영상이나 공식 페이지 참조 부탁드립니다 :)
NAVER D2
테스트 객체는 엣지 케이스까지 찾아주는 Fixture Monkey에게 맡기세요
bridge-now.naver.com
https://naver.github.io/fixture-monkey/v1-1-0-kor/docs/introduction/overview/
개요
Fixture Monkey # Fixture Monkey는 테스트 객체를 쉽게 생성하고 조작할 수 있도록 고안된 Java 및 Kotlin 라이브러리입니다. 이 라이브러리는 테스트 작성을 간편하게 하기 위해 필요한 테스트 픽스처를
naver.github.io
Fixture Monkey 란?
Fixture Monkey는 네이버에서 개발한 Java 기반의 테스트 데이터 생성 라이브러리입니다. Fixture Monkey는 Property Based Testing(PBT) 라이브러리 입니다. Property Based Testing(PBT)은 입력값을 랜덤하게 생성하여, 특정 조건(Property)이 항상 만족되는지 검증하는 테스트 기법입니다. 즉, 임의의 입력을 생성하여 여러 번 실행하는 테스트 방식으로, 경계값이나 예외적인 상황을 자동으로 찾아낼 수 있습니다. 따라서 테스트 코드에서 테스트 객체를 직접 생성하는 수고를 덜고, 일관된 테스트 데이터를 빠르게 만들어낼 수 있도록 도와줍니다. 네이버 내부 뿐만 아니라 많은 개발자들을 통해서 검증이 되었기 때문에 크게 걱정하지 않아도 됩니다.
Fixture Monkey 장점
1. fixture 생성의 간결함
테스트 코드를 작성하실 때, 다들 fixture 생성이 너무 귀찮다고 생각하신 분들이 분명 많이 계실거라고 생각합니다. List일때 혹시 일일이 혹시 값을 지정 하고 계신가요?
일반적인 테스트 코드 작성
@DisplayName("일반적은 fixture 생성")
@Test
void findAllByProduct() {
// given
Product product1 = createProduct("001", HANDMADE, SELLING, "아메리카노", 4000);
Product product2 = createProduct("002", HANDMADE, HOLD, "카페라떼", 4500);
Product product3 = createProduct("003", HANDMADE, STOP_SELLING, "팥빙수", 7000);
List<Product> products = List.of(product1, product2, product3);
// when
// then
}
Fixture Monkey 테스트 코드 작성
@DisplayName("fixture Monkey 사용한 방법")
@Test
void findAllByProduct() {
// given
List<Product> products = fixtureMonkey.giveMe(Product.class, 3);
// when
// then
}
Fixture Monkey를 사용하면 정말 간단하게 List 형식의 fixture도 쉽게 만들수 있습니다.
2. 경계값 검증
일반적으로 운영중인 서비스에서 장애가 발생하는 경우는 전혀 예상하지 못한 값들에서 주로 발생합니다. 하지만 개발자분들이 작성하는 테스트 코드의 fixture들은 "아메리카노", "팥빙수" 등 당연히 문제가 발생하지 않는 값으로 테스트를 하며, 경계값으로 테스트 코드를 작성하더라도 1~2개 작성이 전부이기에 의미있는 경계값 검증을 하기 힘듭니다. 하지만 Fixture Monkey를 사용하면 이러한 경계값을 다양하게 검증할 수 있습니다.
Fixture Monkey로 생성된 값을 확인해 보면 아래와 같습니다.
- Product(id=null, productNumber=ꙩ豞䦤ﭻꃭ뉟燂ꅱ鞗鯼뭥옧鲎ⱒ錣ᇃ촛惰鲸չ簜Ӌ뀓訟猶쯮체罱ⲵ澺, type=HANDMADE, sellingStatus=SELLING, name=揑琚擟쳨洱欯斛芀皶峍䯥说瑶쮄წ, price=1742987),
- Product(id=null, productNumber=❔嗀谗䤎哖쵔瞿蹀킰ےꘆ栠휋憽遭슱႙틥шﴳ⠌悁稅볓蟣蜨꛵C脬䑗殡쥃볐䱢箋א蛐霃吶凑칽ꈪ阧찯꓂જ珹臶军綂頇濽ꟹ艀漒覮쵀浃샗⼔祮ﴣ菠徽㇞攴荋呋紬얭甔帗쌸鬲퉌፡롂湌媕ۗ嘐࣡뽡䯘횜훩鹧燣è塭㴗퇽婼䛾䖂폫㻔ᾼ䔸騛㫵, type=null, sellingStatus=SELLING, name=ᤜ䰟抈瓾簦턕ꍕ엵喸൛檊찴셾Ꝼ︙, price=-4371821),
- Product(id=1682572, productNumber=ᣲ拾鸂ﶆ㡟⢝⸎換蓼쭒זּ㳗㋸, type=BOTTLE, sellingStatus=null, name=垱设࡞쫃鴄킲꿗卦ꭅ꿌, price=-2915)]
일반적인 사람들이 예쌍하지 못한 다양한 경계값들이 들어가는 것을 확인할 수 있습니다. String에는 특수기호가 들어가고 int에는 음수와 양수 값들이 들어가는 것을 확인할 수 있습니다. 또한 Enum은 선언된 값 안에서 랜덤으로 선택되는 것을 알 수 있으며 null 여부에 대한 검증도 가능합니다.
희망하는 정해진 값도 설정이 가능합니다.
@Test
void findAllBySellingStatusIn() {
// fixture
var products = fixtureMonkey.giveMeBuilder(Product.class)
.set("type", ProductType.BAKERY)
.setNull("name")
.sampleList(3);
log.info(products.toString());
}
giveMeBuilder를 사용하면 특정 값을 지정할 수 있으며, null, notNull, 최소 글자수, 최대 글자수 등등 다양한 설정을 할 수 있습니다.
3. @Validation 어노테이션과 호환으로 편리한 데이터 생성
객체 필드에 생성한 Java의 검증 애너테이션(@Min, @NotNull, @Size 등)을 자동으로 인식하여 제약 조건을 만족하는 데이터를 생성할 수 있습니다.
package star.cafekiosk.product;
import jakarta.persistence.*;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@ToString
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
private String productNumber;
@Enumerated(EnumType.STRING)
private ProductType type;
@Enumerated(EnumType.STRING)
private ProductSellingStatus sellingStatus;
@NotNull
private String name;
@Min(0)
@Max(10000)
private int price;
}
Product 객체의 필드에 Validation 어노테이션을 붙여 보겠습니다.
- price : @Min(0), @Max(10000)로 인해 price는 0~10000 사이의 숫자만 얻을 수 있습니다.
- name : @NotNull 조건으로 인해 null을 가질 수 없습니다.
Fixture Monkey로 생성된 Product 값을 확인해 보면 아래와 같습니다.
private final FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
.plugin(new JakartaValidationPlugin()) // Jakarta Validation 적용
.build();
@Test
void findAllBySellingStatusIn() {
// fixture
var products = fixtureMonkey.giveMe(Product.class,3);
log.info(products.toString());
}
Product(id=null, productNumber=없읇졯徳쵎쬓餩ᒘ뻄﹫츨닁뵃ዋ崡諺ᗵ欌䣎泲䵌깋, type=null, sellingStatus=HOLD, name=䳎錠핁誄䚈뚜葨篐⨏韜혷縠萩쨒鮭輓Ằᡔꇁ⮈佸浖ኚ뷕얛凰⣩愬甅⚘끪, price=745)
Product(id=30, productNumber=ᶻ扱麸擣锒Ⓦ븁ꀆ힌禋᪰㟱펢Ԕ倚娕婏뾆镽, type=BOTTLE, sellingStatus=STOP_SELLING, name=ꏆ⸑밆뉶⬿덟, price=7)
Product(id=10761562, productNumber=뙅Ӆꬁ捍ś⢒댿腾舸⹊釚瘃쯂消玑흜麬褞晹촦黬ᇀ鷚䎍륗, type=HANDMADE, sellingStatus=SELLING, name=꧖ᆕ鞿팤⅗哅罱喹㷕뺩㴷垣틞㲾, price=44)
이처럼 Fixture Monkey는 Validation 어노테이션을 통해 간단하게 데이터 생성도 가능합니다.
의미 있는 테스트 코드에 대해 알아보자 <-- 제 블로그의 테스트 코드와 관련된 다른 글도 추천 드립니다 :)
reference)
https://github.com/naver/fixture-monkey
https://naver.github.io/fixture-monkey/v1-0-0-kor/docs/introduction/overview/
https://oliveyoung.tech/2024-04-01/testcode-use-fixture-monkey/
'테크톡 딥다이브' 카테고리의 다른 글
| 데이터베이스 락 (Lock) with MySQL (0) | 2025.03.31 |
|---|---|
| 스프링 Transaction 전파 속성 (0) | 2025.03.31 |
| 의미 있는 테스트 코드에 대해 알아보자 (0) | 2025.02.24 |
| 카카오 선물하기 팀의 캐싱 전략 (하이브리드 캐시와 캐시 웜업 자동화) (1) | 2025.01.07 |
| DB Replication (with 우아한 테크 코스's 테크톡) (4) | 2025.01.03 |