ほげほげ見聞録

技術メモ、備忘録、使い方はそのうち覚える

PHPUnitをJenkinsから実行するメモ


Jenkinsのジョブを実行してPHPUnitを実行する設定のメモ。
更に、テスト実行のジョブを下流ジョブに設定してメールの送信も試す。

例によってフレームワークFuelPHP
デプロイ前にテストを実行出来たら良いのだろうけど、Jenkinsのあるサーバの環境をいじれなかったので流れは以下。

  • developの内容をテスト環境にデプロイ
  • テスト環境上でPHPUnitを実行

そもそもテスト環境でPHPUnitを実行できるか

SSH使ってテストサイトで「php oil test --testsuite=app」を実行。
エラー発生。
「fuel/vendor/bin/phpunit: 許可がありません」

以下のファイルに権限の設定をする必要がある。
chmod 755なら問題ないだろう。


再度実行すると、oilパッケージ内で以下エラー。
「Tests Running...This may take a few moments.: そのようなファイルやディレクトリはありません」

エラーが出ているのはoilパッケージ内のpassthru()で実行しているコマンド。
「fuel/vendor/bin/phpunit -c "fuel/app/phpunit.xml"」

statで確認したが、二つとも存在。どちらもアクセス権は問題ないようだ。
実際に問題だったのは以下のファイル。

これらを色々いじっていたら、上書きした時に「php oil test」できることが判明する。
はて面妖なと考えていると、再び「そのようなファイルやディレクトリはありません」エラーが発生。
どうやらJenkinsが動いたので、ファイルを上書きされたらしい。

アップロードする方法によってテスト実行できるか試す。

  • FTPでアップロード:テスト実行可能
  • Jenkinsでアップロード:エラー発生

FTPでアップロードとJenkinsでアップロードしたファイルの違い

FTPでアップロード

$ stat fuel/vendor/bin/phpunit
  Size: 603             Blocks: 8          IO Block: 4096   通常ファイル


Jenkinsでアップロード

$ stat fuel/vendor/bin/phpunit
  Size: 620             Blocks: 8          IO Block: 4096   通常ファイル

なんかファイルサイズ増えてるんですけど……。
この現象はもう一つのファイル「fuel/vendor/phpunit/phpunit/phpunit」でも発生していた。

アップロード方法によらず、ファイルの文字列は同じ。
ということは、改行コードの問題だろうと分かる。

ちなみに、Backlogのリポジトリから取得したファイルはFTPでアップロードしたものと同サイズ。
つまり、Jenkinsでデプロイする際に一度ワークスペースにファイルを落としてきているのが原因ではないか。
実際に確認すると、ワークスペースのファイルの改行コードはCR+LF、リポジトリはLF。CR+LF→LFに変換するとリポジトリと同サイズになる。

どうやら、Gitの改行コード変換の問題らしい。
Git - Git の設定

Jenkinsのサーバで以下のコマンドを実行。

git config --global core.autoCRLF false


再度デプロイした後にPHPUnitを実行すると、無事に実行できた。

JenkinsジョブからPHPUnitを実行

ファイルのアップロードは済んでいる状態。
別ホストのテスト環境にログインするには「SSH Plugin」使うと楽。

認証情報の追加は、システムの設定 > SSHリモートホスト > 追加。
テスト接続で「Successfull connection」が出れば良し。

ジョブの設定で、ビルド > リモートホストでシェルを実行を追加。
SHリモートホストに追加したサイトを選択。

cd 【oilパス】
php oil test --testsuite=app

ビルド実行してログに「[SSH] exit-status: 0」出力されていれば成功。

パイプラインから下流プロジェクト実行

外部から呼び出すのはパイプラインのジョブなので、これにPHPUnitを実行するジョブを組み込む。
デプロイが成功していればテストを実行するという流れ。

ビルドの成功チェックは以下で可能。

def jobBuild = build job
def result = jobBuild.getResult()

if (result == "SUCCESS") {
}

Google グループ

パイプラインだとエラー時の動作設定がないのでscript中に追記。
Cleaning up and notifications

Scripted Pipeline(nodeで囲む)でなくDeclarative Pipeline(pipelineで囲む)使うと、エラー時の動作などかけるので便利。
Pipeline Syntax
Pipeline Syntax

Declarative PipelineでJenkinsfileを書いてみた(Checkstyle,Findbugs,PMD,CPDとか) - Qiita

というわけでスクリプトの流れ。

def jobResult

pipeline {
    agent any

    stages {
        stage('deproy') {
            steps {
                script {
                    // デプロイ
                    build Deploy
                }
            }
        }
        stage('PHPUnit') {
            steps {
                script {
                    // テスト実行
                    build Test
                    // テスト結果をメール
                    def consoleURL = "${env.JENKINS_URL}/job/【ジョブ名】/${env.BUILD_NUMBER}/consoleText"
                    def data = new URL(consoleURL).getText()
                    mail to: '【アドレス】',
                         subject: 'test',
                         body: data
                }
            }
        }
    }

    post {
        failure {
            script {
                //エラーメール送信
            }
        }
    }
}



変数

pipelineを使うDeclarative Pipelineを調べていると、変数をenvironmentで宣言するなどという情報が出てくる。
試してみたが、environmentで宣言したものは定数で後から変更できなかった。
変数宣言はpipelineの外で行わないとエラーが出る。
ぶっちゃけdefなしだとglobalな変数になるようなので、宣言しない手もある。

The Apache Groovy programming language - Documentation

テスト結果のメール

PHPUnitを実行すると、以下のようなメールが飛ぶ。
プラグイン導入してカバレッジ出す方が良さそうな気もするが、とりあえずどの程度テストが実行されているかのチェックはしやすい。

[SSH] script:

php oil test --testsuite=app

[SSH] executing...
[0;32mTests Running...This may take a few moments.[0m
PHPUnit 6.0.0 by Sebastian Bergmann and contributors.

.......................S...SSSSSS  33 / 156 ( 21%)
...RR..RRR
[SSH] completed
[SSH] exit-status: 0

Finished: SUCCESS
-------------------------

テスト結果が途中で途切れるのは、リダイレクトが実行された場合など。
最後まで到達してテストが失敗になっていないと、失敗として認識されないらしい。

余談:Jenkinsからメールを飛ばす設定

ビルドの成功失敗やテストの結果など、毎回Jenkinsを開いて確認するのは面倒。
そこで、Jenkinsの管理でメール送信の設定をする。

envelope-from(return-path)は、Jenkinsの位置 > システム管理者のメールアドレスに設定。
紛らわしいが、E-mail 通知 > 返信先アドレスではないので注意。

E-mail 通知の項目で入力値を使ったテスト送信ができる。
ただしテスト送信の結果が正常でも、envelope-from(return-path)が存在しないアドレスだとエラーになってメールが届かない場合がある。
インフラの人曰く、ダブルバウンスが発生するのだそうだ。
Bounce address - Wikipedia
Double bounce

この設定をすると、各ジョブでビルド失敗時などにメールを飛ばすことができる。