mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle2.6の新機能のうち二つを試してみた

JJUG LT大会、行きそびれました。

完全に夜型というか一日の活動時間が6時間くらいしかない僕が夜7時のイベントに参加するなど、到底無理でした(言い訳)

一応、夕方4時くらいには起きていたのですが、雨が降り出して、気分が落ち込んでしまったため、寝て起きたら8時過ぎていました。


JJUGのLTで@grimroseさんがgradle2.6についてLTしていたようです。

そして、LTの2時間後の11:00くらいにgradle2.6がリリースされました。

discuss.gradle.org


Gradle2.6の新機能

  • Playframeworkのサポート
  • Gradleプラグインの機能テストサポート
  • Rule base Model configurationのレポート改善
  • Tooling API のテストラウンチャー(よくわかってない)
  • gradle wrapperのSHA-256サポート

のようです。

Tooling APIはちょっと僕もよくわかってないので後回しで、Playframeworkもあれなので後回し(やるかどうかもあれ)で、ラッパーは独り身の僕にはまあ殆ど関係ないので放っておいて、残りの二つについて試してみました。

Rule base Model configurationのレポート改善

これ、gradle 2.4/2.5の時のmodelタスクの出力がすごい適当感溢れてて、設定された値だけしか表示されていなくて、もうなんかねっていう感じでした。どのような型の値を設定できるのか不明だったし、どのようなdslが書けるのかもわからなかったので、非常によい改善だと思います。

例えば、このようなモデルを考えます。

@Managed
interface Contents {
    String getLine();
    void setLine(String line);

    Integer getRepeat();
    void setRepeat(Integer repeat);
}

@Managed
interface Hello {
    String getDirName();
    void setDirName(String dirName);

    String getFileName();
    void setFileName(String fileName);

    ModelSet<Contents> getContents();
}

class HelloTestKit extends RuleSource {
    @Model
    static void hello(Hello hello) {
        hello.dirName = 'hello'
        hello.fileName = 'hello.txt'
    }
}

このようなモデルの場合のmodel DSLは次のようになります。

model {
    hello {
        dirName = 'test'
        fileName = 'test.txt'
        contents.create {
            line = 'Hello Gradle Test Kit'
            repeat = 3
        }
        contents.create {
            line = 'hello'
            repeat = 2
        }
    }
}

このときのmodelタスクの出力はこのようになります。

+ model
    + hello
          | Type:       Hello
          | Creator:    HelloTestKit#hello
          | Rules:
             ⤷ model.hello
        + contents
              | Type:       org.gradle.model.ModelSet<Contents>
              | Creator:    HelloTestKit#hello
            + 0
                  | Type:       Contents
                  | Creator:    model.hello > create()
                + line
                      | Type:       java.lang.String
                      | Value:      Hello Gradle Test Kit
                      | Creator:    model.hello > create()
                + repeat
                      | Type:       java.lang.Integer
                      | Value:      3
                      | Creator:    model.hello > create()
            + 1
                  | Type:       Contents
                  | Creator:    model.hello > create()
                + line
                      | Type:       java.lang.String
                      | Value:      hello
                      | Creator:    model.hello > create()
                + repeat
                      | Type:       java.lang.Integer
                      | Value:      2
                      | Creator:    model.hello > create()
        + dirName
              | Type:       java.lang.String
              | Value:      test
              | Creator:    HelloTestKit#hello
        + fileName
              | Type:       java.lang.String
              | Value:      test.txt
              | Creator:    HelloTestKit#hello

これ、バージョン2.5までだとこんな感じでした。

model
    hello
        contents
            0
                line : Hello Gradle Test Kit
                repeat : 3
            1
                line : hello
                repeat : 2
        dirName : test
        fileName : test.txt

設定できる型がわからないので、なんかもう残念ですね。しかし、今後はプロパティに何を設定することができるのか型情報がわかるので、よりユーザーフレンドリーになりますね。

Gradleプラグインの機能テストサポート

これはbuild.gradleをテスト時に読み込ませて、そのタスクを実行させたり、タスク実行の結果がSUCCESSなのかFAILUREなのか、SKIPPEDなのかをテストすることができる機能です。

具体的なコードについては僕がサンプルで書いたコードあるいはgradle本家のドキュメントを参照するとよいでしょう。

github.com

class BuildLogicFunctionalTest extends Specification {
    @Rule final TemporaryFolder testProjectDir = new TemporaryFolder()
    File buildFile

    def setup() {
        buildFile = testProjectDir.newFile('build.gradle')
    }

    def "hello world task prints hello world"() {
        given:
        buildFile << """
            task helloWorld {
                doLast {
                    println 'Hello world!'
                }
            }
        """

        when:
        def result = GradleRunner.create()
            .withProjectDir(testProjectDir.root)
            .withArguments('helloWorld')
            .build()

        then:
        result.standardOutput.contains('Hello world!')
        result.task(":helloWorld").outcome == SUCCESS
    }
}

The Gradle TestKitより抜粋


すごい機能なわけですが、残念だった所がひとつだけあります。

プラグインを作るプロジェクトで、これを試してみたのですが、作っている当のプラグインが読み込めないという残念なところがあります。

github.com

上のテストコードはプロダクション(プラグインの)コードで作ったプラグインを読み込むbuild.gradleを元にプロジェクトのタスクを走らせているのですが、残念なことにplugin idが解決できないというエラーが発生してテストがコケます。

buildSrcプロジェクトにプラグインを作るべきなのか、それとも一度publishする必要があるのかまでは確認できていませんが、これは非常に残念です。

後でgradle forumに質問を書こうと思います。


以上、他人の成果を横取りする出来の悪いおっさんのエントリーでした。

ああ、サンプルで書いたコードのレポジトリーはこれです。

github.com


amazon.co.jp