๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
BackEnd๐ŸŒฑ/Spring

JUnit5 ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ

by ์•ˆ์ฃผํ˜• 2022. 10. 2.

๋ชฉ์ฐจ

  1. JUnit5๋ž€?
  2. JUnit5 ๊ตฌ์„ฑ
  3. JUnit5 ์‹œ์ž‘ํ•˜๊ธฐ
  4. JUnit5์˜ ์–ด๋…ธํ…Œ์ด์…˜๋“ค
  5. JUnit5 ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํ‘œ์‹œํ•˜๊ธฐ
  6. JUnit5 Assertion
  7. ์กฐ๊ฑด์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ
  8. ํƒœ๊น…๊ณผ ํ•„ํ„ฐ๋ง
  9. ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณตํ•˜๊ธฐ 
  10. ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค
  11. ํ…Œ์ŠคํŠธ ์ˆœ์„œ

 

1.  JUnit5๋ž€?

Junit๋ž€ ํ…Œ์ŠคํŒ… ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ์จ ์ž๋ฐ” ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.
ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ(Test Driven Development, TDD)์„ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ฒ€์ฆํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ
  • ํ…Œ์ŠคํŠธ ํ†ต๊ณผ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ ์ž‘์„ฑ
  • ์ดํ›„ ๋ฆฌํŒฉํ† ๋งํ•˜์—ฌ ์‹ค์ œ ๊ฐœ๋ฐœ ์ฝ”๋“œ์— ์ ์šฉ 

 

2. JUnit5 ๊ตฌ์„ฑ

JUnit5๋Š” Java8๋ฒ„์ „ ์ด์ƒ๋ถ€ํ„ฐ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ Platform, Jupiter, Vintage ์ด ์„ธ ๊ฐ€์ง€๊ฐ€ ๊ฒฐํ•ฉํ•œ ํ˜•ํƒœ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

JUnit5 ๊ตฌ์„ฑ ๋ชฉ๋ก

JUnit Platform

  • JVM์—์„œ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋Ÿฐ์ฒ˜์™€ TestEngine API ์ œ๊ณต

JUnit Jupiter

  • TestEngine API์˜ ๊ตฌํ˜„์ฒด๋กœ JUnit5์—์„œ ์ œ๊ณต

JUnit Vintage

  • TestEngine API์˜ ๊ตฌํ˜„์ฒด๋กœ JUnit3, JUnit4์—์„œ ์ œ๊ณต
  • ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด JUnit3, JUnit4 ๊ธฐ๋ฐ˜์˜ ํ”Œ๋žซํผ์— TestEngine ์ œ๊ณต

 

3.  JUnit5 ์‹œ์ž‘ํ•˜๊ธฐ

2.2+ ๋ฒ„์ „ ์ด์ƒ์˜ ์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด ๊ธฐ๋ณธ์œผ๋กœ JUnit5 ์˜์กด์„ฑ์ด ์ถ”๊ฐ€๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ์„ค์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ง์ ‘ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.5.2</version>
    <scope>test</scope>
</dependency>

 

4.  JUnit5 ์–ด๋…ธํ…Œ์ด์…˜๋“ค

@Test: ํ…Œ์ŠคํŠธ Method์ž„์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

@ParameterizedTest: ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

@RepeatedTest: ๋ฐ˜๋ณต๋˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

@TestFactory: @Test๋กœ ์„ ์–ธ๋œ ์ •์  ํ…Œ์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ๋™์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@TestInstance: ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

@TestTemplate: ๊ณต๊ธ‰์ž์— ์˜ํ•ด ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ํ…œํ”Œ๋ฆฟ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

@TestMethodOrder: ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@DisplayName: ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ๋˜๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์˜ ์ด๋ฆ„์„ ์ •์˜ํ• ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@DisplayNameGeneration: ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ์ •์˜ํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์˜ ์ด๋ฆ„์„ ์น˜ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.

@BeforeEach: ๊ฐ๊ฐ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ๋งค๋ฒˆ ์šฐ์„ ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฉ๋‹ˆ๋‹ค.

@AfterEach: ๊ฐ๊ฐ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ํ›„์— ๋งค๋ฒˆ ํ…Œ์ŠคํŠธ๋ฉ๋‹ˆ๋‹ค.

@BeforeAll: ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „ ๋”ฑ ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. 
๋ฐ˜๋“œ์‹œ static method๋กœ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
private ๋ถˆ๊ฐ€, default ๊ฐ€๋Šฅ, return type ๋ถˆ๊ฐ€๋Šฅ ์˜ค์ง void๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

@AfterAll: ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ๋”ฑ ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
๋ฐ˜๋“œ์‹œ static method๋กœ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
private ๋ถˆ๊ฐ€, default ๊ฐ€๋Šฅ, return type ๋ถˆ๊ฐ€๋Šฅ ์˜ค์ง void๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

@Nested: ํด๋ž˜์Šค๊ฐ€ ์ •์ ์ด ์•„๋‹ˆ๋ผ ์ค‘์ฒฉ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

@Tag: ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์†Œ๋“œ ๋ ˆ๋ฒจ์—์„œ ํƒœ๊ทธ๋ฅผ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋ฉฐ, Mavan์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ํƒœ๊ทธ ์„ค์ •์„ ํ†ตํ•ด ์›ํ•˜๋Š” ํƒœ๊ทธ๋งŒ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ์ œ์™ธ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Disabled: ์ด ํด๋ž˜์Šค๋‚˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.(์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

@Timeout: ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์„ ์–ธํ•œ ํ›„, ์‹œ๊ฐ„๋‚ด์— ํ…Œ์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์œผ๋ฉด ์‹คํŒจ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

@ExtendWith: ํ™•์žฅ์„ ์„ ์–ธ์ ์œผ๋กœ ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@RegisterExtension: ํ•„๋“œ๋ฅผ ํ†ตํ•ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ํ™œ์žฅ์„ ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@TempDir: ํ•„๋“œ ์ฃผ์ž… ๋˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์ฃผ์ž…์„ ํ†ตํ•ด ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

5.  JUnit5 ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํ‘œ์‹œํ•˜๊ธฐ

1. @DisplayNameGeneration

  • Method์™€ Class ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ ์ด๋ฆ„์„ ํ‘œ๊ธฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด๋กœ ReplaceUnderscores๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ์• ๋…ธํ…Œ์ด์…˜์— ReplaceUnderScores ์†์„ฑ์„ ์ฃผ์–ด ๋ฉ”์„œ๋“œ ๋„ค์ž„์˜ ์–ธ๋”์Šค์ฝ”์–ด๊ฐ€ ๊ณต๋ฐฑ์œผ๋กœ ๋ฐ”๋€Œ์–ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

โญ๏ธ Before

public class JUnit5Test {
    @Test
    void naming_test(){
        System.out.println("ํ…Œ์ŠคํŠธ");
    }
}

@DisplayNameGeneration ์ ์šฉ ์ „

โญ๏ธAfter

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
public class JUnit5Test {
    @Test
    void naming_test(){
        System.out.println("ํ…Œ์ŠคํŠธ");
    }
}

@DisplayNameGeneration ์ ์šฉ ํ›„


2. @DisplayName

  • ์–ด๋–ค ํ…Œ์ŠคํŠธ์ธ์ง€ ํ…Œ์ŠคํŠธ ์ด๋ฆ„์„ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„๋ณด๋‹ค ๋” ์‰ฝ๊ฒŒ ์–ด๋–ค ํ…Œ์ŠคํŠธ์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • @DisplayNameGeneration๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค.

โญ๏ธ Before

public class JUnit5Test {
    @Test
    void naming_test(){
        System.out.println("ํ…Œ์ŠคํŠธ");
    }
}

@DisplayName ์ ์šฉ ์ „

โญ๏ธ After

public class JUnit5Test {
    @DisplayName("ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ์ง€์ •")
    @Test
    void naming_test(){
        System.out.println("ํ…Œ์ŠคํŠธ");
    }
}

@DisplayName ์ ์šฉ ํ›„

 

6. JUnit5 Assertion

Assertion์€ ์‹ค์ œ ํ…Œ์ŠคํŠธ์—์„œ ๊ฒ€์ฆํ•˜๊ณ ์ž ํ•˜๋Š” ๋‚ด์šฉ์„ ํ™•์ธํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.

1. assertEquals(expected, actual)

์‹ค์ œ ๊ฐ’(actual)์ด ๊ธฐ๋Œ€ํ•œ ๊ฐ’(expected)๊ณผ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ˆœ์„œ๋Š” ์•„๋ฌด๋ ‡๊ฒŒ๋‚˜ ํ•ด๋„ ์ƒ๊ด€์—†์ง€๋งŒ ๋ณดํ†ต ์ฒซ ๋ฒˆ์งธ์— ๊ธฐ๋Œ“๊ฐ’์„ ๋„ฃ๊ณ , ๋‘ ๋ฒˆ์งธ์— ์‹ค์ œ ๋‚˜์˜ค๋Š” ๊ฐ’์„ ๋„ฃ์Šต๋‹ˆ๋‹ค.

    @Test
    @DisplayName("์Šคํ„ฐ๋”” ๋งŒ๋“ค๊ธฐ")
    void create_new_study() {
        Study study = new Study(-10, 25);
        assertEquals(StudyStatus.DRAFT, study.getStatus(), "์—๋Ÿฌ ๋ฉ”์„ธ์ง€");
        assertEquals(StudyStatus.DRAFT, study.getStatus(), () -> "์—๋Ÿฌ ๋ฉ”์„ธ์ง€");
        assertEquals(StudyStatus.DRAFT, study.getStatus(), String.valueOf(new Supplier<String>() {
            @Override
            public String get() {
                return "์—๋Ÿฌ ๋ฉ”์„ธ์ง€";
            }
        }));
	}

assertEquals์—์„œ ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ํ•ด๋‹น ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ–ˆ์„ ๊ฒฝ์šฐ ๋ณด์—ฌ์ฃผ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์œ„์˜ ์„ธ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋žŒ๋‹ค์‹์„ ์จ์„œ ๋ฉ”์„ธ์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๊ฐ€์žฅ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

๋žŒ๋‹ค์‹์„ ์จ์„œ ๋ฉ”์„ธ์ง€๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ์ด์œ .

  • ๋ฌธ์ž์—ด ์—ฐ์‚ฐ์˜ ์‹คํ–‰์„ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ–ˆ์„ ๋•Œ๋งŒ ํ•œ๋‹ค. ๋žŒ๋‹ค์‹์ด ์•„๋‹ ๊ฒฝ์šฐ์—๋Š” ํ•ญ์ƒ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋žŒ๋‹ค์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ ์ž…์žฅ์—์„œ ์กฐ๊ธˆ ์œ ๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

2. assertNotNull(actual)

๊ฒฐ๊ณผ ๊ฐ’(actual)์ด null์ธ์ง€ ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. 

    @Test
    @DisplayName("์Šคํ„ฐ๋”” ๋งŒ๋“ค๊ธฐ")
    void create_new_study() {
        Study study = new Study(-10, 25);
        assertNotNull(study);
    }

3. assertTrue(boolean)

๋‹ค์Œ ์กฐ๊ฑด์ด ์ฐธ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

    @Test
    @DisplayName("๋ฉค๋ฒ„ ๋งŒ๋“ค๊ธฐ")
    void create_new_member() {
        Member member = new Member("๊ณ ์–‘์ด");
        assertTrue(member.getName().equals("๊ณ ์–‘์ด"), () -> "๋ฉค๋ฒ„ ์ด๋ฆ„์ด ๊ณ ์–‘์ด๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.")
    }

4. assertAll(executable...)

๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

๊ธฐ์กด์—๋Š” ์ด์ „์˜ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ๋‹ค์Œ ํ…Œ์ŠคํŠธ๊ฐ€ ๋‚จ์•„์žˆ์Œ์—๋„ ๋ฐ”๋กœ ์ข…๋ฃŒํ•˜์ง€๋งŒ asserAll์„ ์‚ฌ์šฉํ•˜๋ฉด ์ผ๋‹จ ์ „๋ถ€ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

โญ๏ธ Before

    @DisplayName("assertAll")
    @Test
    void assertAllTest(){
        assertTrue(false, ()->"์ฒซ๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค.");
        assertTrue(false, ()->"๋‘๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค.");
        assertTrue(false, ()->"์„ธ๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค.");
    }

assertAll ์ ์šฉ ์ „

โญ๏ธ After

    @DisplayName("assertAll")
    @Test
    void assertAllTest() {
        assertAll(
                () -> assertTrue(false, () -> "์ฒซ๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค."),
                () -> assertTrue(false, () -> "๋‘๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค."),
                () -> assertTrue(false, () -> "์„ธ๋ฒˆ์งธ false์ž…๋‹ˆ๋‹ค.")
        );
    }

assertAll ์ ์šฉ ํ›„


5. assertThrows(expectedType, executable)

์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

    @DisplayName("assertThrows")
    @Test
    void assertThrowsTest() {
        Member member = new Member();
        member.setName("๊ณ ์–‘์ด");
        
        /*
           memberService.join(member)์„ ์ˆ˜ํ–‰ํ–ˆ์„ ๋•Œ IllegalStateException ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
        */
        assertThrows(IllegalStateException.class, () -> {
            memberService.join(member);
        });
    }

6. assertTimeout(duration, executable)

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

    @Test
    @DisplayName("ํŠน์ • ์‹œ๊ฐ„ ์•ˆ์— ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋Š”์ง€ ํ™•์ธ")
    void timeout_test() {
        assertTimeout(Duration.ofSeconds(10), () -> new Study(10, 20));

        /*
            ์‹œ๊ฐ„์ด 100 millis๊ฐ€ ์ง€๋‚ฌ๋”๋ผ๋„ ๋ธ”๋ก์•ˆ์˜ ๋ชจ๋“  ๊ตฌ๋ฌธ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ข…๋ฃŒ๋œ๋‹ค.
         */
        assertTimeout(Duration.ofMillis(100), () -> {
            new Study(10, 20);
            Thread.sleep(300);
            System.out.println("here~");
        });

        /*
            ์‹œ๊ฐ„์ด ์˜ค๋ฒ„๋˜๋ฉด ๋ธ”๋ก์•ˆ์˜ ๊ตฌ๋ฌธ์„ ๋” ์ด์ƒ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ข…๋ฃŒ์‹œํ‚จ๋‹ค.
            ThreadLocal ์„ ์‚ฌ์šฉ ํ•  ๊ฒฝ์šฐ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค.
         */
        assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
            new Study(10, 20);
            Thread.sleep(300);
            System.out.println("not here~");
        });
    }

Assertion์€ ๊ฐ€๋…์„ฑ์ด ์ข‹์ง€ ์•Š์•„ AssertThat์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” AssertJ๋ฅผ ์š”์ฆ˜์€ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

AssertJ๋Š” AssertThat("actual").isEqualTo("actual)์™€ ๊ฐ™์ด ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

AssertJ ๊ฐ™์€ ๊ฒฝ์šฐ ์ด์ „์— ์ •๋ฆฌํ•œ ์ ์ด ์žˆ์œผ๋ฉฐ, ์•„๋ž˜์˜ ๊ฒŒ์‹œ๊ธ€์—์„œ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

AssertJ ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์•Œ์•„๋ณด๊ธฐ

AssertJ๋ž€? โญ๏ธ ํ…Œ์ŠคํŠธ์— ๊ด€๋ จ๋œ ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ  ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์œผ๋กœ ๊ฐ€๋…์„ฑ ๋†’์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์„ ์ง€์›ํ•˜๋Š” ์˜คํ”ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. โญ๏ธ assertThat(๊ฒ€์ฆ๋Œ€์ƒ)๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹

dkswnkk.tistory.com

 

7.  ์กฐ๊ฑด์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ

JUnit์—์„œ๋Š” ํŠน์ •ํ•œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์— ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ex) ํŠน์ •ํ•œ OS, ํ™˜๊ฒฝ๋ณ€์ˆ˜, ์‹œ์Šคํ…œ ๋ณ€์ˆ˜์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ• ์ง€ ๋ง์ง€๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

org.junit.jupiter.api.Assumptions.*

  • assumeTrue(์กฐ๊ฑด) : ํ•ด๋‹น ์กฐ๊ฑด์ด ํ†ต๊ณผํ•ด์•ผ ์•„๋ž˜ ๋กœ์ง๋“ค์ด ์ˆ˜ํ–‰๋œ๋‹ค.
  • assumingThat(์กฐ๊ฑด, ํ…Œ์ŠคํŠธ): ์กฐ๊ฑด์ด ํ†ต๊ณผ๋ฅผ ํ•ด์•ผ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•œ ํ…Œ์ŠคํŠธ(๋กœ์ง)๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.
    @Test
    @DisplayName("์กฐ๊ฑด์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ")
    void condition_test() {

        String test_env = System.getenv("TEST_ENV");
        System.out.println(test_env);
        /*
            ์กฐ๊ฑด์— ๋งŒ์กฑํ•  ๊ฒฝ์šฐ์—๋งŒ ๋‹ค์Œ ํ…Œ์ŠคํŠธ๋กœ ๋„˜์–ด๊ฐ€๋ผ
         */
        assumeFalse("LOCAL".equalsIgnoreCase(test_env));
        System.out.println("์ถœ๋ ฅ๋˜์ง€ ์•Š์Œ.");

        /*
            ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋‹ค์Œ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด ๋„˜์–ด๊ฐ€๋ผ.
         */
        assumingThat("LOCAL".equalsIgnoreCase(test_env), () -> {
            System.out.println("์ถœ๋ ฅ ๋จ");
        });
    }

์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์กฐ๊ฑด์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • @EnabledOnOs: ํŠน์ • OS์ผ๋•Œ๋งŒ ํ…Œ์ŠคํŠธ๊ฐ€ ๋™์ž‘ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • @EnableOnJre: ํŠน์ • JRE ๋ฒ„์ „์ผ๋•Œ๋งŒ ํ…Œ์ŠคํŠธ๊ฐ€ ๋™์ž‘ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
    @Test
    @DisplayName("์šด์˜์ฒด์ œ๊ฐ€ mac์ธ ๊ฒฝ์šฐ")
    @EnabledOnOs(OS.MAC)
    void macOS_test() {
        System.out.println("macOS์ž…๋‹ˆ๋‹ค.");
    }

    @Test
    @DisplayName("์šด์˜์ฒด์ œ๊ฐ€ window์ธ ๊ฒฝ์šฐ")
    @EnabledOnOs(OS.WINDOWS)
    void windowOS_test() {
        System.out.println("windowOS์ž…๋‹ˆ๋‹ค.");
    }

    @Test
    @DisplayName("์šด์˜์ฒด์ œ๊ฐ€ window ํ˜น์€ mac์ธ ๊ฒฝ์šฐ")
    @EnabledOnOs({OS.WINDOWS, OS.MAC})
    void windowOS_macOS_test() {
        System.out.println("windowOS ํ˜น์€ macOS์ž…๋‹ˆ๋‹ค.");
    }

    @Test
    @DisplayName("ํŠน์ • ์ž๋ฐ” ๋ฒ„์ „๋งŒ ์‹คํ–‰ํ•ด๋ผ")
    @EnabledOnJre(JRE.JAVA_11)
    void Jre_test() {
        System.out.println("JAVA_11์ž…๋‹ˆ๋‹ค.");
    }

 

8. ํƒœ๊น…๊ณผ ํ•„ํ„ฐ๋ง

JUnit5์—์„œ๋Š” ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๋งŒ๋“ค๊ณ  ์›ํ•˜๋Š” ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

@Tag: ํƒœ์ŠคํŠธ ๋ฉ”์„œ๋“œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ํƒœ๊ทธ ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ•˜๋‚˜์˜ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์— ์—ฌ๋Ÿฌ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

    /*
        fast ํƒœ๊ทธ๋Š” ๋กœ์ปฌ์—์„œ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ๊ฐ€์ •.
     */
    @Test
    @DisplayName("Tag ํ…Œ์ŠคํŠธ")
    @Tag("fast")
    void tag1_test() {
        Study actual = new Study(20, 20);
        assertNotNull(actual);
    }

    /*
        slow ํƒœ๊ทธ๋Š” CI ํ™˜๊ฒฝ์—์„œ ์ˆ˜ํ–‰ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •.
     */
    @Test
    @DisplayName("Tag ํ…Œ์ŠคํŠธ")
    @Tag("slow")
    void tag2_test() {
        Study actual = new Study(20, 20);
        assertNotNull(actual);
    }

์œ„์ฒ˜๋Ÿผ fast์™€ slowํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , fast๋Š” ๋กœ์ปฌ์—์„œ, ์˜ค๋žœ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๋Š” slow๋Š” CI์—์„œ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒœ๊ทธ ์ง€์ • ํ›„ ์›ํ•˜๋Š” ํƒœ๊ทธ๋งŒ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก ์•„๋ž˜์™€ ๊ฐ™์ด ํ•„ํ„ฐ๋ง ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ•„ํ„ฐ๋ง ๋ฐฉ๋ฒ•(MAC ๊ธฐ์ค€)

InteliJ -> Run -> Edit Configurations... -> ์ขŒ์ธก์˜ + ๋ฒ„ํŠผ -> JUnit ์„ ํƒ -> ์›ํ•˜๋Š” ํƒœ๊ทธ ์„ธํŒ…

์„ค์ • ์ฐฝ

Maven์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด Maven - pom.xml ์ž‘์„ฑ์„ ํ†ตํ•ด ํ•„ํ„ฐ๋ง ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. (| ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•ด ๋‹ค์ˆ˜์˜ ํƒœ๊ทธ๋„ ์ง€์ • ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.)

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <groups>fast | slow</groups>
    </configuration>
</plugin>

 

9. ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณตํ•˜๊ธฐ

์ธ์ž๊ฐ€ ๋žœ๋ค๊ฐ’์ด๊ฑฐ๋‚˜, ํ…Œ์ŠคํŠธ ๋ฐœ์ƒ ์‹œ์ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ๊ฐ’ ๋•Œ๋ฌธ์—, ํ…Œ์ŠคํŠธ ๋‚ด์šฉ์ด ๋ฐ˜๋ณต๋˜์•ผํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? JUnit์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณต์„ ์œ„ํ•œ ์• ๋…ธํ…Œ์ด์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

1. @RepeatedTest

๋ฐ˜๋ณต ํšŸ์ˆ˜์™€ ๋ฐ˜๋ณต ํ…Œ์ŠคํŠธ ์ด๋ฆ„์„ ์„ค์ •ํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. 

  • {displayName}: @DisplayName์œผ๋กœ ์„ค์ •ํ•œ ํ…Œ์ŠคํŠธ์˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • {currentRepetition}: ํ˜„์žฌ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ช‡ ๋ฒˆ ๋ฐ˜๋ณต๋˜์—ˆ๋Š”์ง€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • {totalRepetition}: ์ „์ฒด ํ…Œ์ŠคํŠธ๊ฐ€ ๋ช‡๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š”์ง€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    @DisplayName("ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณตํ•˜๊ธฐ")
    @RepeatedTest(3)
    void repeat_test_v1() {
        System.out.println("๋ฐ˜๋ณต");
    }

    @DisplayName("ํ…Œ์ŠคํŠธ ํ˜„์žฌ ํšŸ์ˆ˜์™€ ๋‚จ์€ ํšŸ์ˆ˜ ์ถœ๋ ฅํ•˜๊ธฐ")
    @RepeatedTest(3)
    void repeat_test_v2(RepetitionInfo repeatInfo) {
        System.out.println("๋ฐ˜๋ณต " + repeatInfo.getCurrentRepetition() + "/" + repeatInfo.getTotalRepetitions());
    }

    @DisplayName("ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ๋ช…์‹œํ•˜๊ธฐ")
    @RepeatedTest(value = 3, name = "{currentRepetition}/{totalRepetitions}")
    void repeat_test_v3(RepetitionInfo repeatInfo) {
        System.out.println("๋ฐ˜๋ณต " + repeatInfo.getCurrentRepetition() + "/" + repeatInfo.getTotalRepetitions());
    }

์ˆ˜ํ–‰ ๊ฒฐ๊ณผ


2. @ParameterizedTest

ํ…Œ์ŠคํŠธ์— ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋Œ€์ž…ํ•ด๊ฐ€๋ฉฐ ๋ฐ˜๋ณต ์‹คํ–‰ํ•˜๋Š” ์• ๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.

  • @ValueSource: ์†์„ฑ์— ์„ ์–ธํ•ด ์ค€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ธ์ž ๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•˜๋Š”๋ฐ, Stringํƒ€์ž…๋ฟ ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์›์‹œ ํƒ€์ž…์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • {displayName}: @DisplayName ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ์„ค์ •ํ•œ ํ…Œ์ŠคํŠธ์˜ ์ด๋ฆ„
  • {index}: ํ˜„์žฌ ๋ฐ˜๋ณต๋œ ํ…Œ์ŠคํŠธ์˜ ์ธ๋ฑ์Šค
  • {arguments}: ์ „๋‹ฌ๋˜๋Š” ์ธ๋ฑ์Šค ์ „์ฒด
  • {0}, {1} ...: ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ธ๋ฑ์Šค๋กœ ์กฐํšŒ
    /*
        ๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค.
     */
    @DisplayName("๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
    @ParameterizedTest(name = "{index} {displayName} message={0}")
    @ValueSource(strings = {"๋‚ ์”จ๊ฐ€", "๋งŽ์ด", "์ถ”์›Œ์ง€๊ณ ", "์žˆ๋„ค์š”"})
    void parameterizedTest(String message) {
        System.out.println(message);
    }

    @DisplayName("๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
    @ParameterizedTest(name = "{index} {displayName} message={0}")
    @ValueSource(ints = {10, 20, 40})
    void parameterizedTest(Integer message) {
        System.out.println(message);
    }

์ˆ˜ํ–‰ ๊ฒฐ๊ณผ


3. ์ธ์ž ๊ฐ’๋“ค์˜ ์†Œ์Šค

์ธ์ž ๊ฐ’๋“ค์„ ์ œ๊ณตํ•ด์ฃผ๋Š” ์• ๋…ธํ…Œ์ด์…˜์€ ๋” ๋‹ค์–‘ํ•˜๊ฒŒ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • @ValueSource: ๋‹ค์–‘ํ•œ ๊ธฐ๋ณธ ํƒ€์ž…์˜ ์ธ์ž ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • @NullSource, @EmptySource, @NullAndEmptySource: Null๊ณผ ๊ณต๋ฐฑ ๋ฌธ์ž๋ฅผ ๊ฐ๊ฐ ์ œ๊ณตํ•ด์ฃผ๊ฑฐ๋‚˜ ํ•œ ๋ฒˆ์— ์ œ๊ณตํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • @EnumSource: Enum์˜ ๊ฐ’์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    /*
       EmptySource๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น„์–ด์žˆ๋Š” ๋ฌธ์ž์—ด์„ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.
    */
    @DisplayName("๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
    @ParameterizedTest(name = "{index} {displayName} message={0}")
    @ValueSource(strings = {"๋‚ ์”จ๊ฐ€", "๋งŽ์ด", "์ถ”์›Œ์ง€๊ณ ", "์žˆ๋„ค์š”"})
    @EmptySource
    void parameterizedWithEmptySourceTest(String message) {
        System.out.println(message);
    }

    /*
       NullSource๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Null์„ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.
    */
    @DisplayName("๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
    @ParameterizedTest(name = "{index} {displayName} message={0}")
    @ValueSource(strings = {"๋‚ ์”จ๊ฐ€", "๋งŽ์ด", "์ถ”์›Œ์ง€๊ณ ", "์žˆ๋„ค์š”"})
    @NullSource
    void parameterizedWithNullSourceTest(String message) {
        System.out.println(message);
    }

    /*
       NullAndEmptySource๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Null๊ณผ ๋นˆ ๋ฌธ์ž์—ด์„ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.
    */
    @DisplayName("๋ฐ˜๋ณต์ ์ธ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ")
    @ParameterizedTest(name = "{index} {displayName} message={0}")
    @ValueSource(strings = {"๋‚ ์”จ๊ฐ€", "๋งŽ์ด", "์ถ”์›Œ์ง€๊ณ ", "์žˆ๋„ค์š”"})
    @NullAndEmptySource
    void parameterizedWithNullAndEmptySourceTest(String message) {
        System.out.println(message);
    }

์ˆ˜ํ–‰ ๊ฒฐ๊ณผ

 

10. ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค

JUnit์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

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

@TestInstance(Lifecycle.PER_CLASS)

  • ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ ๊ฐ„์— ๊ณต์œ ํ•˜๋Š” ๋ชจ๋“  ์ƒํƒœ๋ฅผ @BeforeEach ๋˜๋Š” @AfterEach์—์„œ ์ดˆ๊ธฐํ™”ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • @BeforeAll๊ณผ @AfterAll์„ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ•œ default ๋ฉ”์„œ๋“œ๋กœ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

โญ๏ธ Before

public class InstanceTest {
    int _instance = 1;

    @AfterEach
    void plus() {
        _instance++;
    }

    @RepeatedTest(10)
    void test() {
        System.out.println(_instance);
    }
}

@TestInstance(Lifecycle.PER_CLASS) ์ ์šฉ ์ „

@TestInstance(Lifecycle.PER_CLASS) ์ ์šฉ ์ „์˜ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. ๋ถ„๋ช… @AfterEach๋ฅผ ํ†ตํ•ด์„œ ๋งค๋ฒˆ ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚  ๋•Œ๋งˆ๋‹ค _instance ๊ฐ’์„ +1 ํ•˜๋„๋ก ์„ค์ •ํ–ˆ์ง€๋งŒ ๋งค ํ…Œ์ŠคํŠธ๋Š” 1์ด ์ถœ๋ ฅ๋˜๋Š” ๋ชจ์Šต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โญ๏ธ After

@TestInstance(Lifecycle.PER_CLASS)
public class InstanceTest {
    int _instance = 1;

    @AfterEach
    void plus() {
        _instance++;
    }

    @RepeatedTest(10)
    void test() {
        System.out.println(_instance);
    }
}

@TestInstance(Lifecycle.PER_CLASS) ์ ์šฉ ํ›„

@TestInstance(Lifecycle.PER_CLASS) ์ ์šฉ ํ›„์˜ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๋Œ€๋กœ _instance๊ฐ’์ด ์ฆ๊ฐ€ํ•ด์„œ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

11. ํ…Œ์ŠคํŠธ ์ˆœ์„œ

ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋Š” ์ •์˜ ํ•œ ์ˆœ์„œ๋Œ€๋กœ ์ฐจ๋ก€๋Œ€๋กœ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ•˜๋‚˜์˜ ๋‹จ์œ„(ํ…Œ์ŠคํŠธ)๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์— ์˜ํ–ฅ์„ ์ฃผ๋ฉด ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.(ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ด์œ )

ํ•˜์ง€๋งŒ ํŠน์ • ์ˆœ์„œ๋Œ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ด ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // ํ…Œ์ŠคํŠธ์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ์‹คํ–‰์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
public class OrderTest {
    @DisplayName("์ด ํ…Œ์ŠคํŠธ๊ฐ€ ๋‘๋ฒˆ์งธ ์ˆœ์„œ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.")
    @Test
    @Order(2)
    void secondTest() {
        System.out.println("๋‘ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋˜์–ด์•ผ๋งŒ ํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.");
    }

    @DisplayName("์ด ํ…Œ์ŠคํŠธ๊ฐ€ ์„ธ๋ฒˆ์งธ ์ˆœ์„œ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.")
    @Test
    @Order(3)
    void thirdTest() {
        System.out.println("์„ธ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋˜์–ด์•ผ๋งŒ ํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.");
    }

    @DisplayName("์ด ํ…Œ์ŠคํŠธ๊ฐ€ ์ฒซ๋ฒˆ์งธ ์ˆœ์„œ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค.")
    @Test
    @Order(1)
    void firstTest() {
        System.out.println("์ฒซ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋˜์–ด์•ผ๋งŒ ํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.");
    }

์ˆ˜ํ–‰ ๊ฒฐ๊ณผ

 

ํ…Œ์ŠคํŠธ ๊ด€๋ จ ๊ฐ™์ด ๋ณด๋ฉด ์ข‹์€ ๊ธ€

๋Œ“๊ธ€