나는 이전까지 레거시 환경에서 테스트코드에 대해 들어본적이 없었고
jUnit 도 모르니 테스트를 한다면 화면 띄우고 디비에 연결해서
입력폼에 값 하나씩 입력하고 확인 버튼을 누르는 등 직접 결과를 확인했다
하지만 인강과 관련 개발서적(TDD)를 읽어보니
테스트에 대해 너무 무지했다는 걸 깨달았다
진행 중인 스터디의 주제로 리팩토링이 나왔는데
요구사항에 테스트 코드가 있고 스터디장이 테스트에 대해 설명을 해줘서 손쉽게 접근을 했다.
테스트 코드는 Gilded Rose 의 리팩토링 과제로 진행했다
다음은 요구사항의 일부분이다
Gilded Rose 요구사항 정의
안녕하세요, Gilded Rose 팀에 오신 것을 환영합니다. 우리는 최고의 위치를 가진 작은 여관이며 최고급 상품만을 사고 판매합니다. 하지만 우리의 제품은 판매해야하는 날짜가 가까워지는 상품은 지속적으로 품질이 저하되고 있습니다. 우리는 이러한 상품들을 관리하고 있으며 아래와 같은 로직으로 돌아가는 시스템을 갖추고 있습니다.
- 모든 아이템은 아이템을 판매해야하는 날짜를 나타내는 "SellIn" 값을 가집니다.
- 모든 상품에는 상품의 가치는 나타내는 "Quality" 값이 있습니다.
- 하루가 지날 때마다 시스템은 모든 상품의 두 값을 모두 낮춥니다.
현재까지 구현된 시스템의 흥미로운 부분은 아래와 같습니다.
- 판매 기한이 지나면 "Quality"가 2배 빠르게 저하됩니다.
- 모든 상품의 "Quality"는 0 이하로 내려가지 않습니다.
- 모든 상품의 "Quality"는 50을 넘지 않습니다.
- "Aged Brie" 상품은 날이 지날수록 "Quality"가 증가됩니다.
- 전설적인 상품인 "Sulfuras"는 판매할 필요도 없고, 품질이 저하될 필요도 없습니다. 또한 전설적인 상품이므로 "Quality" 값은 80으로 설정됩니다.
- "Backstage passes" 상품은 "Aged Brie"처럼 날이 지날수록 "Quality"가 증가됩니다. "SellIn" 값에 따라, 10일 이하일 때는 2, 5일 이하일 때는 3씩 증가하지만, 판매 기한이 지나면 "Quality"는 0이 됩니다.
최근에 창조된 아이템 공급 업체와 계약했기 때문에, 시스템의 변경이 필요합니다.
- "Conjured" 상품은 일반적인 상품보다 "Quality"가 2배 빠르게 저하됩니다.
updateQuality 함수를 자유롭게 변경하고 필요하다면 새로운 코드를 추가하세요.
아래와 같은 순서로 commit을 생성해주면 좋을 것 같습니다.
- 시스템이 동작하는 모든 로직을 테스트할 수 있는 단위 테스트를 작성하세요.
요구사항은 레거시 코드로 구현이 된 상태다
public class Item {
public String name;
public int sellIn;
public int quality;
public Item(String name, int sellIn, int quality) {
this.name = name;
this.sellIn = sellIn;
this.quality = quality;
}
@Override
public String toString() {
return this.name + ", " + this.sellIn + ", " + this.quality;
}
}
class GildedRose {
Item[] items;
public GildedRose(Item[] items) {
this.items = items;
}
public void updateQuality() {
for (int i = 0; i < items.length; i++) {
if (!items[i].name.equals("Aged Brie")
&& !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].quality > 0) {
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].quality = items[i].quality - 1;
}
}
} else {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].sellIn < 11) {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
if (items[i].sellIn < 6) {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
}
}
}
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].sellIn = items[i].sellIn - 1;
}
if (items[i].sellIn < 0) {
if (!items[i].name.equals("Aged Brie")) {
if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
if (items[i].quality > 0) {
if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
items[i].quality = items[i].quality - 1;
}
}
} else {
items[i].quality = items[i].quality - items[i].quality;
}
} else {
if (items[i].quality < 50) {
items[i].quality = items[i].quality + 1;
}
}
}
}
}
}
이를 기반으로 곧바로 테스트 코드를 작성했다
- 하루가 지날 때마다 시스템은 모든 상품의 두 값을 모두 낮춥니다.
@Test
void 하루마다_퀄리티_감소() {
List<Item> items = new ArrayList<>();
Item item = Item.builder().
name(Constants.ETC).
sellIn(10).
quality(10).
build();
items.add(item);
gildedRoseService.updateQuality(items);
assertEquals(9, item.getQuality());
}
- 판매 기한이 지나면 "Quality"가 2배 빠르게 저하됩니다.
@Test
void 판매기한초과_퀄리티_2배_감소() {
List<Item> items = new ArrayList<>();
Item item = Item.builder().
name(Constants.ETC).
sellIn(0).
quality(10).
build();
items.add(item);
gildedRoseService.updateQuality(items);
assertEquals(8, item.getQuality());
}
- Backstage passes" 상품은 "Aged Brie"처럼 날이 지날수록 "Quality"가 증가됩니다. "SellIn" 값에 따라, 10일 이하일 때는 2, 5일 이하일 때는 3씩 증가하지만, 판매 기한이 지나면 "Quality"는 0이 됩니다.
@ParameterizedTest
@CsvSource({"3, 13", "6, 12", "11, 11"})
void BACKSTAGE_PASSES_판매일별_퀄리티_증가(int sellIn, int dayQuality) {
List<Item> items = new ArrayList<>();
Item item = Item.builder().
name(Constants.BACKSTAGE_PASSES).
sellIn(sellIn).
quality(10).
build();
items.add(item);
gildedRoseService.updateQuality(items);
assertEquals(dayQuality, item.getQuality());
}
다른 요구사항도 같은 방식으로 테스트 코드를 작성했다
이미 구현된 로직을 기반에서 작성을 해서 그런지 금방 금방 진행이 되었고 (리팩토링 도전한 다음에 다시 테스트 코드를 확인해야한다)
잘 몰랐던 테스트 코드에 대한 개념을 익숙하게 만들어준 기회가 되었다
이제는 예전에 했던 비효율적인 테스트가 아닌
개발자라면 개발자다운 테스트로 진행해야겠다
그리고 보니 테스트 코드에 대한 개념 설명을 안했네...;;;
조만간 테스트 코드에 대한 글을 작성해야겠다
TDD 에 관련된 책
테스트 코드를 알려준 고마운 스터디
'개발 & 방법론 > TDD' 카테고리의 다른 글
Mockito 알아보기 (부제 : BDD) (1) | 2021.12.06 |
---|---|
AssertJ 알아보기 (부제 : Jupiter, Hamcrest 맛보기 ) (0) | 2021.11.21 |
JUnit5 알아보기 (0) | 2021.10.26 |
테스트 코드를 작성하는 이유 (0) | 2021.03.03 |