Geb のレポート出力で日本語ファイル名をエスケープさせないようにする

前回のエントリー「Geb はじめました - Java開発のんびり日記」の続きです。

Geb を使って感動したものの、レポート出力されたファイルが残念なことになっていました。ということで、なんとかがんばってみました。

日本語が入ったテストケースをレポート出力すると…

package geb.sample

import geb.spock.GebReportingSpec

class GoogleGeb extends GebReportingSpec {

    def "Google ホームページに遷移する"() {
        given:
        to GoogleHomePage

        expect:
        at GoogleHomePage
    }
}

このテストケースを実行すると、reportsDir で指定したディレクトリに次のようなファイルがレポートとして出力されます。

001-001-Google ___________-homepage.html
001-001-Google ___________-homepage.png
002-002-Google ___________-end.html
002-002-Google ___________-end.html

テストケースのメソッド名がファイル名に使用されるのですが、みごとに日本語部分が置換されています。メソッド名をすべて英数字で書けばいいのですが、それだと可読性がものすごく下がるのでなんとかしたいです。

Geb のソースコードを追いかけてみる

まず、今回の流れで登場するクラスたちです。

すべて見たわけではないので、解釈間違っているかもしれませんが…

  • ScreenshotAndPageSourceReporter でファイルをレポート出力している
  • そのスーパークラスの ReporterSupport の escapeFileName メソッドでファイル名をエスケープ変換している
  • ScreenshotAndPageSourceReporter をescapeFileName メソッドをオーバーライドすればなんとかなる

  • どの Reporter が呼び出されるかは、Configuration で決める
  • Configuration は Geb 設定ファイルである、GebConfig.groovy の設定を読み込んでいる
  • GebConfig.groovy で Reporter の呼び出し先をオーバーライドした Reporter クラスに変更する

という感じでいけるのではないかということで、やってみたらうまくいきました。

主要なクラスを見てみる

レポートを出力する ScreenshotAndPageSourceReporter のスーパークラスの ReporterSupport クラスでは、escapeFileName メソッドが実装されています。
このメソッドの中でファイル名をエスケープ変換しています。おそらく、ファイル名に使えない文字を「_」に変換したいのだと思います。
ですが、この正規表現の指定では日本語が変換されてしまいます。この正規表現を変えるとよさそうです。

package geb.report

abstract class ReporterSupport implements Reporter {

    protected escapeFileName(String name) {
        name.replaceAll("[^\\w\\s-]", "_")
    }
}

Configuration クラスでは、reporter という変数値(オブジェクト)を取得しています。
その取得元は GebConfig.groovy です。
reporter が設定されていなければ、ScreenshotAndPageSourceReporter クラスが使用されます。
ScreenshotAndPageSourceReporter がそのまま呼ばれると、escapeFileName メソッドで日本語ファイル名が変換されてしまうので、ここを置き換える(つまり reporter に自作オブジェクトを設定する)必要があります。

package geb

class Configuration {

    Reporter getReporter() {
        def reporter = readValue("reporter", null)
        if (reporter == null) {
            reporter = new ScreenshotAndPageSourceReporter()
            setReporter(reporter)
        }
        reporter
    }
}

ということで、GebConfig.groovy に以下の記述を追加します。
ScreenshotAndPageSourceReporter の escapeFileName メソッドをオーバーライドしたオブジェクトを reporter に代入します。
日本語をエスケープしないように、かつファイル名として不正な記号をエスケープするように正規表現を工夫しています。

reporter = new ScreenshotAndPageSourceReporter() {
    @Override
    protected escapeFileName(String name) {
        // name.replaceAll("[^\\w\\s-]", "_") 
        name.replaceAll('[\\\\/:\\*?\\"<>\\|]', '_')
    }
}

正規表現、苦手なのであっているか不安です。間違っていたらご指摘ください。

長くなりましたが…

上記のように GebConfig.groovy を設定すると、レポート出力は次のようになります。

001-001-Google ホームページに遷移する-homepage.html
001-001-Google ホームページに遷移する-homepage.png
002-002-Google ホームページに遷移する-end.html
002-002-Google ホームページに遷移する-end.html

おまけ

今回、Geb のソースをかなり追いかけましたが、Groovy らしいコーディングがたくさんあって勉強になりました。
methodMissing, propertyMissing のオーバーライドとか使えるとかっこいいなと。