Slide 1

Slide 1 text

Try KotlinTest Rui Kowase @rkowase

Slide 2

Slide 2 text

自己紹介 ● 名前: 小和瀬 塁(こわせ るい) ● アカウント: @rkowase 2

Slide 3

Slide 3 text

今日の話 https://github.com/kotlintest/kotlintest KotlinTest is a flexible and comprehensive testing tool for Kotlin.

Slide 4

Slide 4 text

Assertion Lib (Test Framework) for Kotlin 名前 GitHub Star 簡単な説明 spek 970 Spec風、Java 8 Only kotlintest 593 Spec風 expekt 96 メソッドチェーン記法、更新頻度低 Assertk 78 AssertJ風 knit 57 DroidKaigi 2017アプリで利用、更新頻度低 (2017/12/15時点)

Slide 5

Slide 5 text

導入(Gradle) testImplementation 'io.kotlintest:kotlintest:2.0.7'

Slide 6

Slide 6 text

基本的な使い方 // test cases in init block class MyTests : StringSpec() { init { // tests here } } // test cases in lambda expression class MyTests : StringSpec({ // tests here })

Slide 7

Slide 7 text

基本的な使い方 // test cases in init block class MyTests : StringSpec() { init { // tests here } } // test cases in lambda expression class MyTests : StringSpec({ // tests here })

Slide 8

Slide 8 text

基本的な使い方 // test cases in init block class MyTests : StringSpec() { init { // tests here } } // test cases in lambda expression class MyTests : StringSpec({ // tests here })

Slide 9

Slide 9 text

基本的な使い方 // test cases in init block class MyTests : StringSpec() { init { // tests here } } // test cases in lambda expression class MyTests : StringSpec({ // tests here })

Slide 10

Slide 10 text

色々なSpec Spec 簡単な説明 String Spec StringSpec reduces the syntax to the absolute minimum. Fun Spec FunSpec allows you to create tests similar to the junit style. Should Spec ShouldSpec is similar to fun spec, but uses the keyword should instead of test. Word Spec WordSpec uses the keyword should and uses that to nest test blocks after a context string. Feature Spec FeatureSpec allows you to use feature and scenario. Behavior Spec BehaviorSpec allows you to use given, when, then. Free Spec FreeSpec allows you to nest arbitary levels of depth using the keyword - (minus).

Slide 11

Slide 11 text

String Spec class MyTests : StringSpec() { init { "strings.length should return size of string" { "hello".length shouldBe 5 } } }

Slide 12

Slide 12 text

Word Spec class MyTests : WordSpec() { init { "String.length" should { "return the length of the string" { "sammy".length shouldBe 5 "".length shouldBe 0 } } } }

Slide 13

Slide 13 text

Word Spec class MyTests : WordSpec() { init { "String.length" should { "return the length of the string" { "sammy".length shouldBe 5 "".length shouldBe 0 } } } }

Slide 14

Slide 14 text

Feature Spec class MyTests : FeatureSpec() { init { feature("the thingy bob") { scenario("should explode when I touch it") { // test here } } } }

Slide 15

Slide 15 text

Feature Spec class MyTests : FeatureSpec() { init { feature("the thingy bob") { scenario("should explode when I touch it") { // test here } } } }

Slide 16

Slide 16 text

Behavior Spec class MyTests : BehaviorSpec() { init { given("a broomstick") { `when`("I sit on it") { then("I should be able to fly") { // test code } } } } }

Slide 17

Slide 17 text

Behavior Spec class MyTests : BehaviorSpec() { init { given("a broomstick") { `when`("I sit on it") { then("I should be able to fly") { // test code } } } } }

Slide 18

Slide 18 text

Free Spec class MyTests : FreeSpec() { init { "String.length" - { "should return the length of the string" { "sammy".length shouldBe 5 "".length shouldBe 0 } } } }

Slide 19

Slide 19 text

Free Spec class MyTests : FreeSpec() { init { "String.length" - { "should return the length of the string" { "sammy".length shouldBe 5 "".length shouldBe 0 } } } }

Slide 20

Slide 20 text

Intercepting a Test Case override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { // before test() // don't forget to call test()! // after }

Slide 21

Slide 21 text

Intercepting a Test Case override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { // before test() // don't forget to call test()! // after } setUp()

Slide 22

Slide 22 text

Intercepting a Test Case override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { // before test() // don't forget to call test()! // after } tearDown()

Slide 23

Slide 23 text

AndroidのPresenterのテストで使ってみる class StringSpecTest : StringSpec() { @Mock lateinit var mRepository: GitHubRepository @Mock lateinit var mView: GitHubContract.View lateinit var mPresenter: GitHubPresenter lateinit var mSchedulerProvider: BaseSchedulerProvider override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { MockitoAnnotations.initMocks(this) mSchedulerProvider = ImmediateSchedulerProvider() mPresenter = GitHubPresenter(mRepository, mView, mSchedulerProvider) test() // don't forget to call test()! }

Slide 24

Slide 24 text

AndroidのPresenterのテストで使ってみる class StringSpecTest : StringSpec() { @Mock lateinit var mRepository: GitHubRepository @Mock lateinit var mView: GitHubContract.View lateinit var mPresenter: GitHubPresenter lateinit var mSchedulerProvider: BaseSchedulerProvider override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { MockitoAnnotations.initMocks(this) mSchedulerProvider = ImmediateSchedulerProvider() mPresenter = GitHubPresenter(mRepository, mView, mSchedulerProvider) test() // don't forget to call test()! }

Slide 25

Slide 25 text

AndroidのPresenterのテストで使ってみる class StringSpecTest : StringSpec() { @Mock lateinit var mRepository: GitHubRepository @Mock lateinit var mView: GitHubContract.View lateinit var mPresenter: GitHubPresenter lateinit var mSchedulerProvider: BaseSchedulerProvider override fun interceptTestCase(context: TestCaseContext, test: () -> Unit) { MockitoAnnotations.initMocks(this) mSchedulerProvider = ImmediateSchedulerProvider() mPresenter = GitHubPresenter(mRepository, mView, mSchedulerProvider) test() // don't forget to call test()! }

Slide 26

Slide 26 text

AndroidのPresenterのテストで使ってみる init { "Should init service when presenter started"{ mPresenter.start() verify(mRepository).initService() } "Should show error when request failed"{ Mockito.`when`(mRepository.request("")).thenRetrn(Observable.error(Exception()) mPresenter.request(GitHubPresenterTest.USER) verify(mView).showError() } }

Slide 27

Slide 27 text

AndroidのPresenterのテストで使ってみる init { "Should init service when presenter started"{ mPresenter.start() verify(mRepository).initService() } "Should show error when request failed"{ Mockito.`when`(mRepository.request("")).thenRetrn(Observable.error(Exception()) mPresenter.request(GitHubPresenterTest.USER) verify(mView).showError() } }

Slide 28

Slide 28 text

AndroidのPresenterのテストで使ってみる init { "Should init service when presenter started"{ mPresenter.start() verify(mRepository).initService() } "Should show error when request failed"{ Mockito.`when`(mRepository.request("")).thenRetrn(Observable.error(Exception()) mPresenter.request(GitHubPresenterTest.USER) verify(mView).showError() } }

Slide 29

Slide 29 text

問題点(気になるところ) ● StringSpec以外だとlateinitな変数がInterceptingできない(?) ○ https://github.com/kotlintest/kotlintest/issues/174 ● BehaviorSpecがgiven-when-thenなので、予約語のwhenをエスケープ (`when`)しないといけない ○ Spekはdescribe-on-it形式なのでエスケープ不要

Slide 30

Slide 30 text

その他機能色々 ● Property Testing ● Table-driven Testing ● Matchers ● Inspectors ● Eventually ● etc...

Slide 31

Slide 31 text

参考 kotlintest/reference.md at master · kotlintest/kotlintest https://github.com/kotlintest/kotlintest/blob/master/doc/reference.md Spek User Guide http://spekframework.org/docs/latest/#_android

Slide 32

Slide 32 text

おまけ 32 https://qiita.com/rkowase/items/54dc44537e9af519023e