ꎀ늬 메뉎

𝑆𝑢𝑛𝑠ℎ𝑖𝑛𝑒 𝑎𝑓𝑡𝑒𝑟 𝑟𝑎𝑖𝑛✧

[Spring] TestCode, TDD, JUnit, assertJ 볞묞

Test Code

제품 또는 서비슀의 품질을 확읞하고 소프튞웚얎의 버귞륌 찟습니닀.  
슉, í•šìˆ˜, íŠ¹ì •í•œ êž°ëŠ¥, UI, ì„±ëŠ¥, API슀펙읎 ì˜ˆìƒëŒ€ë¡œ ë™ìž‘하는지 í™•ìží•˜ëŠ” 것입니닀.

 

테슀튞 윔드의 종류

 

 

  • 테슀튞 플띌믞드는 ëŒ€ìƒ 범위나 성격에 따띌 Unit test(닚위 í…ŒìŠ€íŠž), Integration test(통합 테슀튞), UI 테슀튞(E2E 테슀튞) 3가지의 테슀튞로 나누얎집니닀.
  • 개발자분듀읎 프로젝튞륌 진행할 때 공통적윌로 작성핎알 하는 테슀튞듀을 몚아놓은 것읎 í…ŒìŠ€íŠž 플띌믞드입니닀.

 

1. Unit Test

  • 닚위 테슀튞
  • 핚수나 몚듈 큎래슀와 같은 닚위의 Ʞ능에 대한 유횚성을 검슝하는 테슀튞입니닀.
  • 예륌 듀얎 자동찚의 타읎얎륌 하나 테슀튞하는 것을 닚위 테슀튞띌 합니닀.
  • 닚위 테슀튞는 맀우 간닚하고 명확하며 빠륎게 싀행된닀는 특징읎 있습니닀.
  • 또한, 작게 쪌개진 닚위 테슀튞는 핎당 로직읎 ì–Žë–€ 역할을 하는지 쉜게 파악할 수 있닀.
  • 닚위 테슀튞륌 사용하멎 System.out윌로 하는 번거로욎 디버깅읎 필요 없습니닀.

 

2.  Integration test

  • 통합 테슀튞
  • 하나의 닚위가 아니띌 여러 가지의 서로 닀륞 몚듈 혹은 큎래슀 간 상혞작용의 유횚성을 검사하는 테슀튞읎닀.
  • 읎러한 통합 테슀튞가 필요한 읎유는 각각 닚위 테슀튞가 검슝되었닀 하더띌도, 몚듈 간 읞터페읎슀 및 데읎터 흐늄읎 의도한 대로 작동하지 않는 겜우도 있Ʞ 때묞읎닀.
  • 예륌 듀얎, 타읎얎와 엔진 등 부품듀읎 서로 상혞작용을 하멎서 시동읎 걞늬는지륌 확읞하는 통합 테슀튞입니닀. 

 

3. User interface Test(E2E Test)

  • End-to-End의 쀄임말로 끝곌 끝의 테슀튞
  • 싀제 사용자듀읎 사용하는 화멎에 대한 테슀튞륌 하여 서비슀의 Ʞ능읎 정상적윌로 작동하는지 검슝하는 테슀튞입니닀.
  • 예륌 듀얎, 타읎얎나 엔진 등 부분적읞 상혞작용읎 아니띌 엑셀곌 람레읎크, 엔진 등 ì°šê°€ 나아가는지 전첎적윌로 테슀튞하는 것을 의믞합니닀.
  • UI 테슀튞는 싀제 앱을 사용하는 사용자의 흐늄에 대핮 테슀튞 핚윌로썚 UI 변겜 사항윌로 발생할 수 있는 묞제륌 사전에 찚닚핚윌로썚 신뢰성을 높입니닀. 
  • 하지만 화멎곌 직접적윌로 연ꎀ되얎있는 테슀튞읎닀볎닌 싀행 시간도 였래 걞늬고 디자읞읎 변겜될 때마닀 테슀튞 윔드의 수정읎 필요합니닀.
  • 귞래서 유지볎수 비용도 큜니닀.

 

테슀튞 윔드 작성의 장점

  • 개발 곌정 쀑 예상치 못한 묞제륌 믞늬 발견할 수 있닀. (에러륌 큎띌읎얞튞볎닀 빚늬 발견할 수 있닀.)
  • 작성한 윔드가 의도한 대로 작동하는지 검슝할 수 있닀.
  • 윔드 늬펙토링을 유연하고 안정적읞 대응을 할 수 있게 핮 쀀닀.
  • 윔드의 몚듈화륌 한 번 더 고믌하게 핮 쀀닀.
  • 윔드 변겜 시, 변겜 부분윌로 읞한 영향도륌 쉜게 파악할 수 있닀.
  • 테슀튞 윔드륌 통핎 동작하는 방식 및 결곌 확읞읎 가능하닀.

TDD (Test Driven Development)

  • 테슀튞 죌도 개발
  • 테슀튞륌 뚌저 짜고 테슀튞륌 통곌할 만큌의 윔드륌 추가하는 닚계륌 반복하여 구현한닀.
  • 싀팚하는 테슀튞륌 뚌저 작성하고 귞에 핎당하는 Ʞ능을 만듀얎나가는 방식읎닀.
  • 읎후엔 늬팩터링윌로 횚윚성 향상한닀.

 

TDD 개발 프로섞슀

 

  • Red } 닚계에서는 싀팚하는 테슀튞 윔드륌 뚌저 작성합니닀.
  • Green } 닚계에서는 테슀튞 윔드륌 성공시킀Ʞ 위한 싀제 윔드륌 작성합니닀.
  • Yellow } 닚계에서는 쀑복 윔드 제거, 음반화 등의 늬팩터링을 수행합니닀.

 

읎렇게 싀팚하는 테슀튞 윔드륌 뚌저 작성하고 귞에 핎당하는 Ʞ능을 구현하는 방식읎 TDD읎닀. 쀑요한 것은 싀팚하는 테슀튞 윔드륌 작성할 때까지 싀제 윔드륌 작성하지 않는 것곌, 싀팚하는 테슀튞륌 통곌할 정도의 최소 싀제 윔드륌 작성핎알 하는 것입니닀. 

 

 

TDD의 장점

  • 몚든 요구사항, 목표에 대핎서 점검할 수 있고, 사용자 입장에서 윔드륌 작성할 수 있닀.
    (시슀템 전반적읞 섀계 향상)
  • 구현볎닀는 읞터페읎슀에 집쀑핎서 윔드륌 구현핚윌로썚 윔드의 퀄늬티는 향상되고 시슀템 전반적읞 섀계륌 향상한닀. 
  • 자연슀럜게 테슀튞 통곌윚읎 높아진닀.
  • 였버 엔지니얎링 방지
  • 섀계에 대한 플드백에 빠륎닀.

 

음반 개발 방식곌 TDD 개발 방식의 찚읎점

 

음반 개발 방식

볎통 개발 방식은 ‘요구사항 분석 → 섀계 → 개발 → 테슀튞 → 배포’의 형태의 개발 죌Ʞ륌 갖습니닀.

 

 

음반 개발 방식의 묞제점

  1. 소프튞웚얎 개발을 느늬게 하는 잠재적 위험읎 졎재한닀.
  2. 소비자의 요구사항읎 처음부터 명확하지 않을 수 있닀.
  3. 따띌서 처음부터 완벜한 섀계는 얎렵닀.
  4. 자첎 버귞 검출 능력 저하 또는 소슀윔드의 품질읎 저하될 수 있닀.
  5. 자첎 테슀튞 비용읎 슝가할 수 있닀.

 

읎러한 묞제점읎 발생되는 읎유는 얎느 프로젝튞든 쎈Ʞ 섀계가 완벜하지 않아 재섀계로 읞핎 개발자는 윔드륌 삜입, 수정, 삭제하는 곌정에서 불필요한 윔드가 낚거나 쀑복될 가능성읎 큜니닀.

귞래서 음반 개발 방식은 고객의 요구사항 또는 디자읞의 였류 등 많은 왞부 또는 낎부 조걎에 의핎 재섀계하여 점진적윌로 완벜한 섀계로 나아가는데, 결론적윌로 읎러한 윔드듀은 재사용읎 얎렵고 ꎀ늬가 얎렀워서 유지볎수륌 얎렵게 만듭니닀.

작은 부분의 Ʞ능 수정에도 몚든 부분을 테슀튞핎알 하므로 전첎적읞 버귞륌 검출하Ʞ 얎렀워젞 자첎 버귞 검출 능력읎 저하됩니닀. 따띌서 ìž‘은 수정에도 몚든 Ʞ능을 닀시 테슀튞핎알 하는 묞제가 발생하여 자첎 테슀튞 비용읎 슝가됩니닀.

 

 

TDD 개발 방식

 

TDD와 음반적읞 개발 방식의 가장 큰 찚읎점은 테슀튞 윔드륌 작성한 뒀에 싀제 윔드륌 작성한닀는 것입니닀.

디자읞(섀계) 닚계에서 프로귞래밍 목적을 반드시 믞늬 정의핎알만 하고 ë˜ 묎엇을 테슀튞핎알 할지 ë¯žëŠ¬ 정의(테슀튞 쌀읎슀 작성) í•Žì•Œ 합니닀. 테슀튞 윔드륌 작성하는 도쀑 발생하는 예왞 사항(버귞 및 수정사항)은 테슀튞 쌀읎슀에 추가하고 섀계륌 개선합니닀. 읎후 테슀튞가 통곌된 윔드만을 윔드 개발 닚계에서 싀제 윔드로 작성합니닀.

 


읎러한 반복적읞 닚계가 진행되멎서 자연슀럜게 윔드의 버귞가 쀄얎듀고 소슀윔드는 간결핎집니닀.
또한 테슀튞 쌀읎슀 작성윌로 읞핎 자연슀럜게 섀계가 개선됚윌로 재섀계 시간읎 절감됩니닀.

 

 

TDD 개발 방식의 묞제점

 

  1. 생산성 저하

처음부터 2개의 윔드륌 짜알하고 쀑간쀑간 테슀튞륌 하멎서 고쳐나가알 하Ʞ 때묞에 개발 속도가 느렀진닀고 생각하는 사람읎 많습니닀. TDD 방식의 개발 시간은 음반적읞 개발 방식에 비핎 대략 10~30% 정도로 늘얎납니닀. 

따띌서 SI 프로젝튞에서는 소프튞웚얎의 품질볎닀는 납Ʞ음 쀀수가 훚씬 쀑요하Ʞ 때묞에 TDD 방식을 잘 사용하지 않습니닀.

 


테슀튞 도구 (JUnit & assertJ)

 

JUnit

  •  ìžë°”ìš© 닚위테슀튞(Unit Test) ë„구 

 

 JUnit 특징

  • @Test ë©”서드가 í˜žì¶œí•  ë•Œ ë§ˆë‹€ ìƒˆë¡œìšŽ ìžìŠ€í„ŽìŠ€ë¥Œ ìƒì„±í•˜ì—¬ ë…늜적읞 í…ŒìŠ€íŠžê°€ ìŽë£šì–Žì§€ê²Œ í•©ë‹ˆë‹€.
  • ë‹šì •(assert) ë©”서드로 í…ŒìŠ€íŠž ìŒ€ìŽìŠ€ì˜ ìˆ˜í–‰ ê²°ê³Œë¥Œ íŒë³„í•  ìˆ˜ ìžˆìŠµë‹€. (닚정메소드는 ì•„래에 ì •ëŠ¬)
  • jUnit4부터는 ì–Žë…ží…ŒìŽì…˜ìœŒë¡œ ê°„결하게 í…ŒìŠ€íŠžë¥Œ ì§€ì›í•©ë‹ˆë‹€.(@Test @Before @After)
  • 결곌는 ì„±ê³µ(녹색), ì‹€íŒš(붉은색) ì€‘ í•˜ë‚˜ë¡œ í‘œì‹œë©ë‹ˆë‹€.
  • 테슀튞 ê²°ê³Œë¥Œ í™•ìží•˜ëŠ” ê²ƒ ìŽì™ž ìµœì í™”된 ìœ”드륌 ìœ ì¶”핎낎는 êž°ëŠ¥ë„ ì œê³µí•©ë‹ˆë‹€.

 

assert메서드 정늬

  • assertArrayEquals(a, b) :  ë°°ì—Ž A와 B가 음치핚을 확읞한닀.
  • assertEquals(a, b) : ê°ì²Ž A와 B가 같은 값을 가지는지 확읞한닀.
  • assertEquals(a, b, c) :  ê°ì²Ž A와 B가 값읎 음치핚을 확읞한닀.( a: 예상값, b:결곌값, c: 였찚범위)
  • assertSame(a, b) : ê°ì²Ž A와 B가 같은 객첎임을 확읞한닀.
  • assertTrue(a): ì¡°ê±Ž A가 찞읞지 확읞한닀.
  • assertNotNull(a) : ê°ì±„ A가 null읎 아님을 확읞한닀.

 

org.junit.Assert.assertThat

공식 묞서

org.junit.Assert.assertThat의 Ʞ볞 형태는 아래와 같습니닀.

public static <T> void assertThat(T actual, Matcher<? super T> matcher)

actual 읞자에 검슝대상(싀행 닚계의 결곌)을 넣고, 읎와 비교하는 로직(matcher)을 죌입받아 ê²€ìŠ 닚계륌 수행합니닀.

개발자가 matcher륌 직접 구현하는 것은 비횚윚적읎고, 구현한 matcher에서 였류가 발생할 수도 있습니닀.
matcher에서 였류가 발생하멎 테슀튞가 싀팚하는데, 왞부 요읞에 영향을 받는 것은 좋은 테슀튞띌고 할 수 없습니닀.
귞런 읎유 때묞읞지, JUnit의 assertThat은 hamcrest에 구현된 matcher륌 사용하도록 강제하고 있습니닀.

 

AssertJ

  • Java 테슀튞에서 유찜하고 풍부한 assertions륌 작성하는 데 사용되는 였픈 소슀 컀뮀니티 êž°ë°˜ 띌읎람러늬
  • 테슀튞 윔드 작성 시 가독성읎 뛰얎나고 상섞한 에러 메시지륌 제공핎죌는 띌읎람러늬

 

org.assertj.core.api.Assertions.assertThat

공식 묞서

public static AbstractAssert<SELF, T> assertThat(T actual)

assertj의 assertThat은 읞자로 actual(검슝대상)만 받습니닀.

귞늬고 actual의 타입에 따띌 AbstractAssert띌는 추상 큎래슀륌 상속한 Assert 큎래슀륌 반환합니닀.

 

 

ê²°ë¡ 

AssertJ와 Junit Assertions 쀑 ì–Žë–€ 걞 썚알 하나

Assertions는 Junit읎 구현한 큎래슀도 있고, AssertJ의 Assertions가 있습니닀. 죌로 AssertJ륌 사용합니닀. ê·ž 읎유는 JUnit5.Assertions는 IDE가 자동 완성도 지원하지 않윌며 메서드륌 왞워알 한닀는 닚점읎 있습니닀.

반멎 assertJ는 junit읎 제공하는 assert 볎닀 사용하Ʞ 펾한 묞법을 제공하며, 핚수명읎 직ꎀ적읎얎서 가독성도 좋습니닀.

AssertJ공식묞서륌 볎멎 바꟞는 방법읎 나옚 예시에서 AssertJ가 더 명확합니닀.

 

// Junit 
assertEquals(expected, actual);
// to : AssertJ
assertThat(actual).isEqualTo(expected);

 

 

 

 

[ì°žì¡°]

1. https://hanamon.kr/tdd%EB%9E%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C/

2. https://wooaoe.tistory.com/33

3. https://hanamon.kr/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1%EC%9D%98-%EC%A4%91%EC%9A%94%EC%84%B1/

4. https://jwkim96.tistory.com/168