play+Jacoco+Findbugs + Flyway on CircleCI

play java 2.2系アプリをCircleCIを使って、CI環境を構築した際のメモ。

下記を満たすように構築。

* ユニットテスト用のDBを自前で作成
* テスト用のapplication.confを指定
* カバレッジ測定
* コードの静的解析
* CircleCI上で見たいのでテスト結果などはなるべくhtmlで保存

手順はcircle.ymlに記述していく。

### 自前のDB、ユーザの構築

databaseの項目に、スキーマとユーザ作成を記述。

```lang:circl.yml

database:
  override: 
    - mysql -uroot -e 'CREATE DATABASE db_unittest;'
    - mysql -uroot -e 'CREATE USER app_user@localhost IDENTIFIED BY "app";' 

```

### flywayでmigration

DDLとコード値のマスタテーブルの初期データ投入までをflywayにまかせる。

```lang:project/plugins.sbt

resolvers += "Flyway" at "http://flywaydb.org/repo"

addSbtPlugin("org.flywaydb" % "flyway-sbt" % "3.2.1")
```

DBへの接続情報がちらばってしまうのが微妙ですが、固定のままでいくので割り切ってbuild.sbtに記述。sqlの置き場所をファイルシステムに変更。

```
seq(flywaySettings: _*)

flywayUrl := "jdbc:mysql://localhost/db"

flywayUser := "app_user"

flywayPassword := "app"

flywayLocations := Seq("filesystem:db/migration")

```

ユニットテスト用のurlはコマンドの引数で渡すかたちをとる。

```
play -Dflyway.url=jdbc:mysql://localhost/db_unittest flywayMigrate
```

### jacoco4sbtでテストとカバレッジ


テストとカバレッジの測定をjacocoで行う

```
jacoco:cover
```


#### jacoco4sbtの設定

```lang:project/plugins.sbt

addSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.6")
```

* parallelExecutionをoffにしないとテスト結果のxmlがひとつにまとめられてしまう
* フレームがつくるクラスファイルを除外
* テスト用の設定ファイルをSystem Propertyに設定することで指定

```lang:build.sbt

jacoco.settings

parallelExecution in jacoco.Config := false

jacoco.excludes in jacoco.Config := Seq(
   "controllers*",
   "*Routes*",
   "controllers*routes*",
   "views*html*",
   "controllers*javascript*",
   "controllers*ref*",
   )

testOptions in Test += Tests.Argument("-verbosity", "1")

testOptions in jacoco.Config += Tests.Setup( () => System.setProperty("config.file", "conf/application_test.conf") )
```

カバレッジの閾値を設定したい場合は、以下を追加
[how-to-fail-build-on-low-test-coverage-with-activator-sbt](http://stackoverflow.com/questions/26510218/how-to-fail-build-on-low-test-coverage-with-activator-sbt)

```
jacoco.thresholds in jacoco.Config := Thresholds(
  instruction = 50,
  method = 50,
  branch = 50,
  complexity = 50,
  line = 50,
  clazz = 50)
```

### findbugs4sbtでコード解析

バグの要因になりやすい箇所を指摘してくれる。標準はxmlのレポートが生成される。

```project/plugins.sbt

addSbtPlugin("de.johoop" % "findbugs4sbt" % "1.3.0")
```

* 不要クラスを除外
* レポートのファイル名を変更
* レポートタイプをhtmlに変更


```lang:build.sbt
findbugsSettings

findbugsExcludeFilters := Some(<FindBugsFilter>
    <Match>
       <Or>
       <Package name="controllers" />
       <Package name="views.html" />
       <Class name="routes" />
       <Class name="routes$javascript" />
       <Class name="routes$ref" />
       </Or>
    </Match>
</FindBugsFilter>)

findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html")

findbugsReportType := Some(ReportType.Html)
```

下記コマンドで、target/scala-2.10/findbugsにレポートが出力される。

```
play findbugs
```

### テストの成果物を保存

テスト後の後処理で、成果物の保存・加工を行う。

$CIRCLE_TEST_REPORTS/に、テスト結果のxmlをおくと、`Test Results`で成功、失敗の件数が表示される。

```lang:circle.yml

test:

 post: 
     - play findbugs
     - mkdir -p $CIRCLE_TEST_REPORTS/junit/
     - mkdir -p $CIRCLE_TEST_REPORTS/findbugs/
     - mkdir -p $CIRCLE_TEST_REPORTS/jacoco/
     - cp target/test-reports/* $CIRCLE_TEST_REPORTS/junit/
     - cp -r target/scala-2.10/jacoco/html/ $CIRCLE_TEST_REPORTS/jacoco/
     - cp target/scala-2.10/findbugs/* $CIRCLE_TEST_REPORTS/findbugs/

```


### junitの結果をmaven-surefire-report pluginでhtmlに変換

テスト項目と結果を見るのにxmlではつらいので、苦肉の策でmvnコマンドを使う。
（いけてないのでなんとかしたい）

#### mvnを動かすためだけのpom.xml

```
play makePom
```

で、もとになるpom.xmlファイルを作成。

securesocialが依存関係が解決できないので、その部分はコメントアウト。

```
 <!--
         <dependency>
            <groupId>securesocial</groupId>
            <artifactId>securesocial_2.10</artifactId>
            <version>2.1.2</version>
        </dependency>
 -->
```

レポートプラグインの追加

```lang:pom.xml
<reporting>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jxr-plugin</artifactId>
    <version>2.3</version>
  </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
        <version>2.18.1</version>
      </plugin>
      <plugin>
       <artifactId>maven-project-info-reports-plugin</artifactId>
       <configuration>
         <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
        </configuration>
      </plugin>
    </plugins>
  </reporting>
```



#### レポートのxmlファイルを移動

sure-fire-pluginで対象のxmlがあるディレクトリをうまく指定できなかったので、デフォルト設定のディレクトリに移す作戦をとる。（残念すぎる・・・）

```lang:circle.yml
 - mkdir -p target/surefire-reports

 - cp target/test-reports/* target/surefire-reports
```

あとは、`mvn site` を実行。site以下のsurefire-report.htmlから、テスト結果を見られる。

`Artifacts` から、保存したものをたどっていけます。

## まとめ

ようやく、テストとコード解析を伴ったCIでの開発環境が整った！
Redmineのチケットごとにブランチを切っているので、featureブランチにpushする度にテストとコード解析が走るので、安心してリファクタリングができる。カバレッジが高ければ、それだけ、デグレしにくいという目安にもなる。

課題は、findbugsやカバレッジの数値の推移がこれではわからないということ。CircleCI自体は、毎回使い切りの思想なので、別のサービスにデータを送るしかなさそう。