Laravel5.7: TravisCIでテストしてCodecovでカバレッジを取得する


LaravelアプリをGitHubへプッシュしたら、同時にテストとカバレッジ取得を行うようにします。
そして、下記のようなバッジをREADME.mdで表示させます。

親記事

Laravel 5.7で基本的なCRUDを作る - Qiita

準備

プッシュする前に、TravisCIとCodecovにGitHubアカウントでログインして、リポジトリを有効にしておいてください。
いっつも忘れちゃうんですよね…。

テスト用の環境設定

Qiita: TravisClでLaravel5.2のテストを自動化してみる

下記の内容の.env.travisを作成します。
.env.travis

ファイル名を.env.testingにしてしまうと、ローカルのtesting環境でも適用されてしまいます。
なので、.env.travisとしたほうがいいです。

DBはローカルではMySQLを、本番のHerokuではPostgreSQLを使っています。
TravisCIではPostgreSQLでDBを作ってテストすることにします。

APP_URLhttp://localhost:8000とは、php artisan serveで起動するPHPの組込み開発サーバへのURLです。
CIでのブラウザテストではこれが必要です。
readouble.com: ローカル開発サーバ
:link: PHP公式ドキュメント: ビルトインウェブサーバー

ちなみに、ホスト名とポート番号の初期値は下記の箇所で設定されています。

src/Illuminate/Foundation/Console/ServeCommand.php

    protected function serverCommand()
    {
        // PHPのビルトインウェブサーバーをそのまま利用するコマンドを生成している。
        // 「php -S localhost:8000」のような形式。
        return sprintf('%s -S %s:%s %s',
            ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)),
            $this->host(),
            $this->port(),
            ProcessUtils::escapeArgument(base_path('server.php'))
        );
    }

// (中略)

    protected function getOptions()
    {
        // ホストは「127.0.0.1」、ポートは「8000」が初期値。
        return [
            ['host', null, InputOption::VALUE_OPTIONAL, 'The host address to serve the application on', '127.0.0.1'],
            ['port', null, InputOption::VALUE_OPTIONAL, 'The port to serve the application on', 8000],
        ];
    }

なお、PHPのビルトインウェブサーバーはSSLには対応していないようです。
Stack Overflow: openSSL not working with PHP built-in webserver

TravisCIの設定

Travis CIの公式ドキュメント: PostgreSQL
readouble.com: Travis CI

下記の内容の.travis.ymlを作成します。
.travis.yml

travis_retryの意味

タイムアウトが原因で依存パッケージのインストールに失敗しても、3回までリトライしてくれます。
Travis CIの公式ドキュメント: Timeouts installing dependencies

コマンドの末尾の&の意味

バックグラウンドでプログラムを実行する(&アンド)
末尾に&をつけると並列で処理します。

bash <(curl -s https://codecov.io/bash) -cF phpの意味

Codecovで、PHPとJavaScriptなど複数の言語のカバレッジをひとつにまとめるためのコマンドです。
下記の例をそのまま真似しました。
Codecov公式サンプル: .travis.yml
:link: Codecov公式ドキュメント: Multiple Languages

https://codecov.io/bash の中身はシェルスクリプトで、それをcURLのサイレントモード(curl -s)でダウンロードしています。
Linuxコマンド集 - 【curl】ファイルのダウンロードやアップロードを行う:ITpro

そして、ダウンロードしたスクリプトを入力リダイレクト(<)でbashとして実行しています。
Linuxコマンド集 - 【 < 】 入力のリダイレクト:ITpro

その際、オプションとして-cF phpを渡しています。
https://codecov.io/bash を見ると下記のように説明されています。

    -c           Move discovered coverage reports to the trash
    -F flag      Flag the upload to group coverage metrics

                 -F unittests        This upload is only unittests
                 -F integration      This upload is only integration tests
                 -F ui,chrome        This upload is Chrome - UI tests

要するに、「これから送るカバレッジに"php"のフラグを付けるので、そちらでグループに分けて管理してください」ということのようです。
これで、PHPとJavaScriptなど複数のカバレッジの結果を同時に送ることができ、しかもそれらを総合してひとつのスコアとして表示してくれます。

Laravel側の設定

Travis CI用に、Laravel側で追加で設定しなければならないことがあります。

DuskServiceProviderを登録する

app/Providers/AppServiceProvider.php
+use Laravel\Dusk\DuskServiceProvider;

 class AppServiceProvider extends ServiceProvider
 {
     function register()
     {
+        // 本番環境以外で、Duskサービスプロバイダを登録する
+        if ($this->app->environment('local', 'testing')) {
+            $this->app->register(DuskServiceProvider::class);
+        }
     }

5.7の公式ドキュメントには、登録は自動で行われると書いてあります。

Duskをインストールしたら、Laravel\Dusk\DuskServiceProviderサービスプロバイダを登録する必要があります。通常、Laravelの自動サービスプロバイダ登録により、自動的に行われます。

しかし、上の記述なしでTravis CIでテストを実行すると「duskというコマンドは存在しない」と警告されます。
よって、上のように手動による登録が必要です。

TravisCIのログ
$ php artisan dusk
chrome: command not found

  Command "dusk" is not defined.  

Laravel development server started: <http://127.0.0.1:8000>
The command "php artisan dusk" exited with 1.

ちなみに、上のコードは5.4の公式ドキュメントに記載されていたものです。

Duskをdiscoverの対象から外す

composer.json
     "extra": {
         "laravel": {
             "dont-discover": [
+                "laravel/dusk"
             ]
         }
     },

上の記述を追加しないと、Travis CIでのテストの準備段階でパッケージをインストールする際にエラーとなってしまいます。

TravisCIのログ
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
In DuskServiceProvider.php line 43:

  It is unsafe to run Dusk in production.  

Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1
The command "composer install --no-interaction --prefer-dist --no-suggest" failed. Retrying, 3 of 3.

Laracastの質問と回答

README.mdにバッジを載せる

Travis CIでテストする前に、あらかじめバッジを設置しておきます。
すでに存在するreadme.me(小文字)を削除して、このプロジェクト用のREADME.meを下記の内容で作ります。
.env.travis

大事なのは、冒頭でバッジを表示する箇所です。
markdown
[![Build Status](https://travis-ci.org/sutara79/demo-laravel-crud.svg?branch=5.7)](https://travis-ci.org/sutara79/demo-laravel-crud)
[![codecov](https://codecov.io/gh/sutara79/demo-laravel-crud/branch/5.7/graph/badge.svg)](https://codecov.io/gh/sutara79/demo-laravel-crud)

ユーザー名、リポジトリ名、ブランチ名を皆さんの環境に合わせて修正してください。

Travis CIのバッジの取得方法

Codecovの場合

プッシュする

以上の準備を終えたら、GitHubへプッシュします。
自動でTravis CIでテストが始まり、それが成功したらCodecovでカバレッジを取得します。
エラーがあった場合などにはメールで通知が来ます。