テストフレームワークのSpekを使えるようにする

最初に

Kotlinで書かれているテストフレームワークSpekをAndroidのテストでも使えるかどうかという検証を行いました。

結論

結論としては、普通に使おうとするとRobolectricなどと併用することができないため、今のところ使うのは辛い感じです。

Spekとは

JetBrains社が開発しているKotlinでテストが記述できるようになるテスティングフレームワークです。1
これを導入すると、初期化, テスト対象の処理実行, アサーションと改行などで区切っていた部分をDSLで区分けして記述できるようになります。

@Test
public void testCalculateTaxRate() {
  TaxRateCalculator calculator = new TaxRateCalculator();

  Int value = calculator.calculateRate(200, 10);

  assertEquals(300,value);
}
class SimpleTest : Spek({
  describe("a calculator") {
    val calculator = SampleCalculator()

    it("should return the result of adding the first number to the second number") {
      val sum = calculator.sum(2, 4)
      assertEquals(6, sum)
    }

    it("should return the result of subtracting the second number from the first number") {
      val subtract = calculator.subtract(4, 2)
      assertEquals(2, subtract)
    }
  }
})

導入

使えるようんいするまでのGradleでの設定方法について記述していきます。
Kotlinの導入は終わっているものとします。

Gradleの設定

SpekはJUnit5をベースとしたフレームワークであるのでJUnit4で動かすには違う設定が必要です。2

公式HPには記載されていなかったのですが、下記で試しているバージョンでは、kotlin-test-junitが必要でした

KOTLIN_VERSION=1.1.3

SPEK_VERSION=1.1.2

JUNIT_PLATFORM_VERSION=1.0.0-M4

repositories {
  maven { url "http://dl.bintray.com/jetbrains/spek" }
}

dependencies {
  testCompile ("org.jetbrains.spek:spek-api:${SPEK_VERSION}") {
    exclude group: 'org.jetbrains.kotlin'
  }
  testCompile ("org.jetbrains.spek:spek-junit-platform-engine:${SPEK_VERSION}") {
    exclude group: 'org.junit.platform'
    exclude group: 'org.jetbrains.kotlin'
  }
  testCompile "org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION"
  testCompile "org.junit.platform:junit-platform-launcher:${JUNIT_PLATFORM_VERSION}"
  testCompile "org.junit.platform:junit-platform-runner:${JUNIT_PLATFORM_VERSION}"
}

テストコードの記述

JUnit4でSpekのテストを実行するためには、@RunWith(JUnitPlatform::class)のアノテーションが必要です。

そのために、TestRunnerを指定するようなテストライブラリは使えなくなります。
例えば、RobolectricTestRunnerを指定する必要があるRobolectricです。

@RunWith(JUnitPlatform::class)
object SampleCalculatorTest : Spek({
  given("a caluculator") {
    val caluculator = SampleCalculator()
    on("addition") {
      val result = calculator.add(2, 4);
      it("should return 6") {
        assertEquals(6, result)
      }
    }
    on("substraction") {
      val sum = calculator.substract(2, 4);
      it("should return -2") {
        assertEquals(-2, result)
      }
    }
  }
})

用意されているブロック

  • given
    • テストの内容を説明します。givenを使うときは、onと同時に使い、onで処理の細かい条件等を説明しテストを実行する形が良さそうです。
  • on
    • 実行する処理を説明します。テスト対象のメソッド単位に用意するのが良さそうです。
  • it
    • 実行する(した)処理の期待する振る舞いなどを説明します。データのバリエーションを用意して複数の確認を行う場合はそれぞれにitを定義するのが良さそうです。
  • describe
    • テストの内容を説明します。また、複数のdescribeを並べて複数のテストを行えます。

まとめ

現時点では公式でRobolectricとの併用などをサポートしていないようなので使うことは難しそうですが、使えるようになるとテストコードがより読みやすくかけるようになりそうです。
次回までにCustomTestRunnerを用意できたらと思っています。


  1. https://github.com/JetBrains/spek 
  2. http://spekframework.org/docs/latest/#setting-up-legacy