Help us understand the problem. What is going on with this article?

Spek2でのテストの書き方

More than 1 year has passed since last update.

DroidKaigi2019でもSpekに関するセッションがあり、触発されたのでとりあえず使い方をざっくりまとめます。

以下、Spekのバージョンは2.0.0の前提で記載します。

Spekとは

公式ドキュメント

平たく言うと、Kotlinで書かれたRspec風テストフレームワークです。
スタイルは以下の2種類を提供しています。

SetUp

Setting Up - Android

動作要件

  • JDK8
  • JUnit5

注意点

  • Android integration テストには対応していません
  • RobolectricなどはJUnit4で書く必要があるため、両方で動かすにはjunit-vintageなども入れる必要があります

書き方

ここでは specification スタイルでの解説になります。

上記ドキュメントの「Best practices」のセクションに記載されていますが、以下2つの観点でテストを実装すると良いです。

  • 副作用を検証する
  • 戻り値を検証する

また、specification でのコンセプトは以下の通りです

Suites

  • describe, contextを用いて仕様のグループ化に利用します。
  • 入れ子で定義することもできます。
  • contextdescribeの中で定義することができます。
  • 通常、以下のように記載することが多いようです。
    • describe
      • テスト対象
    • context
      • テスト条件

Specs

  • itを用いて何をチェクするかなどのアウトプットに関する内容を記述します。

Skipping

  • describe, context, itxをつけることで、そのテストをスキップすることができます。
  • もしくは、第二引数にSkip.Yesを指定することでスキップすることもできます。
  • テストにスキップの指定をする場合は必ず理由を記述します。

Aliases

  • describe, contextブロックのテスト前後に実行したい処理はbefore / afterbeforeEach / afterEachを利用して記載します。
  • before / afterbeforeGroup / afterGroup と同じで、各describe, contextブロックの開始 / 終了時に呼ばれます
  • beforeEach / afterEachbeforeEachTest / afterEachTest と同じで宣言したブロック内(入れ子も含む)のテストの前後で呼ばれます
  • 入れ子のブロックでそれぞれ宣言した場合の呼び出し順序は以下の通りです
    • beforeは外側で宣言したものからafterは内側で宣言したものから呼ばれます
    • 入れ子になっていても宣言されているbeforeがすべて呼ばれた後にbeforeEachが呼ばれます(afterはその逆)

以下、入れ子での呼び出し順を試したサンプルコードとその実行結果です。

@RunWith(JUnitPlatform::class)
class SpekSampleTest : Spek({
    describe("1 - describe") {
        before {
            println("1 - before")
        }
        beforeEach {
            println("1 - beforeEach")
        }
        context("1 - 1 - context") {
            before {
                println("1 - 1 - before")
            }
            beforeEach {
                println("1 - 1 - beforeEach")
            }
            it("1 - 1 - it") {
                println("1 - 1 - it")
            }
            afterEach {
                println("1 - 1 - afterEach")
            }
            after {
                println("1 - 1 - after")
            }
        }
        context("1 - 2 - context") {
            it("1 - 2 - it") {
                println("1 - 2 - it")
            }
        }
        afterEach {
            println("1 - afterEach")
        }
        after {
            println("1 - after")
        }
    }
    describe("2 - describe") {
        before {
            println("2 - before")
        }
        beforeEach {
            println("2 - beforeEach")
        }
        context("2 - context") {
            it("2 - 1 - it") {
                println("2 - 1 - it")
            }
            it("2 - 2 - it") {
                println("2 - 2 - it")
            }
        }
        afterEach {
            println("2 - afterEach")
        }
        after {
            println("2 - after")
        }
    }
})
1 - before
1 - 1 - before
1 - beforeEach
1 - 1 - beforeEach
1 - 1 - it
1 - 1 - afterEach
1 - afterEach
1 - 1 - after
1 - beforeEach
1 - 2 - it
1 - afterEach
1 - after
2 - before
2 - beforeEach
2 - 1 - it
2 - afterEach
2 - beforeEach
2 - 2 - it
2 - afterEach
2 - after

記述例

@RunWith(JUnitPlatform::class)
class SpekSampleTest : Spek({
    val set = mutableListOf<String>()

    describe("adding an item") {
        beforeEachTest {
            set.add("item")
        }

        it("should contain item") {
            assertEquals("item", set[0])
        }

        it("should have a size > 0") {
            assertTrue(set.size > 0)
        }
    }
})

最後に

あとは実際に書く時に、describecontextなどにどんな記述で書くか、テストをスキップさせる場合はどうするかなどをチーム内でルール化しておくと良いと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした