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

๐Ÿ“š์ฝ์€ ์ฑ… ์ •๋ฆฌ/์ž๋ฐ” ์ฝ”๋”ฉ์˜ ๊ธฐ์ˆ 

[์ž๋ฐ” ์ฝ”๋”ฉ์˜ ๊ธฐ์ˆ ] 6์žฅ : ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋“œ๋Ÿฌ๋‚ด๊ธฐ

6.1 Given-When-Then์œผ๋กœ ํ…Œ์ŠคํŠธ ๊ตฌ์กฐํ™”

JUnit์€ ์ž๋ฐ” ํด๋ž˜์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋Š” ์†ํ•˜์ง€ ์•Š์ง€๋งŒ ์ž๋ฐ”์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑํ•˜๋Š” ์‚ฌ์‹ค์ƒ์˜ ํ‘œ์ค€์ด๋‹ค.

๋ฉ”์„œ๋“œ์— @Test๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด JUnit์ด ์•Œ์•„์„œ ํ…Œ์ŠคํŠธ๋กœ ์‹คํ–‰ํ•œ๋‹ค.

๋ฌธ์ œ ์ฝ”๋“œ

    @Test
    void setPlanetarySpeedIs7667() {
        CruiseControl cruiseControl = new CruiseControl();
        cruiseControl.setPreset(SpeedPreset.PLANETARY_SPEED);
        Assertions.assertTrue(7667 == cruiseControl.getTargetSpeedKmh());
    }

์œ„ ํ…Œ์ŠคํŠธ๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์ข€ ๋” ์ฝ”๋“œ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜์—ฌ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ๋‹ค.

 

given, when, then ๊ตฌ์กฐ๋ฅผ ์ด์š”ํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž.

    void otherTest() {
        // given
        CruiseControl cruiseControl = new CruiseControl();

        // when
        cruiseControl.setPreset(SpeedPreset.PLANETARY_SPEED);

        // then
        Assertions.assertTrue(7667 == cruiseControl.getTargetSpeedKmh());
    }
  • given : ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ „์ œ ์กฐ๊ฑด
  • when : ์‹ค์ œ๋กœ ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰
  • then : when์—์„œ ์ˆ˜ํ–‰ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์‹ค์ œ๋กœ ๊ธฐ๋Œ€ํ–ˆ๋˜ ๊ฒฐ๊ณผ์ธ์ง€ ๊ฒ€์ฆ (assertion)

์ด๋ ‡๊ฒŒ ์„ธ ๊ฐ€์ง€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๋ฉด ๊ฐ ๋ถ€๋ถ„์ด ๋” ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

 

6.2 ์˜๋ฏธ ์žˆ๋Š” ์–ด์„œ์…˜ ์‚ฌ์šฉํ•˜๊ธฐ

'assertTrue()' ๋ง๊ณ  'assertEquals()' ๋ฅผ ์‚ฌ์šฉํ•˜์ž.
Assertions.assertTrue(7667 == cruiseControl.getTargetSpeedKmh());

assertTrue ์‚ฌ์šฉ ์‹œ ์„ฑ๊ณต ์‹œ์—๋Š” ๋ฌธ์ œ์—†์ด ์ž‘๋™ํ•˜์ง€๋งŒ

์‹คํŒจ ์‹œ 'java.lang.AssertionError'๋ผ๋Š” ์Šคํƒ์ถ”์ ์„ ๋ฐ›๋Š”๋ฐ ์—ฌ๊ธฐ์— ์ฃผ์–ด์ง„ ์ •๋ณด๋Š” (์‹คํŒจํ•œ ํด๋ž˜์Šค, ์‹คํŒจํ•œ ์ค„ ๋ฒˆํ˜ธ)๋ง๊ณ  ์–ด๋– ํ•œ ๋ฉ”์‹œ์ง€๋„ ์—†๋‹ค. ๋”ฐ๋ผ์„œ, ์–ด๋–ค ์–ด์„œ์…˜์ด ์™œ ์‹คํŒจํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค..

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋” ์ž์„ธํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ์–ด์„œ์…˜์— ์ •๋ณด๋ฅผ ๋„ฃ์œผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ??

Assertions.assertEquals(7667, cruiseControl.getTargetSpeedKmh());

assertEquals๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด JUnit ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ ํ›จ์”ฌ ๋‚˜์€ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ณตํ•œ๋‹ค. --> ex) expected <7667> but was <1337>

 

์ด์™ธ์—๋„ ๋งŽ์€ assertion์ด ์žˆ๋‹ค. ๊ฐ ํ…Œ์ŠคํŠธ์˜ ์ƒํ™ฉ์— ๋งž์ถฐ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์–ด์„œ์…˜์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

 

6.3 ์‹ค์ œ ๊ฐ’๋ณด๋‹ค ๊ธฐ๋Œ€ ๊ฐ’์„ ๋จผ์ € ๋ณด์ด๊ธฐ

('๊ธฐ๋Œ€', '์‹ค์ œ')

assertionEquals() ์‚ฌ์šฉ์‹œ ์ฃผ์˜ํ•  ์ !!

assertEquals(์ฒซ๋ฒˆ์งธ ์ธ์ž = ๊ธฐ๋Œ“๊ฐ’, ๋‘๋ฒˆ์งธ ์ธ์ž = ์‹ค์ œ ๊ฐ’)

 

์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” ๊ธฐ๋Œ“๊ฐ’, ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ์‹ค์ œ๊ฐ’์œผ๋กœ ๋“ค์–ด๊ฐ€๋Š” ์ธ์ž ์ˆœ์„œ๋ฅผ ๊ผญ ์ง€์ผœ์•ผ๋งŒ ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ์ธ์ž์˜ ์ˆœ์„œ๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด ๋ฉ”์‹œ์ง€๋ฅผ ์˜ค์ธํ•˜๊ฒŒ ๋˜๊ณ  ์ด๋Š” ์ž˜๋ชป๋œ ๋””๋ฒ„๊น…์œผ๋กœ ๋”์šฑ ๊นŠ์€ ์˜ค๋ฅ˜๋กœ ๋น ์ง€๊ฒŒ ๋  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” ๋งค์šฐ ์‚ฌ์†Œํ•˜์ง€๋งŒ ์ค‘์š”ํ•œ ๋ฌธ์ œ์ด๋‹ค.

 

6.4 ํ•ฉ๋‹นํ•œ ํ—ˆ์šฉ๊ฐ’ ์‚ฌ์šฉํ•˜๊ธฐ

    @Test
    void testFilling() {
        OxygenTank tank = OxygenTank.withCapacity(100);

        tank.fill(5.8);
        tank.fill(5.6);

        Assertions.assertEquals(0.114, tank.getStatus());
    }

์œ„ ์ฝ”๋“œ๋Š” 0.114์™€ ํƒฑํฌ์˜ ์ƒํƒœ๊ฐ’์„ ๋น„๊ตํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด ํ…Œ์ŠคํŠธ๋Š” ์˜ˆ์ƒ์น˜ ๋ชปํ•˜๊ฒŒ ์‹คํŒจํ•  ํ™•๋ฅ ์ด ์žˆ๋Š” ์ฝ”๋“œ์ด๋‹ค.

 

์™œ๋ƒ๋ฉด ๋ถ€๋™์†Œ์ˆ˜์  ์—ฐ์‚ฐ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋น„ํŠธ ์ˆ˜๋Š” ์ œํ•œ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์•„์ฃผ์•„์ฃผ ์ž‘์€ ์˜ค์ฐจ๋Š” ์šฉ์ธํ•˜๊ณ  ๊ทผ์‚ฌ๊ฐ’์œผ๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋œ๋‹ค.

 

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋Œ€ํ–ˆ๋˜ ๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์˜ ๊ทผ์‚ฌ ๊ฐ’์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

 

๋”ฐ๋ผ์„œ, ๋ถ€๋™์†Œ์ˆ˜์  ์—ฐ์‚ฐ์„ ํ…Œ์ŠคํŠธํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ์†Œ์ˆซ์  ์ž๋ฆฟ์ˆ˜๋ฅผ ๋ช…์‹œํ•ด์•ผ๋งŒ ํ•œ๋‹ค.

๊ฐœ์„  ์ฝ”๋“œ (3๋ฒˆ์งธ ์ธ์ž๋กœ ๋ช‡๋ฒˆ์งธ ์ž๋ฆฌ๊นŒ์ง€ ์ฐจ์ด๋ฅผ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋ณผ ๊ฒƒ์ธ์ง€ ์ธ์ž๋ฅผ ๋„˜๊น€)

    static final double TOLERANCE = 0.00001;
    
    @Test
    void testFilling() {
        OxygenTank tank = OxygenTank.withCapacity(100);

        tank.fill(5.8);
        tank.fill(5.6);

        Assertions.assertEquals(0.114, tank.getStatus(), TOLERANCE);
    }

6.5 ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” JUnit์— ๋งก๊ธฐ๊ธฐ

๋ฌธ์ œ ์ฝ”๋“œ

class LogbookTest {

    @Test
    void readLogbook() {
        Logbook logbook = new Logbook();

        try {
            List<String> entries = logbook.readAllEntries();
            Assertions.assertEquals(13, entries.size());
        } catch (IOException e) {
            Assertions.fail(e.getMessage());
        }
    }

    @Test
    void readLogbookFail() {
        Logbook logbook = new Logbook();

        try {
            logbook.readAllEntries();
            Assertions.fail("read should fail");
        } catch (IOException ignored) {}
    }
}

๋‘ ํ…Œ์ŠคํŠธ ๋ชจ๋‘ ์ •์ƒ ์‹คํ–‰๋˜์ง€๋งŒ ๋‹จ์ ์„ ๊ฐ€์ง„๋‹ค.

 

์ฒซ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ๋Š” '์›์ธ์‚ฌ์Šฌ'์ด ๊นจ์ง„๋‹ค. ๋ฉ”์‹œ์ง€๋งŒ ์ œ๊ณตํ•  ๋ฟ ์ „์ฒด ์˜ˆ์™ธ๋ฅผ ์Šคํƒ ์ถ”์ ์œผ๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋‘๋ฒˆ์งธ ํ…Œ์ŠคํŠธ๋Š” ์˜ˆ์™ธ๊ฐ€ ์ผ์–ด๋‚˜๊ธธ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋กœ๋Š” ์™œ ์˜ˆ์™ธ๊ฐ€ ์ผ์–ด๋‚˜์•ผ๋งŒ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค...

 

๊ฐœ์„  ์ฝ”๋“œ
class LogbookTest {

    @Test
    void readLogbook() throws IOException {
        Logbook logbook = new Logbook();

        List<String> entries = logbook.readAllEntries();

        Assertions.assertEquals(13, entries.size());
    }

    @Test
    void readLogbookFail() {
        Logbook logbook = new Logbook();

        Executable when = () -> logbook.readAllEntries();

        Assertions.assertThrows(IOException.class, when);
    }
}

 

ํ…Œ์ŠคํŠธ์—์„œ ์˜ˆ์™ธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜์ง€ ๋ง๊ณ  ๊ทธ๋ƒฅ JUnit์ด ์•Œ์•„์„œ ํ•˜๊ฒŒ ๋†”๋‘๋ฉด ๋œ๋‹ค.

 

์ฒซ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ์—์„œ try์™€ fail์„ ๋นผ๋„ '์›์ธ ์‚ฌ์Šฌ'์ด ๊นจ์ง€์ง€ ์•Š์œผ๋ฉด์„œ ์ „์ฒด ์Šคํƒ ์ถ”์ ๋„ ์ œ๊ณตํ•œ๋‹ค.

๋‘๋ฒˆ์งธ ํ…Œ์ŠคํŠธ์—์„œ๋Š” try-catch ๋Œ€์‹  assertThrows๋ฅผ ์ด์šฉํ•˜์—ฌ ์ธ์ž๋กœ ์˜ˆ์™ธ๊ฐ€ ์ƒ๊ธฐ๊ธธ ๋ฐ”๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์–ด๋–ค ์ข…๋ฅ˜์˜ ์˜ˆ์™ธ๋ฅผ ๋ฐ”๋ผ

๋Š”์ง€๋„ ๋ช…์‹œํ•œ๋‹ค.

6.6 ํ…Œ์ŠคํŠธ ์„ค๋ช…ํ•˜๊ธฐ

์ข‹์€ ์ฝ”๋“œ

class OxygenTankTest {
    static final double PERMILLE = 0.001;

    @Test
    @DisplayName("Expect 44% after filling 22l in an empty 50l tank")
    @Disabled("We don't have small tanks anymore! TODO: Adapt for big tanks")
    void fillTank() {
        OxygenTank smallTank = OxygenTank.withCapacity(50);

        smallTank.fill(22);

        Assertions.assertEquals(0.44, smallTank.getStatus(), PERMILLE);
    }

    @Test
    @DisplayName("Fail if fill level > tank capacity")
    void failOverfillTank() {
        OxygenTank bigTank = OxygenTank.withCapacity(10_000);
        bigTank.fill(5344.0);

        Executable when = () -> bigTank.fill(6000);

        Assertions.assertThrows(IllegalArgumentException.class, when);
    }
}

์œ„ ์ฝ”๋“œ๋Š” Given-When-Then ๊ตฌ์กฐ, ํ•ฉ๋‹นํ•œ ํ—ˆ์šฉ๊ฐ’, JUnit์— ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ๋งก๊ธฐ๋Š” ํ–‰๋™์„ ํ•˜๋ฉฐ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋‹ค.

 

๊ฑฐ๊ธฐ์— ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ '์ด๋ฆ„'๊ณผ '์„ค๋ช…์„œ'๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ํ•œ์ธต ๋” ์ข‹์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ด๋‹ค.

 

ํ…Œ์ŠคํŠธ์— ์‹คํŒจํ–ˆ์„ ๋•Œ ์ข‹์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„  ์ข‹์€ ๋ฉ”์„œ๋“œ๋ช…๊ณผ ํ…Œ์ŠคํŠธ ์„ค๋ช…์ด ํ•„์š”ํ•˜๋‹ค.

testfill2() ๋Œ€์‹  failOverfillTank() ์ฒ˜๋Ÿผ ์˜๋„๋ฅผ ๋“ค์–ด๋‚ด๋Š” ๋ฉ”์„œ๋“œ ๋ช…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. (์˜ค๋ฅ˜์‹œ ํ…Œ์ŠคํŠธ๋ช… ์˜๋ฏธ์žˆ๋Š” ํ…Œ์ŠคํŠธ ๋ช… ๋…ธ์ถœ)

@DisplayName("ํ…Œ์ŠคํŠธ ์„ค๋ช…") ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๋ช…์„ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ํ›Œ๋ฅญํ•œ ํ…Œ์ŠคํŠธ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ, @DisplayName์„ ์ด์šฉํ•ด ๋น„ํ™œ์„ฑํ™”ํ•œ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ์™œ ๋น„ํ™œ์„ฑํ™”ํ–ˆ๋Š”์ง€ ์ด์œ ๋„ ์ ์„ ์ˆ˜ ์žˆ๋‹ค.

6.7 ๋…๋ฆฝํ˜• ํ…Œ์ŠคํŠธ ์‚ฌ์šฉํ•˜๊ธฐ

๋ฌธ์ œ์ 

@BeforeEach ์™€ @BeforeAll ํ‘œ๊ธฐ๋ฅผ ์“ธ ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ ์ด ์žˆ๋‹ค.

๋‘ ํ‘œ๊ธฐ๋Š” ํ…Œ์ŠคํŠธ์˜ given์— ํ•ด๋‹นํ•˜๋Š” ํ•„์š”ํ•œ ๊ณตํ†ต ์„ค์ • ์ฝ”๋“œ๋ฅผ ์ถ”์ถœํ•ด ํ•œ๋ฒˆ๋งŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

 

ํ•˜์ง€๋งŒ ์ด๋Š” ํ…Œ์ŠคํŠธ ์ „์ฒด๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•œ๋‹ค.

 

ํด๋ž˜์Šค ์ „์ฒด๋ฅผ ์ฝ์ง€ ์•Š๊ฑฐ๋‚˜ ํ…Œ์ŠคํŠธ๊ฐ€ ๋งค์šฐ ๋งŽ์€ ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ด๋ณด์ž.

์ด๋•Œ ๋งŒ์•ฝ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๊ฒŒ๋˜๋ฉด ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋กœ ๊ฐˆํ…Œ๋‹ˆ given ๋ถ€๋ถ„์ด ์–ด๋””์ธ์ง€ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค. (์—ฌ๋Ÿฌ ์„ค์ • ๋ฉ”์„œ๋“œ๊ฐ€ ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ์— ํผ์ ธ์žˆ๋Š” ๋ณต์žกํ•œ ์ฝ”๋“œ ์ผ ๋•Œ..)

 

๊ฐœ์„  ์ฝ”๋“œ

class OxygenTankTest {
    static OxygenTank createHalfFilledTank() {
        OxygenTank tank = OxygenTank.withCapacity(10_000);
        tank.fill(5_000);
        return tank;
    }

    @Test
    void depressurizingEmptiesTank() {
        OxygenTank tank = createHalfFilledTank();

        tank.depressurize();

        Assertions.assertTrue(tank.isEmpty());
    }

    @Test
    void completelyFillTankMustBeFull() {
        OxygenTank tank = createHalfFilledTank();

        tank.fillUp();

        Assertions.assertTrue(tank.isFull());
    }
}

given, when, then ๋ถ€๋ถ์„ ํ•˜๋‚˜์˜ ํ…Œ์ŠคํŠธ ์•ˆ์—์„œ ๋ฐ”๋กœ ์—ฐ๊ฒฐํ•˜๋ฉด '๋…๋ฆฝ์ ์ธ ํ…Œ์ŠคํŠธ'๊ฐ€ ๋œ๋‹ค.

 

createHalfFilledTank()์ฒ˜๋Ÿผ static ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ฉด์„œ ๊ฐ ํ…Œ์ŠคํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๋ชจ๋“  ์ข…์†์„ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œ์‹œํ–ˆ์œผ๋ฏ€๋กœ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์ง€๊ณ  ์˜ค๋ฅ˜๋„ ์ข€ ๋” ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

 

@BeforeEach ์™€ @BeforeAll ํ‘œ๊ธฐ๋Š” ์•”๋ฌต์  ์ข…์†์„ฑ์„ ๋งŒ๋“ค์–ด๋‚ด๋ฏ€๋กœ ๊ฐ€๋Šฅํ•˜๋ฉด ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž. (๋Œ€์‹  static ๊ณต์šฉ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ)

6.8 ํ…Œ์ŠคํŠธ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™”

์—ฌ๋Ÿฌ ๋‹ค์–‘ํ•œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

class DistanceConversionTest {

    @Test
    void testConversionRoundTrip() {
        assertRoundTrip(1);
        assertRoundTrip(1_000);
        assertRoundTrip(9_999_999);
    }

    private void assertRoundTrip(int kilometers) {
        Distance expectedDistance = new Distance(
                DistanceUnit.KILOMETERS,
                kilometers
        );

        Distance actualDistance = expectedDistance
                .convertTo(DistanceUnit.MILES)
                .convertTo(DistanceUnit.KILOMETERS);

        Assertions.assertEquals(expectedDistance, actualDistance);
    }
}

๋ชจ๋“  ๊ฒ€์ฆ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜์— ๋Œ€ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๋”ฐ๋กœ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ, ํŒŒ๋ผ๋ฏธํ„ฐ '1'์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ '1000'์€ ๊ฒ€์ฆ๋„ ๋ชปํ•ด๋ณด๊ฒŒ ๋œ๋‹ค..

 

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.

๊ฐœ์„  ์ฝ”๋“œ

class DistanceConversionTest {

    @ParameterizedTest(name = "#{index}: {0}km == {0}km->mi->km")
    @ValueSource(ints = {1, 1_000, 9_999_999})
    void testConversionRoundTrip(int kilometers) {
        Distance expectedDistance = new Distance(
                DistanceUnit.KILOMETERS,
                kilometers
        );

        Distance actualDistance = expectedDistance
                .convertTo(DistanceUnit.MILES)
                .convertTo(DistanceUnit.KILOMETERS);

        Assertions.assertEquals(expectedDistance, actualDistance);
    }
}

@ParameterizedTest(name = "#{index}: {0}km == {0}km->mi->km")

@ValueSource(ints = {1, 1_000, 9_999_999})

ํ‘œ๊ธฐ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, '๋งค๊ฐœ๋ณ€์ˆ˜' ์™€ 'ํ…Œ์ŠคํŠธ์ฝ”๋“œ'๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์‹คํ–‰ํ•ด๋ณด๋ฉด JUnit์€ ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋งˆ๋‹ค ๋ณ„๊ฐœ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค.

6.9 ๊ฒฝ๊ณ„ ์ผ€์ด์Šค ๋‹ค๋ฃจ๊ธฐ

์šฐ๋ฆฌ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฐ’๋“ค์„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์—†๋‹ค. 

๋”ฐ๋ผ์„œ ํ‹€๋ฆฌ๊ธฐ ์‰ฌ์šด '๊ฒฝ๊ณ„ ์ผ€์ด์Šค'๋ฅผ ๋‹ค๋ค„์•ผ๋งŒ ํ•œ๋‹ค.

 

(๊ฒฝ๊ณ„์ผ€์ด์Šค ์˜ˆ์‹œ) 

๋ฌธ์ž์—ด -> null, "", " ", "aโˆ†¬…ห™∑s",

int -> 0, 1, -1, MAX, MIN

Object[] -> null, {}, {null} ..

๊ฒฝ๊ณ„ ์ผ€์ด์Šค ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์˜ˆ์‹œ

class TransmissionParserTest {

	// ์˜ฌ๋ฐ”๋ฅด๊ฒŒ parseํ•˜๋Š” ์ง€ ์ฒดํฌ
    @Test
    void testValidTransmission() {
        TransmissionParser parser = new TransmissionParser();

        Transmission transmission = parser.parse("032Houston, UFO sighted!");

        Assertions.assertEquals(32, transmission.getId());
        Assertions.assertEquals("Houston, UFO sighted!",
                transmission.getContent());
    }
    
	// null ์ž…๋ ฅ ์‹œ IllegalArgumentException์ด ์ž˜ ๋ฐœ์ƒํ•˜๋Š”์ง€ ์ฒดํฌ
    @Test
    void nullShouldThrowIllegalArgumentException() {
        Executable when = () -> new TransmissionParser().parse(null);
        Assertions.assertThrows(IllegalArgumentException.class, when);
    }

	// ์ด์ƒํ•œ ํŠน์ˆ˜๋ฌธ์ž ์ž…๋ ฅ ์‹œ ์˜ˆ์™ธ๊ฐ€ ์ž˜ ๋ฐœ์ƒํ•˜๋Š”์ง€ ์ฒดํฌ
    @Test
    void malformedTransmissionShouldThrowIllegalArgumentException() {
        Executable when = () -> new TransmissionParser().parse("tอกษฌษชล‹ษ‘n");
        Assertions.assertThrows(IllegalArgumentException.class, when);
    }
}

6.10 6์žฅ์—์„œ ๋ฐฐ์šด ๋‚ด์šฉ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ์‹ค์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ณด๋‹ค ๋” ๋งŽ์ด ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

 

๋”ฐ๋ผ์„œ, ํ…Œ์ŠคํŠธ ์ง‘ํ•ฉ์„ ์ž˜ ๋””์ž์ธํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

 

ํ…Œ์ŠคํŠธ๋Š”...

given-then-when +

๋…๋ฆฝ์ ์ด๋ฉฐ ํ‘œ๊ธฐ๋ฅผ ํ†ตํ•ด ์„ค๋ช…ํ•ด์•ผํ•˜๋ฉฐ +

์ ์ ˆํ•œ ์–ด์„œ์…˜์„ ์„ ํƒํ•จ์œผ๋กœ ํ…Œ์ŠคํŠธ ์ดํ•ด๋„๋ฅผ ๋†’์—ฌ์•ผ ํ•œ๋‹ค.