D言語＋Travis-CIでテスト自動化する話②

# 概要
D言語でもTravis-CIやCircle-CIをはじめとする各種CIサービスでテスト・デプロイが可能です。
今回はTravis-CIを用いてテストを自動化するテンプレを紹介します。
[過去記事](https://qiita.com/mono_shoo/items/724a514b83f2c181d603)とは別の方法でテスト設定を記述します。
ちなみにビルドにはdubを使う前提です。

1. [D言語＋Travis-CIでテスト自動化する話➀](https://qiita.com/mono_shoo/items/724a514b83f2c181d603)
2. D言語＋Travis-CIでテスト自動化する話② ← この記事
3. [D言語＋Travis-CIでリリースのデプロイ自動化する話](https://qiita.com/mono_shoo/items/699cc8d48ee5ea86d5cb)
4. [D言語+Travis-CIでドキュメントのデプロイ自動化する話](https://qiita.com/mono_shoo/items/81a912b54c7be1d1e5f7)

# .travis.yml のテンプレ

```yml:.travis.yml
language: d

script: ./.travis.sh
sudo: false

jobs:
  include:
    # =============================== Test Stage ===============================
    - stage: test
      d: ldc
      os: linux
      env: TEST_TARGET_ARCH=x86_64
    - d: ldc-latest-ci
      os: linux
      env: TEST_TARGET_ARCH=x86_64
    - d: dmd
      os: linux
      env: TEST_TARGET_ARCH=x86_64
    - d: dmd-nightly
      os: linux
      env: TEST_TARGET_ARCH=x86_64
    - d: ldc
      os: linux
      env: TEST_TARGET_ARCH=x86
      addons:
        apt:
          packages:
            - gcc-multilib
    - d: dmd
      os: linux
      env: TEST_TARGET_ARCH=x86
      addons:
        apt:
          packages:
            - gcc-multilib
    - d: ldc
      os: osx
      env: TEST_TARGET_ARCH=x86_64
    - d: dmd
      os: osx
      env: TEST_TARGET_ARCH=x86_64
stages:
  - name: test
    if: type = pull_request or (type = push and branch = master)
```

### 解説
上記設定で以下の組み合わせでリポジトリのルートに `.travis.yml` を配置することで、以下のように初期設定が行われた状態で `.travis.sh` が呼び出されます。

| OS    | 環境変数　               | コンパイラ       | 備考 |
|:------|:------------------------|:----------------|:-----|
| Linux | TEST_TARGET_ARCH=x86_64 | ldc2(最新)      |      |
| Linux | TEST_TARGET_ARCH=x86_64 | ldc2(latest-ci) |      |
| Linux | TEST_TARGET_ARCH=x86_64 | dmd(最新)       |      |
| Linux | TEST_TARGET_ARCH=x86_64 | dmd(nightly)    |      |
| Linux | TEST_TARGET_ARCH=x86    | ldc2(最新)      |      |
| Linux | TEST_TARGET_ARCH=x86    | dmd(最新)       |      |
| OSX   | TEST_TARGET_ARCH=x86_64 | ldc2(最新)      |      |
| OSX   | TEST_TARGET_ARCH=x86_64 | dmd(最新)       |      |

ポイントは以下：

- `language: d`
- testステージにすべてのテストの条件を記載する。必要な箇所で必要なことをピンポイントで書けるので無駄がない(必要ないのにgcc-multilibに依存したりしない)
- `stage: test`がない要素は、直前のstage名が引き継がれる
- `d:` に `dmd-2.085.1` などのバージョンを指定できる(古いバージョンでもコンパイルできることを保証したい場合)
- OSXではx86向けにコンパイルできないので、前回はexcludeしていたけれど、今回は書かないだけでOK
- X86向けにクロスコンパイルするために `gcc-multilib` が必要
- `if: type = pull_request or (type = push and branch = master)` そのままの意。
- Linux, OSXではldc2とdmdの最新でコンパイルでき、かつ、念のため今後おかしくならないかの確認のためにnightly, latest-ciでもx86_64でテスト…で、計8つの条件。

# .travis.sh のテンプレ[^1]

```sh:.travis.sh
#!/bin/bash

set -eux -o pipefail

TEST_TARGET_ARCH=${TEST_TARGET_ARCH:-x86_64}

dub run -a=${TEST_TARGET_ARCH} -b=unittest-cov -c=default --compiler=${DMD}
```

[^1]: 前回記事と同じ

### 解説[^1]
ポイントは以下：

- **`.travis.sh` は、実行可能アトリビュートを与えてからgitでコミットする。**  
  `git update-index --add --chmod=+x .travis.sh`
- `set -eux -o pipefail` で一つテスト失敗したらそこで終了して、テスト失敗にする。
- 実行可能バイナリを実行するなら `dub run` で、main関数を実行しない場合や、ライブラリなら `dub test` でテストする。
- `-b=unittest-cov` でカバレッジをとれるようにする(Codecovなどと連携できる)
- `--compiler=${DMD}` は、現時点で、[コンパイラがldc2だと `-b=unittest-cov` を指定してもldc2に対して `-cov` フラグが付与されないバグがあるため。](https://github.com/dlang/dub/issues/1758)  
ldc2だとできないが、dmdと同じ引数でldc2を使えるようにしたldmd2だとうまくいく。  
ldcが有効な場合は`${DMD}`にはldmd2が、dmdが有効な場合には`${DMD}`にはdmdがセットされているので、これをうまく使う。
- `dub test` で実行する場合、デフォルト(一番最初に定義した)のコンフィギュレーションが使用されないようなので、 `-c=default` のように指定してやる
- 今回はテストが1つなので`.travis.yml`に直接`script: dub run ....`と記載することもできる、複数のコンフィギュレーション(`-c=default`の引数を変えて)テストする場合は `.travis.sh` など、スクリプト化するのが良い。

# Badgeを付ける
[![CI Status](https://travis-ci.com/shoo/gendoc.svg)](https://travis-ci.com/shoo/gendoc)
↑みたいなバッヂを付ける場合

```md:README.md
[![CI Status](https://travis-ci.com/shoo/gendoc.svg)](https://travis-ci.com/shoo/gendoc)
```

`http://travis-ci.com/`***`<GitHubアカウント名>`***`/`***`<リポジトリ名>`***`.svg` でSVG画像が得られますので、それをREADME.mdなどで画像表示させましょう。