๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๊ฐœ๋…์ •๋ฆฌ(JAVA)

JUnit์— ๊ด€ํ•˜์—ฌ

๐Ÿงช ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test)๋ž€ ?

JUnit์€ Java ์—์„œ ๋…๋ฆฝ๋œ ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋ฅผ ์ง€์›ํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ด๊ธฐ ๋•Œ๋ฌธ์—
๋‹จ์œ„ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ๋จผ์ € ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค ๐Ÿ’ก

 

ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ๋‹จ์œ„๊ฐ€ ์—„๊ฒฉํ•˜๊ฒŒ ์ •ํ•ด์ ธ์žˆ์ง€๋Š” ์•Š์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์†Œ๋“œ ์ˆ˜์ค€์œผ๋กœ ์ •ํ•ด์ง‘๋‹ˆ๋‹ค. ๋‹จ์œ„์˜ ํฌ๊ธฐ๊ฐ€ ์ž‘์„์ˆ˜๋ก ๋‹จ์œ„์˜ ๋ณต์žก์„ฑ์ด ๋‚ฎ์•„์ง€๊ณ , ์‹คํ–‰ํ•˜๋ ค๋Š” ๊ธฐ๋Šฅ์„ ํ‘œํ˜„ํ•˜๊ธฐ ๋” ์‰ฌ์›Œ์ง€๋Š”๊ฒŒ ๋‹น์—ฐํ•˜๊ฒ ์ฃ ?

 

๋‹จ์œ„ํ…Œ์ŠคํŠธ๋ž€ ํŠน์ • ์†Œ์Šค์ฝ”๋“œ์˜ ๋ชจ๋“ˆ์ด ์˜๋„ํ•œ ๋Œ€๋กœ ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
์ฆ‰, ํ•จ์ˆ˜ ๋ฐ ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ์ž‘์—…์œผ๋กœ์จ, Spring์—์„œ ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋Š” Spring Container์— ์˜ฌ๋ผ์™€ ์žˆ๋Š” Bean ์„ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ’ก ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์˜ ์žฅ์ 

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ํ•ด๋‹น ๋ถ€๋ถ„๋งŒ ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•˜์—ฌ๋„ ๋น ๋ฅด๊ฒŒ ๋ฌธ์ œ ์—ฌ๋ถ€๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ, ๊ฐœ๋ฐœ์ž๋Š” ์ž‘์„ฑํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ˆ˜์‹œ๋กœ ๋น ๋ฅด๊ฒŒ ๋Œ๋ฆฌ๋ฉด์„œ ๋ฌธ์ œ์ ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋™์•ˆ์—๋Š” ์‹ค์ œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋™์ž‘์‹œํ‚ฌ ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Bean์„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿง‘๐Ÿผ‍๐Ÿ’ป

 

๐Ÿงช JUnit ์ด๋ž€?

  • ์ž๋ฐ” ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ŠคํŒ… ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์›Œํฌ ์ž…๋‹ˆ๋‹ค.
  • ํ˜„์žฌ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ๋ฒ„์ „์€ JUnit 5 ์ž…๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ Junit 4์— ๋น„ํ•ด JUnit 5๋Š” 3๊ฐ€์ง€ ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • JUnit5๋Š” ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ž๋ฅผ ์œ„ํ•œ API ๋ชจ๋“ˆ๊ณผ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์œ„ํ•œ API๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ž๋ฐ” 8 ์ด์ƒ์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿงช JUnit ๊ตฌ์กฐ

ํ•ด๋‹น ๊ตฌ์กฐ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค ๐Ÿ’ก
๊ธฐ์กด ๋ฒ„์ „์ธ JUnit4์—์„œ๋Š” vintage-engine ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŒ…์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ด์™€ ๋‹ฌ๋ฆฌ, JUnit5๋Š” ํฌ๊ฒŒ 3๊ฐ€์ง€ ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

JUnit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Jupiter API : JUnit5์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์šฉ API

  • JUnit Platform : ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ํ…Œ์ŠคํŠธ ๊ณ„ํš์„ ์ƒ์„ฑํ•˜๋Š” TestEngine ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ ํ•ฉ๋‹ˆ๋‹ค.
    ์ฆ‰, ๊ธฐ์ดˆ์ ์ธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ TestEngine API ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • JUnit Jupiter : JUnit5์—์„œ ํ…Œ์ŠคํŠธ ๋ฐ Extension์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ๊ณผ ํ™•์žฅ ๋ชจ๋ธ์˜ ์กฐํ•ฉ์ด๋ฉฐ, TestEngine API ๊ตฌํ˜„์ฒด ์ž…๋‹ˆ๋‹ค.
    JUpiter ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ํ•„์š”ํ•œ junit-jupiter-api ๋ชจ๋“ˆ๊ณผ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์œ„ํ•œ junit-jupiter-engine ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค.
    • JUnit Jupiter = junit-jupiter-api + junit-jupiter-engine
  • JUnit Vintage : JUnit3, JUnit4 ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” TestEngine ์ž…๋‹ˆ๋‹ค. ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด์„œ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
    TestEngine์˜ ์‹ค์ œ ๊ตฌํ˜„์ฒด๋Š” ๋ณ„๋„ ๋ชจ๋“ˆ๋กœ ์กด์žฌํ•˜๋Š”๋ฐ, ์ด ์ค‘ ํ•˜๋‚˜๊ฐ€ jupiter-engine ์ž…๋‹ˆ๋‹ค.

๐Ÿงช ํ…Œ์ŠคํŠธ์˜ Class & Method ์–ด๋…ธํ…Œ์ด์…˜

Test ์—ญ์‹œ ์ž๋ฐ”์˜ ๊ฐ์ฒด๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Class + Method ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • Class : ์ตœ์ƒ์œ„ ํด๋ž˜์Šค, static member class, @Nested class ์ค‘ ์ ์–ด๋„ ํ•˜๋‚˜์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํด๋ž˜์Šค
    • Test Class ๋Š” absctract ์ด๋ฉด ์•ˆ๋˜๋ฉฐ, ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ’ช
  • Test Method : @Test, @RepeatedTest, @TestFactory ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์ด ์„ ์–ธ๋˜์–ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋กœ ์‹ค์ œ ํ…Œ์ŠคํŠธํ•˜๊ณ ์ž ํ•˜๋Š” ๋‚ด์šฉ์„ ๋„ฃ์Šต๋‹ˆ๋‹ค.
    • @Test
      : ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๊ฐ€ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • @ParametherizedTest
      : ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ํ…Œ์ŠคํŠธ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • @RepeatedTest
      : ๋ฐ˜๋ณต๋˜๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. -> @RepeatedTest(3)
  • LifeCycle Method : @BeforeAll, @BeforeEach, @AfterAll, @AfterEach ๊ฐ€ ์„ ์–ธ๋˜์–ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋กœ Test ์˜ Life Cycle์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ๋ฉ”์†Œ๋“œ ์ž…๋‹ˆ๋‹ค.
    • @BeforeAll
      : ํ…Œ์ŠคํŠธ Class ๊ธฐ์ค€์œผ๋กœ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋“ค์ด ์‹คํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰
      ์ฆ‰, ํ…Œ์ŠคํŠธ ์‹œ์ž‘ ์‹œ์ ์— ๋”ฑ ํ•œ๋ฒˆ ์‹คํ–‰(static ๋ฉ”์†Œ๋“œ๋งŒ ๊ฐ€๋Šฅ)
    • @BeforeEach
      : ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰
      ์ผ๋ฐ˜์ ์œผ๋กœ Mock ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ์„ธํŒ…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
    • @AfterAll
      : ํ…Œ์ŠคํŠธ Class ๊ธฐ์ค€์„ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋“ค์ด ์‹คํ–‰๋œ ํ›„ ์‹คํ–‰
      ์ฆ‰, ํ…Œ์ŠคํŠธ ์ข…๋ฃŒ ์‹œ์ ์— ๋”ฑ ํ•œ๋ฒˆ ์‹คํ–‰(static ๋ฉ”์†Œ๋“œ๋งŒ ๊ฐ€๋Šฅ)
    • @AfterEach
      : ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰

๐Ÿ”„ ์ „์ฒด์ ์ธ Life Cycle
BeforeAll -> BeforeEach -> Test -> AfterEach -> AfterAll

๐Ÿงช ๊ธฐํƒ€ ์–ด๋…ธํ…Œ์ด์…˜

  • @Tag : ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค, ๋ฉ”์†Œ๋“œ์— ํ…Œ์ŠคํŠธ ๊ตฌ๋ถ„์„ ํƒœํ‚นํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
  • @Disabled : ํ•ด๋‹น ํด๋ž˜์Šค๋‚˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ
  • @Timeout : ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ„ ์„ ์–ธ, ์ดˆ๊ณผ๋˜๋ฉด ์‹คํŒจํ•˜๋„๋ก ์„ค์ •
  • @ExtendWith : ํ™•์žฅ์„ ์„ ์–ธ์ ์œผ๋กœ ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉ
  • @TempDir : ํ•„๋“œ ์ฃผ์ž… ํ˜น์€ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ฃผ์ž…์„ ํ†ตํ•ด ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ œ๊ณต
  • @DispayName : ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„ ์„ค์ •(๊ธฐ๋ณธ๊ฐ’ -> ๋ฉ”์†Œ๋“œ ์ด๋ฆ„)

๐Ÿงช Assertions

org.junit.jupiter.api.Assertions ํŒจํ‚ค์ง€๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ

assertArrayEquals

์˜ˆ์ƒ ๋ฐฐ์—ด(expected)๊ณผ ์‹ค์ œ ๋ฐฐ์—ด(actual))์ด ๋™์ผํ•œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๋‘ ๋ฐฐ์—ด์ด ์ผ์น˜ ํ•˜์ง€ ์•Š๋‹ค๋ฉด, ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ ๋ฉ”์„ธ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void whenAssertingArraysEquality_thenEqual() {
 
   char[] expected = { 'J', 'u', 'p', 'i', 't'};
 
   char[] actual = "Jupiter".toCharArray();
 
 
 
   assertArrayEquals(expected, actual, "๋‘ ๋ฐฐ์—ด์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
 
}

 

assertEquals

๋‘ ๊ฐ’์„ ๋น„๊ตํ•˜์—ฌ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void whenAssertingEquality_thenEqual() {
 
   float square = 2 * 2;
 
   float rectangle = 2 * 2;
 
 
 
   assertEquals(square, rectangle);
 
}

 

์‹ค์ œ ๊ฐ’์ด ์˜ˆ์ƒ ๊ฐ’์˜ ์ฐจ์ด๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ ์ฐจ์ด๊ฐ€ ๋‚˜๋Š” ๊ฐ’์„ ๊ฐ€์ง„ delta๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค

 
@Test
 
void whenAssertingEqualityWithDelta_thenEqual() {
 
   float square = 2 * 2;
 
   float rectangle = 3 * 2;
 
   float delta = 2;
 
 
 
   assertEquals(square, rectangle, delta);
 
}
assertNotEquals

์˜ˆ์ƒ ๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์ด ๋‹ค๋ฅธ์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์„ ๊ฒฝ์šฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
void whenAssertingEquality_thenNotEqual() {
 
   Integer value = 5;
 
 
 
   assertNotEquals(0, value, "The result cannot be 0");
 
}
assertTrue and assertFalse

assertTrue๋Š” ์ฃผ์–ด์ง„ ์กฐ๊ฑด์ด ์ฐธ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์กฐ๊ฑด์ด ๊ฑฐ์ง“์ผ ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
void whenAssertingConditions_thenVerified() {
 
   assertTrue(5 > 4, "5 is greater the 4");
 
   assertTrue(null == null, "null is equal to null");
 
}

 

assertFalse๋Š” ์ฃผ์–ด์ง„ ์กฐ๊ฑด์ด ๊ฑฐ์ง“์ธ์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

์กฐ๊ฑด์ด ์ฐธ์ผ ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
 
   assertFalse(5 > 6, "5 is not greater then 6");
 
}
assertNull and assertNotNull

assertNull์€ ๊ฐ์ฒด์˜ null ์—ฌ๋ถ€๋ฅผ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด๊ฐ€ Null์ด ์•„๋‹ ๊ฒฝ์šฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅ ํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void whenAssertingNull_thenTrue() {
 
   Object cat = null;
 
 
 
   assertNull(cat, "The cat should be null");
 
}

 

assertNotNull์€ ๊ฐ์ฒด๊ฐ€ Null์ด ์•„๋‹Œ์ง€๋ฅผ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด๊ฐ€ Null์ผ ๊ฒฝ์šฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅ ํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
void whenAssertingNotNull_thenTrue() {
 
   Object dog = new Object();
 
 
 
   assertNotNull(dog, "The dog should not be null");
 
}
assertSame and assertNotSame

assertSame์€ ์˜ˆ์ƒ ๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์ด ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š”์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void whenAssertingSameObject_thenSuccessfull() {
 
   String language = "Java";
 
   String MyLanguage = "Java";
 
 
 
   assertSame(language, MyLanguage);
 
}

 

๋ฐ˜๋Œ€๋กœ, assertNotSame์€ ์˜ˆ์ƒ ๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
public void whenAssertingSameObject_thenSuccessfull() {
 
   String language = "Java";
 
   String anotherLanguage = "JavaScript";
 
 
 
   assertNotSame(language, anotherLanguage);
 
}
fail

ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํŒจ ์ฒ˜๋ฆฌํ•˜๋ฉฐ ์‹คํŒจ ๋ฉ”์‹œ์ง€๋ฅผ ํ•จ๊ป˜ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ํ…Œ์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•  ๋•Œ ์œ ์šฉ

 
@Test
 
public void whenFailingATest_thenFailed() {
 
   // Test not completed
 
   fail("FAIL - test not completed");
 
}
assertAll

assertAll์•ˆ์— ์ž‘์„ฑ๋œ ๋ชจ๋“  Assertion์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

ํ•œ ๋ฉ”์†Œ๋“œ์— assertํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ์„ ์–ธ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ์‹œ ์ƒ๋‹จ assertํ•จ์ˆ˜์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ทธ ๋ฐ‘ ํ•จ์ˆ˜๋“ค์„ ์‹คํ–‰๋˜์ง€๊ฐ€ ์•Š์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, assertAll()๋กœ ํ•ด๋‹น ์ˆ˜๋“ค์„ ๋ฌถ์„ ์‹œ ์ค‘๊ฐ„์— assertํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰์ด ๋˜์ง€ ์•Š๋”๋ผ๋„ assert์˜ ๋ชจ๋“  ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ, ์‹คํ–‰ ์ค‘ ์˜ˆ์™ธ(Out Of Memory Error ๋“ฑ)๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.

 
@Test
 
void givenMultipleAssertion_whenAssertingAll_thenOK() {
 
   Object obj = null;
 
   assertAll(
 
         "heading",
 
         () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
 
         () -> assertEquals("java", "JAVA".toLowerCase()),
 
         () -> assertNull(obj, "obj is null")
 
   );
 
}
assertIterableEquals

์˜ˆ์ƒ๋œ ๋ฐ˜๋ณต ๊ฐ€๋Šฅ ํ•ญ๋ชฉ๊ณผ ์‹ค์ œ ๋ฐ˜๋ณต ๊ฐ€๋Šฅ ํ•ญ๋ชฉ์ด ์™„์ „ํžˆ ๋™์ผํ•œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๋‘ Iterable์€ ๋™์ผํ•œ ์ˆœ์„œ๋กœ ๋™์ผํ•œ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๋‘ Iterable์ด ๋™์ผํ•œ ์œ ํ˜•์ผ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

 
@Test
 
void givenTwoLists_whenAssertingIterables_thenEquals() {
 
   Iterable<String> al = new ArrayList<>(asList("Java", "Junit", "Test"));
 
   Iterable<String> ll = new LinkedList<>(asList("Java", "Junit", "Test"));
 
 
 
   assertIterableEquals(al, ll);
 
}
assertLinesMatch

์˜ˆ์ƒ ๋ชฉ๋ก์ด ์‹ค์ œ ๋ชฉ๋ก๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋Š” assertEquals ๋ฐ assertItableEquals์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

  1. ์˜ˆ์ƒ ๋ผ์ธ์ด ์‹ค์ œ ๋ผ์ธ๊ณผ ๋™์ผํ•œ์ง€ ํ™•์ธ. ๋™์ผํ•  ๊ฒฝ์šฐ ๋‹ค์Œ ์Œ์œผ๋กœ ๊ณ„์† ์ง„ํ–‰
  2. ์˜ˆ์ƒ๋˜๋Š” ํ–‰์„ ์ •๊ทœ ํ‘œํ˜„์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ String.matches() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒดํฌ๋ฅผ ์ˆ˜ํ–‰. ๋™์ผํ•  ๊ฒฝ์šฐ ๋‹ค์Œ ์Œ์œผ๋กœ ๊ณ„์† ์ง„ํ–‰
  3. ์˜ˆ์ƒ๋˜๋Š” ๋ผ์ธ์ด fast-forward marker  ํ™•์ธ.๋™์ผํ•  ๊ฒฝ์šฐ fast-forward๋ฅผ ์ ์šฉํ•˜๊ณ  ์Šคํ…1๋ถ€ํ„ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ฐ˜๋ณต
 
@Test
 
void whenAssertingEqualityListOfStrings_thenEqual() {
 
   List<String> expected = asList("Java", "\\d+", "JUnit");
 
   List<String> actual = asList("Java", "11", "JUnit");
 
 
 
   assertLinesMatch(expected, actual);
 
}
assertThrows

ํŠน์ • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” "ํ™•์ธํ•  ์˜ˆ์™ธ ํด๋ž˜์Šค", ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” "ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ์ฝ”๋“œ"๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 
@Test
 
void whenAssertingException_thenThrown() {
 
   Throwable exception = assertThrows(
 
      IllegalArgumentException.class,
 
      () -> {
 
         throw new IllegalArgumentException("Exception message");
 
      }
 
   );
 
   assertEquals("Exception message", exception.getMessage());
 
}
assertTimeout and assertTimeoutPreemptively

assertTimeout์€ ํŠน์ • ์‹œ๊ฐ„ ์•ˆ์— ์‹คํ–‰์ด ๋๋‚˜๋Š”์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค.

assertTimeoutPreemptively์€ ์ง€์ •ํ•œ ์‹œ๊ฐ„ ๋‚ด ๋๋‚˜์ง€ ์•Š์œผ๋ฉด ๋ฐ”๋กœ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์ฝ”๋“œ๋Š” 2์ดˆ ์ด๋‚ด์— ๊ทธ ๋‹ค์Œ ์ธ์ž์ธ "Executable ์ฝ”๋“œ"๊ฐ€ ์‹คํ–‰์™„๋ฃŒ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์‹คํ–‰ํ•œ ์ฝ”๋“œ๋Š” Thread.sleep(1000) ์œผ๋กœ, 1์ดˆ๋™์•ˆ ์ผ์‹œ ์ •์ง€ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— 2์ดˆ ์ด๋‚ด์— ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด ํ…Œ์ŠคํŠธ๋Š” ํ†ต๊ณผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

๋งŒ์•ฝ Thread.sleep(2000), Thread.sleep(3000) ์œผ๋กœ ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด 2์ดˆ ์ด๋‚ด์ธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 
@Test
 
void whenAssertingTimeout_thenNotExceeded() {
 
   assertTimeout(
 
      ofSeconds(2),
 
      () -> {
 
         Thread.sleep(1000);
 
      }
 
   );
 
}

๐Ÿงช AssertJ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

AssertJ ๋Š” JUnit Assertions์„ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด ๋” ์šฐ์•„ํ•œ(?) ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์„ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž…๋‹ˆ๋‹ค ๐Ÿ‘
spring-boot-starter-test ์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ’ช

Hamcrest์™€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ ํ•ต์‹ฌ ๋ฉ”์†Œ๋“œ๋Š” assertThat 1๏ธโƒฃ ๊ฐœ ์ด๋ฉฐ ๋ฉ”์†Œ๋“œ ์ฒด์ด๋‹ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก Object Assertions

๋‘ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ์ด๋‚˜ ๊ฐ์ฒด์˜ ํ•„๋“œ๋ฅผ ์กฐ์‚ฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

Example

public class Dog {

	private String name;
    private Double weight;
    
}

@Test
public class DogTest() { 

	Dog dog01 = new Dog("์ง„๋—๊ฐœ", 3.45);
    Dog dog02 = new Dog("์‹œ์ถ”" , 1.23);
    
    assertThat(dog01).isEqualTo(dog02);

}

isEqualsTo() ๋Š” ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ์„ ๋น„๊ตํ•˜๋ฏ€๋กœ ํ•ด๋‹น ํ…Œ์ŠคํŠธ๋Š” fail์ž…๋‹ˆ๋‹ค ๐Ÿฅฒ
๋™๋“ฑ์„ฑ์„ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” isEqualToComparingFieldByFieldRecursively() ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก Boolean Assertions

๋‘ ๊ฐ์ฒด์˜ Boolean ๊ฐ’ ๋น„๊ต๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ

  • isTrue()
  • isFalse()

Example

assertThat("".isEmpty()).isTrue(); // true

๐Ÿ’ก Iterable/Array Assertions

Iterable/Array ์— ํŠน์ • ์š”์†Œ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ

List<String> list = Arrays.asList("1","2","3");

assertThat(list).contains("1"); // ํฌํ•จ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ

assertThat(list).isNotEmpty(); // ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธ

assertThat(list).startsWith("1"); // ํ•ด๋‹น ์š”์†Œ๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ

assertThat(list).doesNotContainNull() // null ํฌํ•จ ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธ
 

์ด์™ธ์—๋„ AssertJ ๋ฅผ ์ด์šฉํ•ด์„œ ๋‹ค์–‘ํ•œ Case๋ฅผ ์ง๊ด€์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ’ช

 

๐Ÿงช ๋งˆ๋ฌด๋ฆฌ

JUnit5๋Š” ์ž๋ฐ”๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๋‹น์—ฐํžˆ ์ˆ™์ง€ํ•ด์•ผํ•  ํ…Œ์ŠคํŒ… ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค ๐Ÿ“š
ํŠนํžˆ ์š”์ฆ˜ ๊ฐœ๋ฐœ ๋ฌธํ™”์— TDD ๋Š” ์ค‘์š”ํ•œ ์š”์†Œ๋กœ ์ž๋ฆฌ ์žก์•˜๊ธฐ์— ๋”์šฑ ํ•„์ˆ˜์ ์œผ๋กœ ์ตํ˜€์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค ๐Ÿ™†๐Ÿป

'๊ฐœ๋…์ •๋ฆฌ(JAVA)' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜(Garbage Collection)  (0) 2024.03.28
์ž๋ฐ” ์˜ˆ์•ฝ์–ด ์ •๋ฆฌ  (1) 2024.03.28
Test & TDD  (0) 2024.03.28
์ด์ง„๊ฒ€์ƒ‰  (2) 2024.03.27
๊ฒ€์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜  (0) 2024.03.27