今回で「動的テストの自動化を考える」シリーズも最終回となりました。最終回らしく今回の内容は盛りだくさんとなっております。前回の予告の通り、より実践に近いかたちでパイプラインのスクリプトを組んでみて実際に動かしてみたいと思います。GitのリポジトリからJenkinsfileを取得しつつ、一連の「動的テストの自動化」のための処理をCIで回すところまでを一気にやりたいと思います。

 

「パイプライン」の新規作成

前回とは違うJobにしますので新たにJobを作成します。図1はJobの名前を”TestPipeline2″として「パイプライン」を作成しています。

図1: Jobの新規作成

次に、作成した「パイプライン」の設定を行います。今回は、Gitのリポジトリ上にあるJenkinsfileを取得した後に、そのJenkinsfileの記述内容に従ってスクリプトを実行していきますので、図2のように「パイプライン」の「定義」のところで「Pipeline script from SCM」を選択します。

図2: 「パイプライン」の「定義」の設定

 

Gitのリポジトリにアクセスするための設定

「Pipeline script from SCM」を選択することで、「パイプライン」の設定がSCM設定用に切り替わりますので、図3のようにGit関連の設定を行って行きます。

図3: Gitリポジトリにアクセスするための設定

「SCM」にはGit、「リポジトリURL」には今回使用するGitのリポジトリのURL、認証情報にはGitにアクセスするためのアカウントユーザを指定します。当然ながら、Jenkins上でGitを使用するためには、予めGitプラグインのインストールとJenkinsからGitにアクセスするためのパスワードや鍵ファイルなどの認証情報の登録が必要となります。「Script Path」には、デフォルトでJenkinsfileが指定されていますのでこのまま使用します。以上で、GitからJenkinsfileを取得するための設定は完了です。

 

Jenkinsfileの実行テスト

今回のようなSCMからJenkinsfileから取得するケースでは、リポジトリの設定ができてしまえばJobの設定としてはほぼ完了となります。残りは、Jobとして実行させたい内容をJenkinsfileにスクリプトとして書いて行くことです。では、今回設定したリポジトリの設定が上手くいっているかを確認するため、次のような単にログ上に”Hello World”を出力するスクリプトで試してみたいと思います。

pipeline {
    agent any
    stages {
        stage('Hello') {
            steps {
                echo 'Hello World'
            }
        }
    }
}
 

“Hello World”を出力するスクリプトをJenkinsfileとしてGitのリポジトリにPushしておき、今回新たに作成したJobを実行してみます。図4はJenkins上でJobを実行したときのStage Viewの画面です。Stage Viewに表示されている図で言うところの薄いグリーンの四角の部分はクリックするとそのステージのログを表示することができます。

図4: Stage View

図5はGitリポジトリにアクセスしているときのログとなります。このログを見ると、Jenkins上でGit関連のコマンドが実行されているのが確認できます。同様に、図6は”Hello World”を出力したときのログとなります。

図5: Gitリポジトリへアクセス時のログ

図6: Hello World出力ログ

以上のことから、単純なスクリプトではありますが、Gitリポジトリから取得したJenkinsfileをJenkins上で実行できることが確認できました。

 

動的テスト自動化スクリプトの実装

次は、このJenkinsファイルに「動的テスト自動化」のためのスクリプトを書いて行きたいと思いますが、今回は最終回となりますので、もう一度フェーズごとに何をやるべきかをおさらいしておきたいと思います。図7は毎度お馴染みの動的テスト自動化のためのCIサイクルの図です。それぞれのフェーズでやるべきことと、対応するスクリプトの記述例は次のようになります。

図7: 動的テストのCIサイクル

コード取得

不要なファイルを削除した後に、Gitのリポジトリからコードを取得するためのスクリプトを記述します。コードは次のようになります。

stage('コードの取得'){
    steps {
        deleteDir()		// 作業フォルダ内ファイル全削除
        chekcout scm	// チェックアウト
    }
}
コードインスペクション

取得したコードを静的解析ツールに掛けるフェーズとなります。コーディングルールのチェックやソースコードの構造解析や静的解析を実行することになりますので、必要な処理をバッチファイルにまとめておき、そのバッチファイルを実行するためのスクリプトを記述します。

stage('コードインスペクション'){
    steps {
        bat 'codetest.bat'	// コーディングルールチェック
        bat 'codeanalysis.bat'	// ソースコード解析
    }
}
テストポイントの挿入

DTシリーズ製品を使用した場合、このフェーズではテストポイントの挿入を行います。また、必要に応じてDTシリーズ製品のプロジェクトファイルを作成するスクリプトも記述します。

stage('テストポイントの挿入'){
    steps {
        echo 'プロジェクトの新規作成'
        bat "mkdir ${ResultFolder}"
        bat "DTCmd -newproj ${DtProj} ${DtRoot} gpio4bit 0x00010"	// プロジェクト新規作成コマンド
        echo 'テストポイントの挿入'
        bat "DTCmd -newins ${DtProj} ${DtFileList}"	// テストポイント挿入コマンド
    }
}
ビルド

ソースコードのビルドを行うフェーズです。ビルド用のバッチファイルやスクリプトを実行するためのスクリプトを記述します。

stage('ビルド'){
    steps {
        bat "${TiJava} -jar ${TiJar} -data ${TiWorkSpace} -application com.ti.ccstudio.apps.projectBuild -ccs.workspace"
    }
}
ディプロイ

実行ファイルやイメージをターゲット環境にディプロイするフェーズです。組込み機器ではファームをターゲット基板に転送して書き込むフェーズとなります。環境に応じて、ディプロイ処理を行うためのコードを実装します。

stage('ディプロイ'){
    steps {
        bat "${TiFlash} ${TiFlashOpt} ${TiImage}"
    }
}
テスト・テストレポート取得

テストケースを流すスクリプトを記述します。DTシリーズ製品の場合は、同時にテストレポートを取得するためのスクリプトを記述します。

stage('テスト・テストレポート取得'){
    steps {
        echo 'DT10起動'
        bat "DTCmd -project ${DtProj}"
        echo 'データ収集開始'
        bat 'DTCmd -trace start'
        echo 'リセットスタート'
        bat "${TiFlash} ${TiFlashReset}"
        echo 'テスト自動実行'
        bat "${TestCommand} \"test up\""
        bat "${TestCommand} \"test down\""
        bat "${TestCommand} \"test rand\""
        bat "${TestCommand} \"test screen\""
        echo 'データ収集停止'
        bat 'DTCmd -trace stop'
    }
}
テストレポート解析

一連のテストが完了した後に取得したデータを解析するフェーズですので、取得したデータつまりテストレポートを解析するためのスクリプトを記述します。

stage('テストレポート解析'){
    steps {
        bat 'DTCmd -analyze all'
    }
}
テスト結果のアウトプット

解析したデータを集計しデータを見えやすく加工するフェーズですので、解析結果のCSVファイル出力やデータ加工のためのスクリプトを実行します。

stage('テストレポート解析'){
    steps {
        bat "mkdir ${DtCsv}"
        bat "DTCmd -export coverage ${DtCsv}\\coverage.csv"	// カバレッジ
        bat "DTCmd -export exectime ${DtCsv}\\exectime.csv"	// 実行時間
        bat "DTCmd -export period ${DtCsv}\\period.csv"		// 周期時間
        echo 'DT10終了'
        bat 'DTCmd -exit save'
    }
}
 

Jenkinsfileの実行結果

これまでの処理をまとめてJenkinsfileとして記述したものが以下になります。前回、弊社のデモ機の開発環境を対象としたときのパイプラインのScriptを紹介しましたが、その時の形式は「Scripted Pipeline」と呼ばれるもので、昨今は「Declarative Pipeline」の記述形式が推奨されているようですので、新たにDeclarative Pipelineの形式で記述しました。

pipeline {
    // Slaveで動作させる必要があるためSlave指定
    agent slave
    // 環境変数設定
    environment {
        ResultFolder="${env.JENKINS_HOME}\\jobs\\${env.JOB_NAME}\\Builds\\${env.BUILD_NUMBER}\\DT10"
        DtRoot="${env.WORKSPACE}\\trunk\\AnalogBoxDemo1"
        DtProj="${ResultFolder}\\AnalogBoxDemo.rprj"
        DtTestTool="${env.WORKSPACE}\\trunk\\TestTool"
        DtFileList="${DtTestTool}\\filelist.txt"
        DtCsv="${DtTestTool}\\csv"
        TiHome='C:\\Program Files(x86)\\Texas Instruments'
        TiCcs="${TiHome}\\ccsv4"
        TiJava="${TiCcs}\\eclipse\\jre\\bin\\java"
        TiJar="${TiCcs}\\eclipse\\startup.jar"
        TiFlash="${TiHome}\\Stellaris\\LM Flash Programmer\\LMFlash"
        TiWorkSpace="${env.WORKSPACE}\\trunk"
        TiImage="${DtRoot}\\Debug\\AnalogBoxDemo.bin"
        TiFlashOpt='--debug-port=JTAG --interface=ICDI --speed=300000 --frequency=6'
        TiFlashReset='--hreset'
        TestCommand="${DtTestTool}\\bin\\TestCommand.exe COM4"
    }
    stages {
        stage('コードの取得'){
            steps {
                deleteDir()		// 作業フォルダ内ファイル全削除
                chekcout scm	// チェックアウト
            }
        }
        stage('コードインスペクション'){
            // コードインスペクションは実行しない
        }
        stage('テストポイントの挿入'){
            steps {
                echo 'プロジェクトの新規作成'
                bat "mkdir ${ResultFolder}"
                bat "DTCmd -newproj ${DtProj} ${DtRoot} gpio4bit 0x00010"	// プロジェクト新規作成コマンド
                echo 'テストポイントの挿入'
                bat "DTCmd -newins ${DtProj} ${DtFileList}"	// テストポイント挿入コマンド
            }
        }
        stage('ビルド'){
            steps {
                bat "${TiJava} -jar ${TiJar} -data ${TiWorkSpace} -application com.ti.ccstudio.apps.projectBuild -ccs.workspace"
            }
        }
        stage('ディプロイ'){
            steps {
                bat "${TiFlash} ${TiFlashOpt} ${TiImage}"
            }
        }
        stage('テスト・テストレポート取得'){
            steps {
                echo 'DT10起動'
                bat "DTCmd -project ${DtProj}"
                echo 'データ収集開始'
                bat 'DTCmd -trace start'
                echo 'リセットスタート'
                bat "${TiFlash} ${TiFlashReset}"
                echo 'テスト自動実行'
                bat "${TestCommand} \"test up\""
                bat "${TestCommand} \"test down\""
                bat "${TestCommand} \"test rand\""
                bat "${TestCommand} \"test screen\""
                echo 'データ収集停止'
                bat 'DTCmd -trace stop'
            }
        }
        stage('テストレポート解析'){
            steps {
                bat 'DTCmd -analyze all'
            }
        }
        stage('テスト結果のアウトプット'){
            steps {
                bat "mkdir ${DtCsv}"
                bat "DTCmd -export coverage ${DtCsv}\\coverage.csv"	// カバレッジ
                bat "DTCmd -export exectime ${DtCsv}\\exectime.csv"	// 実行時間
                bat "DTCmd -export period ${DtCsv}\\period.csv"		// 周期時間
                echo 'DT10終了'
                bat 'DTCmd -exit save'
            }
        }
    }
}

このスクリプトを実行したときのStage Viewは図8のようになります。これで一連の動的テストの自動化がJenkinsfileによって実現できました。実物がお見せできないのが心苦しいところではありますが、現物の動きの動画は折を見て公開して行きたいと思います。

図8: 動的テスト自動化実行時のStage View

 

最後に

いかがでしたでしょうか?
1年半ほど前からスタートしたシリーズですが、今回で最終回となりました。今回で、ようやく「動的テストの自動化」の一連の動きをCI環境で構築できたわけですが、言ってみれば「動的テストを自動化」するための道具がそろったに過ぎません(道具を揃えるのに時間が掛かりすぎとの声も聞こえて来そうですが・・・)。道具や環境が揃っていてもうまく使いこなせなければ活きて来ませんので、今後はうまい使い方の情報を配信して行きたいと思います。

【ホワイトペーパー】CI環境における動的テストの適応

 - Jenkinsを使った動的テスト自動化の施策例 -