Slide 1

Slide 1 text

0LJUDWLQJWR -8QLW -RDQQD+X 

Slide 2

Slide 2 text

About the Speaker Joanna Hu • Backend Engineer • Working in LINE Taiwan since 2019

Slide 3

Slide 3 text

01 02 03 Summary :KDWLV-8QLW :K\PLJUDWLQJWR-8QLW +RZWRPLJUDWHWR-8QLW

Slide 4

Slide 4 text

:KDWLV-8QLW • -8QLW-XSLWHUWKHQHZSURJUDPPLQJH[WHQVLRQPRGHOIRUZULWLQJWHVWVDQGH[WHQVLRQVLQ-8QLW • -8QLW9LQWDJH 7HVW(QJLQH IRUUXQQLQJ-8QLWDQG-8QLWEDVHGWHVWVRQWKHSODWIRUP • -8QLW3ODWIRUP IRXQGDWLRQIRUODXQFKLQJWHVWLQJIUDPHZRUNVRQWKH-90 ※Source from︓https://dzone.com/articles/7-reasons-to-consider-junit-5

Slide 5

Slide 5 text

:K\PLJUDWLQJWR-8QLW • 6XSSRUWHGLQPDMRU,'(%XLOGWRROV • ,QWHOOLM ,'($(FOLSVH96&RGH • 0DYHQ*UDGOH • (DV\PLJUDWLRQ • -8QLWWHVWVFDQFRH[LVWZLWK-8QLWWHVWV • :HFDQXVHERWK-8QLW$VVHUW- DVVHUWLRQVLQRQHWHVW • 1HZ)HDWXUHV

Slide 6

Slide 6 text

-8QLW1HZ)HDWXUHV • 1HVWHGWHVWV • 'LVSOD\QDPH • 3DUDPHWHUL]HGWHVWV • 0XOWLSOH5XQQHUV • %HWWHU$VVHUWLRQV EXWZHUHFRPPHQG$VVHUW- LQVWHDG

Slide 7

Slide 7 text

1HVWHGWHVWV • #1HVWHGFDQKDYHPXOWLSOHOHYHOV • 6XSSRUWQRQVWDWLFLQQHUFODVV class TestingAStackDemo { Stack stack; @Test void isInstantiatedWithNew() { new Stack<>(); } @Nested class WhenNew { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test void isEmpty() { assertTrue(stack.isEmpty()); } @Test void throwsExceptionWhenPopped() { assertThrows(EmptyStackException.class, stack::pop); } @Nested class AfterPushing { // more tests... } } }

Slide 8

Slide 8 text

1HVWHGWHVWV

Slide 9

Slide 9 text

'LVSOD\QDPHV • $GG#'LVSOD\1DPH DQQRWDWLRQ • 6XSSRUWDGGLQJRQFODVVPHWKRG @DisplayName("A stack") class TestingAStackDemo { Stack stack; @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { new Stack<>(); } @Nested @DisplayName("when new") class WhenNew { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test @DisplayName("is empty") void isEmpty() { assertTrue(stack.isEmpty()); } @Nested @DisplayName("after pushing an element") class AfterPushing { // more tests... } } }

Slide 10

Slide 10 text

'LVSOD\QDPHV • $GG#'LVSOD\1DPH DQQRWDWLRQ • 6XSSRUWDGGLQJRQFODVVPHWKRG

Slide 11

Slide 11 text

3DUDPHWHUL]HGWHVWV -8QLW class CalculatorJUnit5Test { @ParameterizedTest @ValueSource(strings = { "", " ", " " }) void isBlank_ShouldReturnTrueForBlankStrings(String input) { assertThat(StringUtils.isBlank(input)).isTrue(); } @ParameterizedTest @NullSource void isBlank_ShouldReturnTrueForNullStrings(String input) { assertThat(StringUtils.isBlank(input)).isTrue(); } @ParameterizedTest @CsvSource({ "0,0,0", "1,1,2" }) void add(int first, int second, int expected) { final Calculator calculator = new Calculator(); final int result = calculator.add(first, second); assertThat(result).isEqualTo(expected); } }

Slide 12

Slide 12 text

0XOWLSOH5XQQHUV -8QLWRQO\VXSSRUWVVLQJOHUXQQHUZKLOH-8QLWVXSSRUWVPXOWLSOHH[WHQVLRQV // JUnit 4 @RunWith(MockitoJUnitRunner.class) public class CMSProductServiceTest { // ... } // JUnit 5 @ExtendWith({ MockitoExtension.class, SoftAssertionsExtension.class }) public class CMSProductServiceTest { // ... }

Slide 13

Slide 13 text

+RZWRPLJUDWHWR-8QLW • 8SJUDGHWR-8QLWLQ0DYHQ*UDGOH • 8SJUDGH0DYHQWR 2U0DYHQVXUHILUHIDLOVDIHSOXJLQWR • 8SJUDGH*UDGOHWR • :ULWHQHZWHVWVLQ-8QLW • 0LJUDWHH[LVWLQJ-8QLWWHVWV • 5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ LIDQ\

Slide 14

Slide 14 text

0LJUDWHH[LVWLQJ-8QLWWHVWV JUnit 4 JUnit 5 org.junit.Test org.junit.jupiter.api.Test org.junit.Before org.junit.jupiter.api.BeforeEach org.junit.After org.junit.jupiter.api.AfterEach org.junit.BeforeClass org.junit.jupiter.api.BeforeAll org.junit.AfterClass org.junit.jupiter.api.AfterAll org.junit.Ignore org.junit.jupiter.api.Disabled org.junit.Assert org.junit.jupiter.api.Assertions (we use AssertJ) org.junit.Assert.assertThat org.hamcrest.MatcherAssert.assertThat org.junit.runner.RunWith org.junit.jupiter.api.extension.ExtendWith org.mockito.junit.MockitoJUnitRunner org.mockito.junit.jupiter.MockitoExtension org.springframework.test.context.junit4.SpringRu nner org.springframework.test.context.junit.jupiter.Spri ngExtension

Slide 15

Slide 15 text

5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ -8QLW5XOH public class EmbeddedMySqlRule extends ExternalResource { private EmbeddedMysql embeddedMysql; @Override protected void before() { // ... embeddedMysql = EmbeddedMysql.anEmbeddedMysql(config, downloadConfig) .addSchema("ecac", ScriptResolver.classPathScript("db/setup.sql")) .start(); } @Override protected void after() { if (embeddedMysql != null) { embeddedMysql.stop(); } } }

Slide 16

Slide 16 text

5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ -8QLW([WHQVLRQ public class EmbeddedMySqlExtension implements AfterAllCallback, BeforeAllCallback { private EmbeddedMysql embeddedMysql; @Override public void beforeAll(ExtensionContext extensionContext) throws Exception { // ... embeddedMysql = EmbeddedMysql.anEmbeddedMysql(config, downloadConfig) .addSchema("ecac", ScriptResolver.classPathScript("db/setup.sql")) .start(); } @Override public void afterAll(ExtensionContext extensionContext) throws Exception { if (embeddedMysql != null) { embeddedMysql.stop(); } } }

Slide 17

Slide 17 text

0LJUDWH8VLQJ,QWHOOL-,'($ 0LJUDWHRQHWHVW 0LJUDWHDOOWHVWV 5HIDFWRU!0LJUDWH https://blog.jetbrains.com/idea/2020/08/migrating-from-junit-4-to-junit-5/

Slide 18

Slide 18 text

• -8QLWZHEVLWHhttps://junit.org/junit5/ • 5HDVRQVWR&RQVLGHU-8QLWhttps://dzone.com/articles/7-reasons-to-consider-junit-5 • 0LJUDWLQJIURP-8QLWWR-8QLWhttps://blog.jetbrains.com/idea/2020/08/migrating-from-junit-4-to-junit-5/ 5HIHUHQFHV

Slide 19

Slide 19 text

THANK YOU