Introduction
タイトルの通り、IntellijIDEA上でKotlinのGradleを使ったプロジェクトを作成し、Spekでテストをさせようとしたときに環境構築で少し苦労したのでまとめておきます。
なお、使用したバージョンは以下の通りです。
種類 | 名前 | バージョン |
---|---|---|
OS | Ubuntu | 18.04(Bionic Beaver) |
開発環境 | Intellij IDEA | ULTIMATE 2018.1 |
開発言語 | Kotlin | 1.2.50 |
JVM | OpenJDK | 10.0.1 |
ビルド | Gradle | 4.8 |
テスト環境1 | JUnit | 5.2 |
テスト環境2 | Spek | 1.1.5 |
環境構築
OS
Ubuntuのインストールです。本題では無いのでささっと書きます。
- Ubuntu18.04 DesktopのISOイメージを使ってインストール(なお、私はVirtualBoxを使っています)
- ネットワークのProxyと/etc/environmentにproxyを設定 (もちろんProxy下にある人のみ)
$ sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade
$ sudo apt-get install build-essential
- VirtualBox Guest Additionをインストール(再起動)
-
$ sudo apt-get install language-pack-gnome-ja language-pack-ja gnome-user-docs-ja gnome-getting-started-docs-ja fonts-noto-cjk-extra firefox-locale-ja
(日本語パックのインストール) - 地域と言語設定より、入力ソースを日本語(Mozc)を優先に変更
JVM
OpenJDKをインストール。なお、執筆時点ではJDK11と言ってもJDK10がインストールされます。
$ sudo apt-get install openjdk-11-jdk-headless
Intellij IDEA
開発環境にはIntellij IDEAを使っています。Ubuntuを使っているので、折角ですからsnapを使ってインストールします。
-
$ sudo snap install --classic intellij-idea-ultimate
(EAP版を使いたい人は--edgeオプション付きで) -
$ intellij-idea-ultimate
で起動後、お気に入りに設定 - 設定のApperance&Behaviour -> System Settings -> HTTP ProxyでProxyを設定 (もちろん、Proxyを使う人だけ)
なお、snapを使ってインストールすると、mavenリポジトリからjarファイルを取得しようとしたときに、エラーが出てしまうようです。
the trustAnchors parameter must be non-empty gradle
他、スタックトレースがいっぱい
そこで、IntellijIDEAのVMOptionsを上書きします。
$ vi ~/.idea64.vmoptions
-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Dawt.useSystemAAFontSettings=lcd
-Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine
-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts
-Djavax.net.ssl.trustStorePassword=changeit
なお、下の二行以外は、デフォルトのvmoptionsです。
そして、IntellijIDEA起動時に、このファイルを読み込むように環境変数をセットします。
$ vi ~/.bashrc
export IDEA_VM_OPTIONS=~/.idea64.vmoptions
なお、環境変数をセットするのではなく、以下のファイルに設定を書くという方法もあります。
$ vi ~/.IntelliJIdea2018.1/config/idea64.vmoptions
Kotlin
Kotlinもsnapを使ってインストールします。
$ sudo snap install --classic kotlin
-
$ kotlin -version
(バージョン確認)
Kotlin version 1.2.50-release-103 (JRE 10.0.1+10-Ubuntu-3ubuntu1)
また、Intellij IDEAのKotlinプラグインも更新しておきます。
- Setting → Plugins → Kotlinを検索して必要であればUpdate
Gradle
Intellij IDEAに標準で入っているGradleは、この時点では4.4です。このバージョンでは、Java9以降のバージョン番号が正しく取得できないという不具合があります。折角ですので、最新版のGradleをインストールしてみます。
$ wget https://services.gradle.org/distributions/gradle-4.8-bin.zip
$ sudo mkdir /opt/gradle
$ sudo unzip -d /opt/gradle gradle-4.8-bin.zip
インストールしたgradleへのパスを通します。
$ vi ~/.bashrc
export PATH=$PATH:/opt/gradle/gradle-4.8/bin
また、Java9よりprivateメソッドへのReflectionの振る舞いが変わったことから、gradle実行時にgroovyの警告メッセージが出力されてしまいます。
$ gradle -v
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/opt/gradle/gradle-4.8/lib/groovy-all-2.4.12.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
------------------------------------------------------------
Gradle 4.8
------------------------------------------------------------
Build time: 2018-06-04 10:39:58 UTC
Revision: 9e1261240e412cbf61a5e3a5ab734f232b2f887d
Groovy: 2.4.12
Ant: Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM: 10.0.1 (Oracle Corporation 10.0.1+10-Ubuntu-3ubuntu1)
OS: Linux 4.15.0-23-generic amd64
これを防ぐために、gradle起動時のオプションを環境設定に指定してします。
$ vi ~/.bashrc
export GRADLE_OPTS="--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED"
これで警告が出なくなりました。
$ gradle -v
------------------------------------------------------------
Gradle 4.8
------------------------------------------------------------
Build time: 2018-06-04 10:39:58 UTC
Revision: 9e1261240e412cbf61a5e3a5ab734f232b2f887d
Groovy: 2.4.12
Ant: Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM: 10.0.1 (Oracle Corporation 10.0.1+10-Ubuntu-3ubuntu1)
OS: Linux 4.15.0-23-generic amd64
プロジェクト作成
Create New Project
Intellij IDEAでgradleプロジェクトを作成します。
なお、これ以降、プロジェクト名はhogehogeを使用します。
- Create New Project → Gradle → Kotlin (Java) → Next
- GroupIdとArtifactIdを入力 → Next
- Use auto-importは環境と好みに合わせてON/OFF
- Use local gradle distributionを選択し、Gradle homeに
/opt/gradle/gradle-4.8
を指定する → Next - Project nameとlocationを入力 → Finish
gradle.properties
IntelliJ IDEAのリポジトリ読み込みでもセキュリティに関するvm optionsを追加しましたが、Gradleで使用するvmにも同じオプションを追加する必要があります。
そこで、プロジェクトディレクトリ直下に、gradle.properties
ファイルを作成して、vm optionsを記載します。
$ vi ~/IdeaProjects/hogehoge/gradle.properties
org.gradle.jvmargs=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts -Djavax.net.ssl.trustStorePassword=changeit
なお、ビルド時にdaemonを使わない場合は、ここに-Dorg.gradle.daemon=falseを追加します。
また、Proxy使用時は、-DproxyHost=PROXY.HOST -DpropxyPort=PROXY.PORTを追加します。
settings.gradle
最新版のkotlin-gradle-pluginを取得するために、ビルド用のリポジトリにkotlin-devを追加します。
なお、pluginManagementはsettings.gradleの先頭に記述します。
$ vi ~/IdeaProjects/hogehoge/settings.gradle
pluginManagement {
repositories {
mavenCentral()
maven {
url { 'http://dl.bintray.com/kotlin/kotlin-dev' }
}
}
}
rootProject.name = 'hogehoge'
ソースディレクトリ
今回は、mainとtestの二つのソースディレクトリを使用することにします(もちろんコマンドではなくUIから作成しても可)。
$ mkdir -p ~/IdeaProjects/hogehoge/src/main/kotlin
$ mkdir -p ~/IdeaProjects/hogehoge/src/test/kotlin
これらをIntellij IDEAのMark Directory as
をソースディレクトリなどに指定しても、build.gradleの内容で上書きさせてしまうので注意が必要です。
build.gradle
初期状態のbuild.gradleは以下の通りになっています。
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.50'
}
group 'hogehoge'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
これに、ソースディレクトリの設定と、Gradle4.7以降deprecatedになったcompileコマンドの変更を行います。
また、ついでにkotlin-stdlib-jdk8のバージョン指定も行いました。
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.50'
}
group 'hogehoge'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.50"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
ひとまずプロジェクト作成用の準備完了です。
ビルド
サンプルソース
今回は、メインのソースディレクトリ下にpackage hoge.hogehogeを作成し、パッケージ下にHello.ktというソースを作成することにします。
src
|-- main
|-- kotlin
|-- hoge.hogehoge
| Hello.kt
package hoge.hogehoge
data class Hello(val who: String) {
override fun toString():String = "Hello, $who!"
}
Gradleビルド
IntelliJ IDEAで、Gradle用ビルドコマンドを追加します。
- Runメニュー → Edit Configurations...
- Add New Configuration(+ボタン)で、Gradleを選択
- Gradle projectに対象となるプロジェクト(hogehoge)を選択します
- Tasksにbuildを入力します
これで、メニュー等からGradleビルドを行うことができるようになります。
テスト(JUnit)
まず、JUnit5の設定を行います。
テストソース
以下の箇所にJUnit5用のテストソースを作成します。
src
|-- test
|-- kotlin
|-- hoge.hogehoge
| HelloTest.kt
package hoge.hogehoge
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class HelloTest {
@Test fun helloWorld() {
val hw = Hello("World")
Assertions.assertEquals(hw.toString(), "Hello, World?") // わざと失敗
}
}
build.gradle
続いて、JUnit用にbuild.gradleを修正します。
dependenciesにJUnit用のライブラリを追加したのと、testブロックを追加しました。
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.50'
}
group 'test8'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.50"
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5:1.2.50'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.2.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
test {
useJUnitPlatform()
}
Gradleテストビルド
IntelliJ IDEAで、Gradle用テストビルドコマンドを追加します。
上記でbuildコマンドを作成したのとほぼ同じで、違いはタスクがbuildからtestになっただけです。
- Runメニュー → Edit Configurations...
- Add New Configuration(+ボタン)で、Gradleを選択
- Gradle projectに対象となるプロジェクト(hogehoge)を選択します
- Tasksにtestを入力します
テスト(Spek)
続いて、テスト用にSpekの設定を行います。
テストソース
以下の箇所にSpek用のテストソースを作成します。
src
|-- test
|-- kotlin
|-- hoge.hogehoge
| HelloSpec.kt
package hoge.hogehoge
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.describe
import org.jetbrains.spek.api.dsl.it
import org.jetbrains.spek.api.dsl.on
import org.junit.jupiter.api.Assertions
object HelloSpec : Spek({
describe("Hello, World!") {
val hw = Hello("World")
on("world") {
it("World is hello") {
Assertions.assertEquals(hw.toString(), "Hello, World?") // わざとERROR
}
}
}
})
build.gradle
続いて、Spek用にbuild.gradleを修正します。
dependenciesにSpek用のライブラリを追加したのと、そのリポジトリを追加しました。
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.50'
}
group 'test8'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven {
url {
'http://dl.bintray.com/jetbrains/spek'
}
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.50"
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5:1.2.50'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.2.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'org.jetbrains.spek:spek-api:1.1.5'
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.2.50'
testRuntimeOnly 'org.jetbrains.spek:spek-junit-platform-engine:1.1.5'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
test {
useJUnitPlatform()
}
Gradleテストビルド
テスト実行は、先ほどJUnit用に作成したものをそのまま使用できます。
これでようやく
スタートラインだな。。。
変更点
2018/7/3
- 各build.gradleからsourceSetsの設定を削除しました(指定してあったパスsrc/main/kotlinは標準なので明示的に指定する必要が無いため)
- 各build.gradleのruntimeOnly 'org.jetbrains.kotlin:kotlin-reflect:1.2.50'を、implementation ~に変更しました (ビルド時に警告がでるため)
- gradle.propertiesに-Dorg.gradle.daemonと-DproxyHost(Port)の説明を追加