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

# 概要
D言語でもTravis-CIやCircle-CIをはじめとする各種CIサービスでテスト・デプロイが可能です。
今回はTravis-CIを用いてテストを自動化するテンプレを紹介します。
ちなみにビルドにはdubを使う前提です。

1. D言語＋Travis-CIでテスト自動化する話➀ ← この記事
2. [D言語＋Travis-CIでテスト自動化する話②](https://qiita.com/mono_shoo/items/4c0017d6cffa53dfd743)
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

d:
  - dmd
  - dmd-nightly
  - ldc
  - ldc-beta

os:
  - linux
  - osx

env:
  - TEST_TARGET_ARCH=x86_64
  - TEST_TARGET_ARCH=x86

matrix:
  exclude:
  - d: ldc
    os: osx
    env: TEST_TARGET_ARCH=x86
  - d: ldc-beta
    os: osx
    env: TEST_TARGET_ARCH=x86

script: ./.travis.sh

sudo: false

addons:
  apt:
    packages:
      - gcc-multilib

stages:
  - name: test
    if: type = pull_request or (type = push and branch = master)
```

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

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

ポイントは以下：

- `language: d`
- `d:` に `dmd-2.085.1` などのバージョンを指定できる(古いバージョンでもコンパイルできることを保証したい場合)
- OSXではx86向けにコンパイルできない
- X86向けにクロスコンパイルするために `gcc-multilib` が必要
- `if: type = pull_request or (type = push and branch = master)` そのままの意。
- これだけでプルリクエストとマスターブランチへのコミットするたびに14本テストが走るので、多すぎると思うなら、不要そうな条件を抜いたり`exclude`に指定したりする。

[^1]: OSXではx86向けにコンパイルできない

# .travis.sh のテンプレ

```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}
```

### 解説
ポイントは以下：

- **`.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などで画像表示させましょう。