Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KMMのテストのtips / KMM testing tips

KMMのテストのtips / KMM testing tips

Masatoshi Kubode

July 29, 2021
Tweet

More Decks by Masatoshi Kubode

Other Decks in Programming

Transcript

  1. ©2021 Wantedly, Inc. ,PUMJO$PNNPOͷ"1*͔͠ར༻Ͱ͖ͳ͍ w +6OJU 3VMFͳͲ  w NPDLL

    w DPSPVUJOFUFTU w FUD DPNNPO5FTUͱ+7.5FTUͱͷҧ͍ // 🙅 @Rule @JvmField val rule = SomeTestRule() // 🙅 @MockK lateinit var mock: SomeInterface @Test fun test() { // 🙅 every { mock.doSomething() } just Runs doTest() // 🙅 verify { mock.doSomething() } }
  2. ©2021 Wantedly, Inc. w %#Λ࢖ͬͨ෦෼ͷςετΛ͍ͨ͠ w ςετͷͨͼʹΫϦʔϯͳ%#Λ࢖͍͍ͨ w ΫϦΞ͢ΔίʔυΛຖճॻ͘ͷ͸ਏ͍ʜ 5FTU3VMF

    class MyTest1 { lateinit var db: VisitAppDb @BeforeTest fun setup() { db = VisitAppDb(testSqlDriver()) } @AfterTest fun tearDown() { db.clean() } } class MyTest2 { lateinit var db: VisitAppDb @BeforeTest fun setup() { db = VisitAppDb(testSqlDriver()) } @AfterTest fun tearDown() { db.clean() } } class MyTest3 { lateinit var db: VisitAppDb @BeforeTest fun setup() { db = VisitAppDb(testSqlDriver()) } @AfterTest fun tearDown() { db.clean() } } class MyTest4… { lateinit var db: Visi @BeforeTest fun setup db = VisitAppDb(t } @AfterTest fun tearDo db.clean() } }
  3. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ interface TestRule { fun onBeforeTest() =

    Unit fun onAfterTest() = Unit } class TestRules(vararg testRules: TestRule) : List<TestRule> by testRules.toList() interface HasTestRules { val testRules: TestRules @BeforeTest fun setupTestRules() { testRules.forEach { it.onBeforeTest() } } @AfterTest fun tearDownTestRules() { testRules.forEach { it.onAfterTest() } } }
  4. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ interface TestRule { fun onBeforeTest() =

    Unit fun onAfterTest() = Unit } class TestRules(vararg testRules: TestRule) : List<TestRule> by testRules.toList() interface HasTestRules { val testRules: TestRules @BeforeTest fun setupTestRules() { testRules.forEach { it.onBeforeTest() } } @AfterTest fun tearDownTestRules() { testRules.forEach { it.onAfterTest() } } } ϧʔϧΛ࡞੒͢Δʹ͸5FTU3VMFΛ࣮૷
  5. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ interface TestRule { fun onBeforeTest() =

    Unit fun onAfterTest() = Unit } class TestRules(vararg testRules: TestRule) : List<TestRule> by testRules.toList() interface HasTestRules { val testRules: TestRules @BeforeTest fun setupTestRules() { testRules.forEach { it.onBeforeTest() } } @AfterTest fun tearDownTestRules() { testRules.forEach { it.onAfterTest() } } } 5FTU3VMFΛ࢖͍͍ͨ5FTUΫϥεʹ࣮૷ͤ͞Δ ͜ΕΒͷσϑΥϧτ࣮૷͕5FTUΫϥεͰࣗಈͰݺ͹ΕΔ
  6. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ class DbTestRule : TestRule { private

    lateinit var sqlDriver: SqlDriver lateinit var db: VisitAppDb private set override fun onBeforeTest() { sqlDriver = testSqlDriver() db = VisitAppDb(driver = sqlDriver) } override fun onAfterTest() { sqlDriver.close() } } class MyTest : HasTestRules { val dbTestRule = DbTestRule() override val testRules = TestRules(dbTestRule) @Test fun test() { dbTestRule.db.userQueries.insertOrReplace(User()) val all = dbTestRule.db.userQueries.selectAll().executeAsList() assertEquals(1, all.size) } }
  7. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ class DbTestRule : TestRule { private

    lateinit var sqlDriver: SqlDriver lateinit var db: VisitAppDb private set override fun onBeforeTest() { sqlDriver = testSqlDriver() db = VisitAppDb(driver = sqlDriver) } override fun onAfterTest() { sqlDriver.close() } } class MyTest : HasTestRules { val dbTestRule = DbTestRule() override val testRules = TestRules(dbTestRule) @Test fun test() { dbTestRule.db.userQueries.insertOrReplace(User()) val all = dbTestRule.db.userQueries.selectAll().executeAsList() assertEquals(1, all.size) } } 5FTU3VMFΛ࣮૷ͯ͠#FGPSF"GUFSΛهड़ UFTU4RM%SJWFS ͕ຖճ%#ΫϦΞ͍ͯ͠Δ
  8. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ class DbTestRule : TestRule { private

    lateinit var sqlDriver: SqlDriver lateinit var db: VisitAppDb private set override fun onBeforeTest() { sqlDriver = testSqlDriver() db = VisitAppDb(driver = sqlDriver) } override fun onAfterTest() { sqlDriver.close() } } class MyTest : HasTestRules { val dbTestRule = DbTestRule() override val testRules = TestRules(dbTestRule) @Test fun test() { dbTestRule.db.userQueries.insertOrReplace(User()) val all = dbTestRule.db.userQueries.selectAll().executeAsList() assertEquals(1, all.size) } } 5FTUΫϥεʹ)BT5FTU3VMFTΛ࣮૷
  9. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ class DbTestRule : TestRule { private

    lateinit var sqlDriver: SqlDriver lateinit var db: VisitAppDb private set override fun onBeforeTest() { sqlDriver = testSqlDriver() db = VisitAppDb(driver = sqlDriver) } override fun onAfterTest() { sqlDriver.close() } } class MyTest : HasTestRules { val dbTestRule = DbTestRule() override val testRules = TestRules(dbTestRule) @Test fun test() { dbTestRule.db.userQueries.insertOrReplace(User()) val all = dbTestRule.db.userQueries.selectAll().executeAsList() assertEquals(1, all.size) } } ࢖͍͍ͨ5FTU3VMFΛࢦఆ
  10. ©2021 Wantedly, Inc. 5FTU3VMF࣮૷ class DbTestRule : TestRule { private

    lateinit var sqlDriver: SqlDriver lateinit var db: VisitAppDb private set override fun onBeforeTest() { sqlDriver = testSqlDriver() db = VisitAppDb(driver = sqlDriver) } override fun onAfterTest() { sqlDriver.close() } } class MyTest : HasTestRules { val dbTestRule = DbTestRule() override val testRules = TestRules(dbTestRule) @Test fun test() { dbTestRule.db.userQueries.insertOrReplace(User(userId = 1, name = "Foo")) val all = dbTestRule.db.userQueries.selectAll().executeAsList() assertEquals(1, all.size) } } !#FGPSF5FTU!"GUFS5FTUΛॻ͔ͳͯ͘Α͘ͳΔ
  11. ©2021 Wantedly, Inc. w ςελϒϧͳઃܭʹ͢Δ w ந৅ JOUFSGBDF ʹґଘ w

    ۩৅ DMBTT PCKFDU HMPCBMGVO ʹґଘ͠ͳ͍ ςελϒϧͳઃܭ
  12. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ class ApiClient { fun createUser(): User

    { // ࣮ࡍ͸௨৴͢Δ return User(…) } } class UserRepository { fun create(): User { return ApiClient().createUser() } }
  13. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ class ApiClient { fun createUser(): User

    { // ࣮ࡍ͸௨৴͢Δ return User(…) } } class UserRepository { fun create(): User { return ApiClient().createUser() } } "QJ$MJFOUͱ͍͏۩৅Ϋϥεʹґଘ͍ͯ͠Δ
  14. ©2021 Wantedly, Inc. @Test fun test() { val user =

    UserRepository().create() // ௨৴݁Ռ͕Θ͔Βͳ͍ͷͰςετͰ͖ͳ͍ // ௨৴ࣦഊͨ͠ΒͲ͏ͳΔʁ } ςελϒϧͳઃܭ
  15. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ interface ApiClient { fun createUser(): User

    } class ApiClientImpl : ApiClient { override fun createUser(): User { // ࣮ࡍ͸௨৴͢Δ return User() } } class UserRepository(private val apiClient: ApiClient) { fun create(): User { return apiClient.createUser() } } "QJ$MJFOUͱ͍͏JOUFSGBDFʹ͢Δ
  16. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ interface ApiClient { fun createUser(): User

    } class ApiClientImpl : ApiClient { override fun createUser(): User { // ࣮ࡍ͸௨৴͢Δ return User() } } class UserRepository(private val apiClient: ApiClient) { fun create(): User { return apiClient.createUser() } } JOUFSGBDFΛ࣮૷ͨ͠*NQMΫϥεʹ͢Δ
  17. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ interface ApiClient { fun createUser(): User

    } class ApiClientImpl : ApiClient { override fun createUser(): User { // ࣮ࡍ͸௨৴͢Δ return User() } } class UserRepository(private val apiClient: ApiClient) { fun create(): User { return apiClient.createUser() } } JOUFSGBDFΛ஫ೖͯ͠JOUFSGBDFʹґଘ͢Δ
  18. ©2021 Wantedly, Inc. ςελϒϧͳઃܭ class ApiClientMock : ApiClient { lateinit

    var mock: () -> User override fun createUser() = mock() } NPDLʹϥϜμΛೖΕΔ͜ͱͰDSFBUF6TFS ͷ݁ՌΛࠩ͠ସ͑
  19. ©2021 Wantedly, Inc. @Test fun test() { val apiClient =

    ApiClientMock() apiClient.mock = { User("test") } val user = UserRepository(apiClient).create() assertEquals("test", user.id) } @Test fun testFailed() { val apiClient = ApiClientMock() apiClient.mock = { throw ExpectedException() } try { UserRepository(apiClient).create() fail() } catch (e: ExpectedException) { // Expected } } ςελϒϧͳઃܭ
  20. ©2021 Wantedly, Inc. @Test fun test() { val apiClient =

    ApiClientMock() apiClient.mock = { User("test") } val user = UserRepository(apiClient).create() assertEquals("test", user.id) } @Test fun testFailed() { val apiClient = ApiClientMock() apiClient.mock = { throw ExpectedException() } try { UserRepository(apiClient).create() fail() } catch (e: ExpectedException) { // Expected } } ςελϒϧͳઃܭ NPDLϓϩύςΟʹϥϜμΛೖΕͯϞοΫ͢Δ
  21. ©2021 Wantedly, Inc. @Test fun test() { val apiClient =

    ApiClientMock() apiClient.mock = { User("test") } val user = UserRepository(apiClient).create() assertEquals("test", user.id) } @Test fun testFailed() { val apiClient = ApiClientMock() apiClient.mock = { throw ExpectedException() } try { UserRepository(apiClient).create() fail() } catch (e: ExpectedException) { // Expected } } ςελϒϧͳઃܭ .PDLΛ஫ೖɺNPDL͕࢖ΘΕΔ
  22. ©2021 Wantedly, Inc. @Test fun test() { val apiClient =

    ApiClientMock() apiClient.mock = { User("test") } val user = UserRepository(apiClient).create() assertEquals("test", user.id) } @Test fun testFailed() { val apiClient = ApiClientMock() apiClient.mock = { throw ExpectedException() } try { UserRepository(apiClient).create() fail() } catch (e: ExpectedException) { // Expected } } ςελϒϧͳઃܭ .PDLͷ಺༰͔Βظ଴͞ΕΔ݁ՌΛςετ
  23. ©2021 Wantedly, Inc. @Test fun test() { val apiClient =

    ApiClientMock() apiClient.mock = { User("test") } val user = UserRepository(apiClient).create() assertEquals("test", user.id) } @Test fun testFailed() { val apiClient = ApiClientMock() apiClient.mock = { throw ExpectedException() } try { UserRepository(apiClient).create() fail() } catch (e: ExpectedException) { // Expected } } ςελϒϧͳઃܭ ྫ֎͕ى͖ͨͱ͖ͷςετ΋༰қʹ