SQLServerだからといって諦めずに、CircleCIでテスト自動化する


## はじめに
昨年後半からデータベースに`SQLServer`を使っているプロジェクトに携わっています。
`TravisCI`や`CircleCI`などの代表的な`CI as a Service`は`MySql`や`PostgreSQL`はサポートしていますが、`SQLServer`はサポートしていません。

- [Setting up Databases - Travis CI](https://docs.travis-ci.com/user/database-setup/)
- [Ubuntu 12.04 (Precise) - CircleCI#databases](https://circleci.com/docs/build-image-precise/#databases)
- [Ubuntu 14.04 (Trusty) - CircleCI#databases](https://circleci.com/docs/build-image-trusty/#databases)

ここで諦めずに、CircleCIでテスト自動化する方法を探っていきます。

## `Microsoft SQL Server on Linux for Docker Engine.`を使う
はじめ、CIのコンテナに直接、`SQL Server on Linux`をインストールする方法を考えました。

- [Install SQL Server on Ubuntu - SQL Server vNext | Microsoft Docs](https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-ubuntu)
- [SQL Server on Linux を試してみた ｜ Developers.IO](http://dev.classmethod.jp/server-side/db/get-started-sql-server-on-linux/)

が、`CI as a Service`でよく使われている`Ubuntu`だと、`16.04 and 16.10`のみサポートしているとのことで、公式のDockerイメージを使うことにしました。

- [microsoft/mssql-server-linux - Docker Hub](https://hub.docker.com/r/microsoft/mssql-server-linux/)

### 使用上の注意事項
`mssql-server-linux`を使用するには、いくつか要件と制限事項があります。

- [Run the SQL Server Docker image on Linux, Mac, or Windows - SQL Server vNext | Microsoft Docs](https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-docker)

#### 要件
- Docker Engine 1.8 以上
  - `TravisCI`は、バージョンを明示していないので、はっきりしたことは言えませんが、`CircleCI`は、1.8以上をサポートしています
  - [Ubuntu 12.04 (Precise) - CircleCI#docker](https://circleci.com/docs/build-image-precise/#docker)  
  - [Ubuntu 14.04 (Trusty) - CircleCI#docker-engine](https://circleci.com/docs/build-image-trusty/#docker-engine)

- ディスク領域 ４GB使用
- メモリ 4GB 以上
- 下記の環境変数が必須
  - `ACCEPT_EULA=Y`
  - `SA_PASSWORD=<YourStrong!Passw0rd>`

#### 制限事項（2017年1月15日現在）
ボリュームのマッピングに対応してません。
したがって、データの永続化ができません。
CIでテスト自動化する分には問題ありませんが、ローカルの開発環境にはほぼ使えないかと思います。

## PHPで小さいアプリを作り、docker-composeで動かす
PHPでDBマイグレーションするだけの小さいアプリを作り、`mssql-server-linux`コンテナとリンクするようにしました。
`docker-compose.yml`は下記のとおりです。

```yml
# docker-compose.yml
mssql:
  build: ./docker/mssql
  env_file: ./docker/mssql/.env
  ports:
    - "1433:1433"
php:
  build: ./docker/php
  env_file: ./docker/php/.env
  links:
    - mssql
  volumes:
    - .:/data/
```

githubにレポジトリを公開してますので、詳細はそちらをご確認ください。

- [imunew/php-with-docker-mssql](https://github.com/imunew/php-with-docker-mssql)


## `CircleCI`で動かしてみる
`circle.yml`は、最終的に下記のようになりました。

```yml
# circle.yml
machine:
  timezone:
    Asia/Tokyo
  services:
    - docker

dependencies:
  override:
    - docker-compose up -d
    - docker-compose run php composer install

database:
  override:
    - docker-compose run php php app/bootstrap.php

test:
  override:
    - docker-compose run php vendor/bin/phpunit
```

### `docker-compose.yml` のフォーマットは、`Version 1`のみサポート
`CircleCI`において、`Version 2`は、現状、サポートされないので、`Version 1`で記述します。

- `Version 2`は、composer 1.6 以上、および、docker engine 1.10 以上が必要

- [Compose file reference - Docker](https://docs.docker.com/compose/compose-file/#/version-2)

### テスト
マイグレーションで投入した３件のレコードを取得して、件数があっているか確認するだけのテストを`PHPUnit`で実行します。

```php
<?php

class Example extends PHPUnit_Framework_TestCase
{
    /** @var PDO */
    private $pdo;

    public function setUp()
    {
        $container = require __DIR__. '/../app/container.php';
        $this->pdo = $container['db'];
    }

    /**
     * @test
     */
    public function findRecords()
    {
        $sql = <<<SQL
SELECT * FROM [user] WHERE [id] in (1, 2, 3);
SQL;

        $records = $this->pdo->query($sql)->fetchAll();

        $this->assertCount(3, $records);
    }

}
```

下記のように、OKが出れば成功です。

![ci.png](https://qiita-image-store.s3.amazonaws.com/0/26422/1eecbd12-d8b3-0dee-91bb-4a3e7e3434ad.png "ci.png")

## おわりに
とかく[プロプライエタリなソフトウェア](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%83%97%E3%83%A9%E3%82%A4%E3%82%A8%E3%82%BF%E3%83%AA%E3%83%BB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)な印象が強い`SQLServer`ですが、`Microsoft SQL Server on Linux`の登場によって、UNIXベースのエコシステムに乗っけやすくなってきました。

- [［速報］マイクロソフト「SQL Server on Linux」のパブリックプレビュー版をリリース。RHEL、Ubuntuに加えmacOS上のDocker環境などに対応。Connect();//2016 － Publickey](http://www.publickey1.jp/blog/16/sql_server_on_linuxrhelubuntumacosdockerconnect2016.html)

`Windows Azure`で`PHP`を動かす場合であっても`MySQL`が選ばれてきたケースが多いと思いますが、今後は`SQLServer`が積極的に選ばれるかもしれませんね。

ではでは。