kdnakt blog

hello there.

Kotlin/Nativeでビルド時にE2Eテストを実行する

Gradle何も分からないけど、何とか動くようになったのでまとめておく。

 

 

[シェルスクリプトでE2Eテスト]

先日、自作したHTTPサーバーのE2Eテストを実装した。

kdnakt.hatenablog.com

 

シェルスクリプトと、Python製のHTTPクライアントであるhttpieを組み合わせている。

httpie.io

 

しかし、テストを実行する際には、ターミナルからスクリプトを手動で呼び出す必要があった。

f:id:kidani_a:20201229154739p:plain

  

[build.gradle.ktsでE2Eテスト]

手動で毎回テストを実行するのは面倒なので、gradleのビルドコマンドを実行した場合に自動的にE2Eテストが実行されるようにしたい。

 

▼Gradleタスクを定義する

Gradleのドキュメントを読んだけれどシェルスクリプトを実行する方法がよくわからなかったのでGoogleで検索したところ、Stack Overflowでやり方を見つけた。

stackoverflow.com

 

以下のようにbuild.gradle.ktsファイルにタスクを定義する。

task("e2etest") {
    doLast {
        exec {
            executable("./run_test.sh")
        }
    }
}

 

しかし、gradle e2etestとコマンドを実行してみると以下のように失敗してしまった。

$ gradle e2etest
> Configure project :
Kotlin Multiplatform Projects are an Alpha feature. See: https://kotlinlang.org/docs/reference/evolution/components-stability.html. To hide this message, add 'kotlin.mpp.stability.nowarn=true' to the Gradle properties.

> Task :e2etest FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':e2etest'.
> A problem occurred starting process 'command './run_test.sh''

もしかして、と思い確認してみるとテストスクリプトのファイルにパーミッションが不足していた。

$ ls -l | grep run_test
-rw-r--r--  1 akito  staff   426 Dec 28 22:46 run_test.sh

 

以下のように実行権限を追加する。

$ chmod +x run_test.sh
$ ls -l | grep run_test
-rwxr-xr-x  1 akito  staff   426 Dec 28 22:46 run_test.sh

 

これでタスクが実行できるようになった。

$ gradle e2etest

> Configure project :
Kotlin Multiplatform Projects are an Alpha feature. See: https://kotlinlang.org/docs/reference/evolution/components-stability.html. To hide this message, add 'kotlin.mpp.stability.nowarn=true' to the Gradle properties.


> Task :e2etest
 ~ [INFO] TEST START
 ~ [INFO] started kttpd (PID: 29638)
 ~ [INFO] retrieve index.html
 ~ [INFO] http get index.html
  ~ [OK] request index.html get got response status code 200  
  ~ [OK] right index.html  
 ~ [INFO] post simple form
  ~ [OK] right response  
 ~ [INFO] stopped kttpd (PID: 29638)
  ~ [OK] TEST FINISHED  

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.7.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

  

▼ビルド時にE2Eテストを実行する

E2Eテストのタスクが定義できたので、ビルド時に自動的にこれを呼び出すようにしたい。

 

こちらのStack Overflowを見ると、dependsOnfinalizedByの2通りのやり方が紹介されていた。

stackoverflow.com

 

dependsOnを利用すると、あるタスクを実行する前に、依存関係にある別のタスクを必ず実行する、ということができるらしい。

実行順序だけ考えれば、今回「別のタスク」に該当するのはbuildタスクであるが、E2Eテストを実行する前に必ずビルドがしたいわけではない。ビルドを実行したあとで、必ずE2Eテストを実行したいのだ。

 

というわけでfinalizedByを採用し、build.gradle.ktsファイルに以下のように追記する。

tasks["build"].finalizedBy("e2etest")
tasks["nativeTestBinaries"].finalizedBy("e2etest")

 

1行目が、gradle buildコマンドでビルドを実行した場合にE2Eテストを自動で実行するための修正である。

 

2行目が、IntelliJでKotlin/Nativeプロジェクト全体をビルドした場合にE2Eテストを実行するための修正である。

IntelliJでKotlin/Nativeプロジェクトをビルドした場合、以下のGradleタスクが実行されていた。一番最後のネイティブテストを実行するタスクに続けて、E2Eテストを実行するようにしている。

> Task :compileKotlinNative
> Task :linkDebugExecutableNative
> Task :linkReleaseExecutableNative
> Task :compileKotlinMetadata NO-SOURCE
> Task :metadataMainClasses UP-TO-DATE
> Task :metadataJar UP-TO-DATE
> Task :assemble
> Task :nativeMainBinaries
> Task :nativeProcessResources NO-SOURCE
> Task :nativeMainKlibrary
> Task :compileTestKotlinNative
> Task :linkDebugTestNative
> Task :nativeTestBinaries

f:id:kidani_a:20201229165644p:plain

 

[まとめ]

  • シェルスクリプトをGradleタスクで実行できるようにした
  • gradle buildコマンド実行時に、Gradleタスクを自動実行できるようにした
  • 実装したコードは以下のリポジトリにまとめてある

github.com