Jenkinsによるテストの自動化

はじめに

Jenkinsの話(CIの話)を聞き、テストの自動実行がとても魅力的に感じたので、
空きPCに環境構築して体験してみた。

やりたいこと

  1. VisualStudioのソリューションファイルをビルドする。
  2. MSTestを使ったユニットテストの実行。
  3. ユニットテストの失敗時に通知する。

※Jenkins端末はインターネットに接続できないローカルLANに配置する予定な為、
通知の手段にIPMessenger(IP Messenger 開発研究室)を使用することにした。メール通知は今回は試してません。

インストール

今回はTracLightningというプロジェクト管理ツールを使用した。(これにJenkinsが含まれている)
Trac Lightning プロジェクト日本語トップページ - SourceForge.JP

インストール種類は、すべてインストール的なものを選択。
screenshot

プラグインのインストール

ソリューションファイルをビルドするために、Jenkins MSBuild Plugin
MSTestでの失敗を検出するために、Log Parser Plugin
をインストールしました。

1,Jenkinsの管理を選択
screenshot

2,プラグインの管理を選択
screenshot

3,プラグインをインストール
screenshot

※画像ではインストール済タブに表示されていますが、未インストール時には利用可能タブに表示されています。
チェックを入れてページ最下部のインストールボタンクリックでインストールされます。

プラグインの設定

Jenkinsの管理を選択し、管理ページを表示させる。
管理項目にインストールしたプラグインの設定項目が追加されている。

Jenkins MSBuild Plugin

設定例。MSBuild.exeのパスを指定する。
screenshot

Log Parser Plugin

設定例。空ファイルを作成し、それを指定する。
screenshot
保存ボタンをクリックしないと設定が反映されないので注意。

ジョブの登録

ジョブ=ビルド単位といったところでしょうか。ビルドしたいソリューションごとにジョブを作成する必要があります。
ジョブカレントディレクトリは、C:\TracLight\projects\hudson\.hudson\jobs\<ジョブ名>(デフォルト)です。

1,新規ジョブを選択
screenshot

2,ジョブ名と種類を選択する。種類はフリースタイル・プロジェクト
screenshot

3,今回はSubversionからソースコードを取得してビルドを行うので、設定する。
screenshot
使用しない場合は"なし"を選択する。

4,リポジトリの更新確認を定期的に行う場合の設定
画像だと、毎時0分(15:00、16:00、、、) にチェックを行いリビジョンが更新されている場合にビルドを行う。
screenshot

5,ビルドするソリューションファイルの設定
はじめにMSBuild用のビルド設定項目を追加。
screenshot
[

追加された項目へ対象のソリューションファイルを指定する。
screenshot
ソース管理を使用しない場合は、ソリューションファイルのフルパスを指定する。

6,テスト実行の設定
はじめにMSTestを実行するバッチ設定項目を追加。
screenshot

追加された項目へバッチファイルを指定する。
screenshot

MSTest実行バッチは下記の通り。失敗時にIPMessengerを使用した通知も行なっている。

setlocal

set MS_TEST_DIR="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\"
set IPMSG_DIR="C:\Program Files\IPMsg\"
set PATH=%PATH%;%MS_TEST_DIR%;%IPMSG_DIR%

rem Jenkinsジョブルートを起点とした相対パス
set TEST_DLL_NAME="TestProject1\bin\Debug\TestProject1.dll"
set TRX_FULLPATH="TestResults\TestResults.trx"

set NOTICE_TARGET_HOST=192.168.111.104
set NOTICE_MSG=JenkinsSampleのテストに失敗しました!

rmdir /S /Q TestResults
mkdir TestResults
MSTest.exe /testcontainer:%TEST_DLL_NAME% /resultsfile:%TRX_FULLPATH%

if not %ERRORLEVEL% == 0 (
    IPMsg.exe /msg %NOTICE_TARGET_HOST% %NOTICE_MSG%
    echo "UnitTest is Failed"
)

endlocal
EXIT \B %ERRORLEVEL%

Jenkinsジョブではバッチファイルの実行結果が検出できないようなので、Log Parser Pluginで検出させる必要がある。
screenshot
保存ボタンクリックしないと設定情報が反映されないので注意。

プラグインの設定で指定した空ファイルへ、テスト失敗時に出力される文字列を指定する。

error /^"UnitTest is Failed"$/

ジョブの実行

手動ビルドまたはSCMポーリングでジョブが実行される。

テスト失敗時にポップアップされる!
screenshot

screenshot

あとでやるリストを抽出&出力するemeditorマクロ(ハッシュタグ機能追加バージョン)

これの派生バージョンとして
ハッシュタグ別にリストを出力する機能を追加しました。

公式サイトに登録しているもの(本流バージョン)はこれで完成形かなと思います。
出力結果も微妙に違ってくるので派生バージョンの公開は独自に行うことにします。
こちらからダウンロードしてください。
ファイル構成やマクロの登録方法は本流バージョンと同じです。

実行後の表示

1,ハッシュタグごとに分けて出力
screenshot

2,非表示対象文字列を含むリストアイテムは出力対象外
screenshot

ハッシュタグについて

  • タイトルの末尾に"#ハッシュタグ名"をつけます。。
  • 認識されるハッシュタグは、1タイトルにつき1つまでです。複数つけると最後につけたハッシュタグで認識されます。
  • 未指定の場合、"(なし)"というタグで認識されます。

非表示対象文字列について

  • デフォルトでは下記の文字列を含むタイトルは出力対象外としています。
  1. #済
  2. #済み
  3. #すみ
  4. #end

非表示対象文字列の設定について

AtodeAlert_Parsers.jseeのcreateParser関数で設定しています。
例えば、ハッシュタグ形式と同じがイヤなので別形式に変えたい場合は下記のように変更します。
これで、非表示対象文字列が "#~" から "<~>" に変わります。

function createParser(addCallback){
  
  var p = {
    atodeMark : "【あとで】",
    detectedCallback : addCallback,
    itemMng : new AtodeYaru(document.FullName),
    targetFilter : new ParseTargetANDFilter([
      new NotExistKeywordFilter("<すみ>")
      , new NotExistKeywordFilter("<済>")
      , new NotExistKeywordFilter("<済み>")
      , new NotExistKeywordFilter("<end>")
    ])
  };
  
  return new AtodeMultiParser([
    new OneLineAtodeParser(p),
    new AtodeListParser(p)
  ]);
}

あとでやるリストを抽出&出力するemeditorマクロ

テキストファイル内に書かれている"あとでやる"リストを表示するマクロです。

私個人で、テキストファイルに日々の作業実績記録&あとでやるメモを書き出しています。
これらタスクの消化を忘れないために、タスクのリスト抽出&表示するマクロを作りました。
自分用に作ったのですが、他の人も使えるかも?と思い公開しました。

公式サイトに登録させてもらいましたので、下記URLから取得できます。
http://jp.emeditor.com/modules/mydownloads/

使用方法

決まったフォーマットで書かれている"あとでやる"リストの各項目タイトルを抽出してアウトプットに出力します。
記述行へタグジャンプできるように出力内容を調整しています。*1

1,マクロ実行前
screenshot

2,実行後表示
screenshot

マクロの自動実行

ファイルを開いた直後にマクロ実行するように登録すると、いろいろ捗るかもしれません。

1,マクロ登録時に「イベントで実行チェックボックス」にチェックを入れる
screenshot

2,イベントボタンクリックするとイベントの選択ダイアログが開くので、ファイルを開いた直後にチェックを入れる
screenshot

あとでやるリストについて

開始・終了

"【あとで】"だけの行~空白行を1リスト範囲とします。
リスト範囲内には任意数のリストアイテムを含めることができます。

リストアイテム

現在は項番ありスタイル、無しスタイルのどちらかの書き方で記述します。

リストアイテムフォーマット(項番ありスタイル)
  • 内容詳細行の先頭はタブ(\t)で開始してください。
  • タイトルは必須ですが、内容詳細は任意項目です。
1、タイトル1
    内容詳細
    内容詳細
2、タイトル2
    内容詳細
3、タイトル3
4、タイトル4
    内容詳細内容詳細
...
リストアイテムフォーマット(項番なしスタイル)
  • 内容詳細行の先頭はタブ(\t)で開始してください。
  • タイトルは必須ですが、内容詳細は任意項目です。
・タイトル1
    内容詳細
    内容詳細
・タイトル2
    内容詳細
・タイトル3
・タイトル4
    内容詳細内容詳細
...
単一行の"あとでやる"リストアイテムフォーマット1 (追記:01/06)
  • "【あとで】"位置はどこでもよい
◎◎について対応した。
    【あとで】タイトル1&内容詳細1
△△の調査&回答
    【あとで】タイトル2&内容詳細2
...
単一行の"あとでやる"リストアイテムフォーマット2 (追記:01/06)
  • "【あとで】"位置はどこでもよい
◎◎について対応した。 【あとで】タイトル1&内容詳細1
△△の調査&回答 【あとで】タイトル2&内容詳細2
...

マクロの拡張について

拡張しやすいように作成したつもりです。
通知処理をAtodeAlert_ResultViewers.jseeに書いていますが、
デフォルト動作以外にアイテム毎にアラートを出すことができるようにもなっています。
ソースコード確認していろいろやってみてくさだい。

*1:アウトプット領域でダブルクリックまたはF10で記述行へスクロール

行列逆転するemeditorマクロ

アプリ開発時、エクセルを使ってダミーデータを作成するときによくやる操作を自動化できるようにと思い、このマクロを作成しました。
※DBにSQLServerを使ったときのダミーデータ作成方法。他はよくわかりません。

  1. select雛形をSQLManagementStudioから取得*1
  2. 取得したSQLをエディタに貼り付け、",\r\n"を"\t"に置換。
  3. 置換文字列をエクセルに貼り付けダミーデータ作成。
  4. 作成データをSQLManagementStudioのテーブル編集機能使って貼り付ける。

公式サイトに登録させてもらいましたので、下記URLから取得できます。
http://jp.emeditor.com/modules/mydownloads/

*1:こんな感じのSQL文が取得できる。
select
hoge,
foo,
bar,
fuga
from
hogehoge

現在編集中ファイルをバックアップするemeditorマクロ

マクロ第二段です。現在編集中ファイルを保存してそのコピーを同フォルダに作成します。
サンプルソースほぼ引用なので、この場で公開するに留めておきます。
このマクロの発展案として、一定数たまったら別の保管用フォルダに移動する処理を入れたりしようかと考えています。

(function(){
	var $d = document;
	var $s = $d.selection;
	try{
		var org = $d.FullName;
		$d.Save(org);
		var bk = org + "_" + new Date().getTime() + ".bk";
		var fso = new ActiveXObject( "Scripting.FileSystemObject" );
		fso.CopyFile(org, bk);
	}catch(e){
		alert("バックアップに失敗(" + e.message + ")");
	}
})();

選択範囲の指定列に連番をInsertするemeditorマクロ

EmEditor既存機能で「番号の挿入」が存在しますが、
自分の思っているのとすこし違っていたので、欲しかった動きをするマクロを組んでみました。
公式サイトに登録させてもらいましたので、下記URLから取得できます。

http://jp.emeditor.com/modules/mydownloads/

ジェネリックな各種リストをスレッドセーフに扱う

その1

System.Collections.ICollectionインターフェイスにキャストすることで、SyncRootにアクセス可能。これでlockを行うことができる。

//こんな感じ
var list = new List<String>();
lock (((System.Collections.ICollection)list).SyncRoot)
{
    list.Add("アイテム1");
}