キーワード駆動テスト
チュートリアル・テキスト
Rev.2017.3.6
目次
事前の確認 ..................................................................................................................1
動作環境 ...................................................................................................................................................................................................1
チュートリアル用のモジュール及びスクリプトの入手 .....................................................................................................................1
ブロック解除 ...................................................................................................................................................................................................1
自動テストの実行............................................................................................................................................................................................2
チュートリアルの準備 .......................................................................................................3
Step 1 概要.........................................................................................................................................................................................3
Step 2 目的と達成目標ついて...................................................................................................................................................4
Step 3 言葉の説明..........................................................................................................................................................................4
自動テストの基礎.............................................................................................................5
Step 1 システムテストとは............................................................................................................................................................5
Step 2 自動テストとは....................................................................................................................................................................5
自動テスト(テストコード、テストランナー)の作成 ................................................................6
Step 1 自動化の手法と作業手順.............................................................................................................................................6
Step 2 テストシナリオの作り方 ..................................................................................................................................................6
Step 3 課題1:テストシナリオの作成......................................................................................................................................7
Step 4 テストランナーとは............................................................................................................................................................8
Step 5 テストランナーの基本機能............................................................................................................................................9
Step 6 自動テストのルール.........................................................................................................................................................9
Step 7 テストランナー用キーワード駆動機能について ................................................................................................10
Step 8 課題 2:自動テストシナリオの作成..........................................................................................................................11
Step 9 テストランナー作成時の PowerShell の使い方 .................................................................................................12
Step 10 PowerShell のクラス用ユニットテスト .....................................................................................................................12
Step 11 CalcRunner の作成準備 ..............................................................................................................................................14
Step 12 課題3:CalcRunner の作成.........................................................................................................................................16
運用スクリプトおよび環境構築........................................................................................20
Step 1 運用スクリプトの機能....................................................................................................................................................20
Step 2 実行環境のフォルダ構成............................................................................................................................................20
Step 3 処理の流れとフォルダの役割 ...................................................................................................................................20
Step 4 課題4:テストセットの追加作成 ................................................................................................................................21
Step 5 テスト運用スクリプト.......................................................................................................................................................22
Step 6 テストの予想結果............................................................................................................................................................24
Step 7 テストセットの追加手順................................................................................................................................................24
テスト対象の変更対応....................................................................................................25
Step 1 テスト対象の仕様変更..................................................................................................................................................25
Step 2 課題6:既存テストの対応とテストセットの追加 .................................................................................................25
テストランナーの追加 .....................................................................................................26
Step 1 全ての消費税を変更して計算するランナーの作成.........................................................................................26
Step 2 実行スクリプトへの追加...............................................................................................................................................28
Step 3 テストセットの追加..........................................................................................................................................................28
Step 4 新テストランナーの利点...............................................................................................................................................28
テスト対象の変更対応 メッセージボックス.......................................................................29
Step 1 テスト対象の仕様変更..................................................................................................................................................29
Step 2 課題7:キーワードの機能追加 .................................................................................................................................29
システムテスト自動化のアーキテクチャ ...........................................................................30
Step 1 システムアーキテクチャ ...............................................................................................................................................30
Step 2 システムテスト自動化のアーキテクチャ...............................................................................................................30
Step 3 アーキテクチャ定義の例..............................................................................................................................................32
補足資料 ................................................................................................................33
PowerShell 5 のインストール..................................................................................................................................................................33
ブロック解除コマンド....................................................................................................................................................................................33
RunnerBase 解説.........................................................................................................................................................................................33
1
事前の確認
本チュートリアルは、PCを使用して進めます。そのため、以下の条件を整える必要があります。
注意点として、これらの設定を行う場合、レジストリ等を操作することがあるため、管理者権限で実行
する必要があります。チュートリアルに参加する前に、下記の作業を行ってください。作業内容は次項
を参照してください。
□ PowerShell 5.0 のインストール
□ PowerShell の実行ポリシーの設定
□ チュートリアルの実行モジュールや資料のダウンロード
□ ブロックの解除
□ 自動テストの実行
動作環境
① OS
Microsoft Windows7 以降。推奨は、Microsoft Windows10 64Bit。
② PowerShell 5.0
Windows 10 に標準搭載された PowerShell 5 が必要です。Windows10 以外の場合は、Windows
Management Framework 5.0 をインストールする必要があります。
入手は、以下のサイトから行います。
https://www.microsoft.com/en-us/download/details.aspx?id=50395
バージョンは、コマンドプロンプトで「PowerShell $PSVersionTable」を実行することで確認できます。
③ PowerShell の実行ポリシーの設定
実行ポリシーをコマンドプロンプト(管理者)で「PowerShell Set-ExecutionPolicy Remotesigned」を実
行して、ポリシーの設定を行います。
チュートリアル用のモジュール及びスクリプトの入手
以下のサイトから実行モジュールなどを入手する必要があります。サイト内の「SOURCE CODE」タ
グの「DownLoad」を実行する Zip ファイルがダウンロードされます。「C:¥KeywordAutoTest」フォル
ダを作成して、Zip の中身をコピーすれば入手は完了です。フォルダ名やドライブは、必ず合わせてく
ださい。https://keyworddriventesttutorial.codeplex.com/
ブロック解除
インターネットからダウンロードしたファイルを使用するとき、セキュリティエラーが発生することが
あります。エラーを回避するためには、ファイルに書き込まれている ZoneId と呼ばれる代替データス
トリームをリセットする必要があります。ZoneId をリセットするには、ファイルのプロパティから「ブ
ロックの解除」を実行します。解除する必要があるファイルには、exe/bat/ps1 などです。
複数のファイルを一括で行なう場合、Streams コマンドを使います。以下は実行例です。
streams.exe -s -d C:¥KeywordAutoTest
1. 入手:Streams
https://technet.microsoft.com/ja-jp/sysinternals/bb897440?f=255&MSPPError=-2147217396
2. 情報:streams コマンドで NTFS の代替データ・ストリーム情報を表示/削除する
http://www.atmarkit.co.jp/fwin2k/win2ktips/1363streams/streams.html
2
自動テストの実行
① テストの実行確認
エクスプローラーから「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript¥RunTest.bat」を実行して
ください。
RunTest.bat の内容
CD C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript
%SystemRoot%¥system32¥WindowsPowerShell¥v1.0¥powershell.exe
C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript¥RunTest.ps1
pause
以下のメッセージボックスが表示されれば、環境が整っています。
② エラー「テスト対象と自動テスト側の 32 ビット/64 ビットの不整合」
bat ファイルを実行したときに、下記のエラー「Platform targets differ…」と表示された場合は、テスト対象
の exe と powershell のプラットフォームが異なっています。
「C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe」を
「C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥01.Target¥86¥V1¥ CalcApp.exe」で
置換えて再度実行してください。
3
チュートリアルの準備
はじめに
ここでは、「キーワード駆動を利用したシステムテスト自動化」チュートリアルの目指す方向、出発点と到着
点を確認します。主な内容は以下の通りです。
ステップ 主な内容
概要 チュートリアルの概要と予定
目的・達成目標 本チュートリアルに期待すること
言葉の説明 本チュートリアルで使用する言葉の説明
Step 1 概要
③ チュートリアルの概要
テスト自動化において、テストコードの作成コストや保守性の悪化、テスト記述の可読性の悪さなどの問題が
発生することがあります。この対処方法の一つがキーワード駆動テストです。本チュートリアルでは、キーワ
ード駆動テストの考え方や自動テストの環境構築手順について説明します。
④ チュートリアルのアジェンダ
内容
1 自動テストの基礎
2 テストシナリオを利用したテストランナーの作成
3 テストコードの作成とテスト運用スクリプトを利用したテストの実行
4 仕様変更への対応と強化
⑤ チュートリアルの進め方
本チュートリアルを有意義なものとするために、講義だけではなく、演習を行ないながら進めます。積極的な
参加をお願いします。
⑥ 注意
テキストファイルは、全て「UTF-8」で作成します。
4
Step 2 目的と達成目標ついて
① 目的
本チュートリアルの目的は、システムテストの自動化の中でキーワード駆動の使いどころや使い方について、修
得することです。また、システムテストを自動化する上で注意すべきことを理解することです。
② 達成目標
・ システムテストの自動化について理解する
・ キーワード駆動とデータ駆動の違いを理解する
・ キーワード駆動テストの構築手順を理解する
・ テストコードを実行する、スクリプトの作り方を理解する
・ システムテスト自動化のアーキテクチャを理解する
③ あなたがつかみたいと思うことについて書いてください。また、その理由も書いてください。
つかみたいと思うこと
その理由
Step 3 言葉の説明
チュートリアルで使用する言葉について説明します。この説明は、一般的な定義と異なるものもありま
すがご了承ください。
① テストケース
テストケースとは、テストの前条件・操作(入力)・期待結果・後条件を組み合わせたものです。
② テストシナリオ
テストの操作(入力)の流れを具体な例で記述したものです。
③ テストスクリプト
テストの手順をスクリプト言語で記述したものです。
④ テストコード
テストシナリオを自動で実行するために記述したコードです。特定のルールに則って記述します。テストコー
ドは、プログラム言語以外で記述されることもあります。通常、テストケース・テストシナリオに対応します。
⑤ テストセット
一つ以上のテストケースの集まりです。
⑥ テストランナー
テストコードを実行するためにスクリプト等で記述されたものです。本チュートリアルでは、複数のテストシナ
リオをグループ化して、特定のグループのシナリオを実行するためのものをテストランナーと呼びます。
⑦ テスト運用スクリプト
テストセットを実行し、運用するためのスクリプトです。
5
自動テストの基礎
Step 1 システムテストとは
① システムテストとは
システムテストとは、システム全体が正しく動作することを確認するテストです。したがって、システムテストは、
End to End(端から端まで)で行われます。
② システムテストの例
1. 運用テスト
実運用に近い環境で、実際に運用するテスト
2. 操作性テスト
利用ユーザー視点で、操作を行うテスト
3. 構成テスト
様々な構成パターンでのテスト
4. マニュアルテスト
マニュアル通りに操作して問題なく動作することを確認するテスト
5. 回帰テスト
今回のリリースと前回のリリースで動作が同じことを確認するテスト
Step 2 自動テストとは
① 自動テストとは
自動テストとは、各種ツールなどを使用してシステム化されたテストです。したがって、自動テストの環境を構
築することは、自動テストのシステムを開発することと同じです。
② 自動テストの対象
すべてのシステムテストを自動化の対象にすることは、得策ではありません。自動化するシステムテストは、
繰り返し実行する必要があるものが効果的です。主に、回帰テストが対象となります。
③ 自動テストの保守性
回帰テストは、システムやシステムが利用するミドルウェアなどに変更が発生した時に、その変更が現状の
機能について悪い影響が出ていないことを確認するために行います。
システムの変更が頻繁に行われるような場合、何度もテストを実行することが必要になるため、自動テストは
非常に有効です。しかし、システムの変更に対応するために自動テストの対応コストが大きいと、即時性や
有効性が下がってしまいます。
④ DRY 原則「Don’t Repeat Yourself」
自動テストは、ソフトウェアです。したがって、ソフトウェア開発の原則が有効です。
DRY の法則をテストコードに適応した場合、テストコードから重複をなくすことになります。そのためには、バ
リエーションが必要な部分と必要がない部分に分けることが重要です。重複をなくすことで効率性や保守性
を高くすることになります。
参考:https://www.infoq.com/jp/news/2012/05/DRY-code-duplication-coupling
6
自動テスト(テストコード、テストランナー)の作成
Step 1 自動化の手法と作業手順
① データ駆動テスト
テストスクリプトとデータを分離し、スクリプトがファイルからデータを読み込んで実行します。
例:キャプチャで作成したスクリプトから値の部分を変数にし、外部ファイルから読み込みます。
② キーワード駆動テスト
スクリプトに、テストのすべての情報を簡易な方法で記述します。
論理的なキーワードを用いて記述されたテストコードをツールが解釈し、テスト対象を操作するテストです。
操作として、値の設定以外に、状態や値の取得を提供します。
③ システムテストのステップ
システムテストは、大きく分けると準備(テストの準備)実行(システムの起動、操作および結果の収集、シス
テムの終了)判定(テスト結果の判定)の3ステップで行います。自動テストでは、この3つのステップを自動
化する必要があります。
最近は、問題が発生した場合に、素早く対処するための情報収集も重要性が増しています。
④ テストシナリオの作成と共通部分の抜出
テストシナリオを複数作成し、共通部分と個別部分に分けます。
⑤ データ駆動(パラメータ駆動)とキーワード駆動の併用
共通部分は細かい制御を行うためデータ駆動を採用して、バリエーションが必要な個別部分はキーワード
駆動を採用します。キーワード駆動を採用することで、作りやすさと保守性を良くすることができます。
Step 2 テストシナリオの作り方
テストシナリオは、テストの手順を箇条書きにしたものです。ユーザーが行う具体的な作業をシナリオ
として記述します。自動化を前提としたシナリオの場合、より具体的に書く必要があります。曖昧な記
述では自動化することはできません。
① シナリオ名
テストの目的が分かる名前を付けます。
② シナリオの範囲
システムの起動からシステムの終了までを記述します。
③ シナリオの内容
操作だけではなく、テストの結果を判定するための手順も記述します。具体的には、「XX の値が YY である
ことを確認する」などと記述します。
④ シナリオの例:「日本語タイトルのメール送信テスト」の一部(本来、起動や確認などが必要です)
1. メールタイトルに「日本語タイトル」と入力します。
2. 送信先の To に「test@test.co.jp」と入力します。
3. 送信ボタンをクリックします。
7
Step 3 課題1:テストシナリオの作成
① 金額計算プログラムをテストのテストシナリオを複数書いてください。テストシナリオには、テス
ト目的をシナリオ名とします。シナリオは箇条書きで記述します。
【機能説明】
単価と個数の入力可能な値は、0から1000まで。
計算ボタンを押すと、金額計算が計算され、結果が表示されます。
結果は、3桁のカンマ区切りで表示されます。
【ヒント】
「同値分割法」や「境界値分析」を意識して、テストシナリオを作成してく
ださい。
例:シナリオ名:最小値の計算テスト
計算プログラムを起動する。
単価として 1 円を入力する。個数として 1 個を入力する。
計算ボタンを押下して、計算を実行する。
金額が 1 円であることを確認する。
計算プログラムを終了する。
シナリオ名:
シナリオ名:
② 上記のシナリオの共通部分抜き出して記入してください。
シナリオの共通部分:
ボタン
8
Step 4 テストランナーとは
① テストランナーとは
テストシナリオをグループ化して、特定グループのテストシナリオを実行するためのスクリプト(プログラム)で
す。
② テストランナーの目的
テストシナリオのグループに属するテストシナリオには、共通部分と可変部分があります。このままテストシナ
リオをテストコード化すると共通部分がテストコード数だけ複製されることになります。これでは、作成コストも
悪く、修正が必要になれば保守コストも増えることになります。テストランナーに共通部分を実装し、テストコ
ードから共通部分を削除します。この手法によって、効率化と保守性を向上されることがテストランナーの目
的です。これは、効率化と保守性を確保する手法のひとつです。
単価 1
個数 1
計算 Click
金額 金額は[{0}] Log
③ テストランナーの粒度
テストランナーは、テスト対象と同じ粒度となります。一般的には、ビジネスレイヤの粒度となります。
④ テストランナーのシステム構造
テストランナーの開発は、キーワード駆動基盤の上で行います。テスト対象のシステム種別ごとに自動実行
のエンジンが必要です。
本チュートリアルでは、.NetFramework で作成されたシステムをテストするためのエンジンとして
Codeer.Friendlyを使用しています。本チュートリアルでは、テストランナーのキーワード駆動基盤について
解説を行います。チュートリアルに、基盤開発は含まれていません。
今回の自動テストシステムは、以下のような構造となっています。
例えば、金額計算のテストコードの場合は、
この部分を削除します。
9
Step 5 テストランナーの基本機能
テストランナーは、基本機能として以下の機能を提供します。
① プログラムの起動
テスト対象のプログラムを起動する機能です。
② 入力域へ値の設定
ID や名前で入力域を特定し、値を設定します。
③ 処理の実行
ID や名前でボタンなどを特定し、処理を実行します。
④ 値の取得
ID や名前で入力域や表示領域を特定し、値を取得しログに出力します。
⑤ ログ出力
ログに文字列を出力します。
⑥ プログラムの終了
テスト対象のプログラムを終了する機能です。
Step 6 自動テストのルール
今回の自動テストでは、以下のルールに従っています。
① テストコードはテキストファイルで作成する
テストコードの学習コストを下げ、容易に作成できるようにするためです。
② テストの結果判定には、前回実行時の結果を使用可能とする
テストコードにテスト結果を定義して判定することもできますが、今回はテストコードには結果(判定)を含み
ません。その代わりに、テストを実行した結果を正常時の結果とすることができます。これは、回帰テストを自
動テストの対象とする場合に採用できるルールです。
このルールを採用するのは、テスト結果の作成コストを下げるためです。
③ できるだけ定義ファイルなどを用意しないで、フォルダ名やファイル名を使用する
フォルダ名やファイル名をそのままテストセット名やテストコード名とします。このルールによって、定義ファイ
ルの記述などが最低限となり、テストセットやテストコードが保守し易くなります。
④ テストの対象を選択可能とする
「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」フォルダ内の「TestList.txt」内にテストセットを
記述することで、テストセットを対象とすることができます。また、テストセットの先頭に#を付けることで一時的
に、テスト対象外とすることもできます。
⑤ テストランナーは PowerShell で作成する
テストランナーはプログラムの一種です。判断や繰り返し処理を行い場合があるため、プログラム言語で作
成する必要があります。今回は、できるだけ容易に作成できるようにするため、 C#などではなく、
PowerShell を採用しています。
⑥ テストランナーの単体テスト(ユニットテスト)を記述する
プログラムの一種であるテストランナーを確実に作成するために、単体テストを作成します。単体テストも、
PowerShell で記述します。
10
Step 7 テストランナー用キーワード駆動機能について
今回のキーワード駆動の機能は今回のテスト用に最低限になっています。強化することで、マイクロソ
フト社が提供するコントロールを使ったプログラムであれば自動テストすることができます。
① キーワード駆動機能について
今回のチュートリアルで利用する、キーワード駆動のキーワードは以下の通りです。
1. Set(値セット)
値をコントロールにセットします。設定は同期で行います。省略可。
2. Click(ボタンクリック)
ボタンをクリックします。
3. Log(値を取得して出力)
コントロールの値を取得して、指定された文字列と組み合わせてをログファイルに出力します。ログファ
イルは、結果判定を行うための情報となります。コントロールを ID で指定することができます。コントロ
ールの ID を指定する場合、続く文字列内の{0}と置き換えて成型することができます。
4. Wait(待ち)
ミリ秒を指定し、指定した時間処理を待つ。通常処理が速いため、目で確認する場合に使用します。
② キーワード駆動のテストコード
テストコードは、タブ区切りのテキストファイル(UTF-8)で作成します。拡張子は.txt。
各行は、「コントロール ID タブ 値 タブ キーワード」で指定します。
#で始まる行は、コメント扱いとなる。先頭行は、必ずコメントで、テストランナーの種類を指定します。
③ テストコードのサンプル
#Runner=SimpleRunner
単価 2
500 Wait
個数 3
500 Wait
計算 Click
金額 金額は[{0}] Log
500 Wait
処理正常終了 Log
④ テストコードの実行ログ
※※※テストケース[01.サンプルテスト.txt]※※※
NumericUpDown[単価]値[2]セット
NumericUpDown[個数]値[3]セット
金額は[6 円]
処理正常終了
⑤ SimpleRunner.psm1
class SimpleRunner : STAR.RunnerFramework.RunnerBase {
SimpleRunner(){
}
[void]テスト実行([string[]]$testCase)
{
#キーワードで値を設定
$this.SetKeywordValues($testCase);
}
}
11
Step 8 課題 2:自動テストシナリオの作成
エディター(メモ帳など)でテストシナリオを作成します。
① テストシナリオをテキストファイルで作成します。
全ページのサンプルを参考に、フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥04.TestSet¥00.キーワ
ードサンプル」内に、拡張子.txt でテストシナリオを作成します。
ファイル「00.テストケース.txt」をコピーして、リネームしてください。ファイル名は、任意で結
構です。
② 注意点
新規にファイルを作成した場合、文字コードは必ず「UTF-8」を選択してください。
③ 自動テストシナリオの実行
フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」内の「RunTest.bat」を実行します。
テスト対象のプログラムが二度起動されることを確認してください。
④ 自動結果の確認
以下の様なメッセージボックスが表示されれば、実行は成功です。エラーとなるのは、テストシナリオを追加
したことで、実行結果が変わったためです。
⑤ 結果を予想結果として、再度自動テストシナリオの実行
自動テストを実行すると、フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥06.TestResult」内に、実行時
間の日時のフォルダが作成され、その中にテスト結果が作成されます。
フォルダ内の「00.キーワードサンプル.log」ファイルを開いて、内容を確認します。
内容が予想した通りであれば、これを正式なテスト結果とします。
ファイルをフォルダ「C:¥KeywordAutoTest¥02.AutoTest¥05.TestExpected」にコピー(置き換え)してく
ださい。
再度「RunTest.bat」を実行して、下記のメッセージボクスが表示されれば成功です。
12
Step 9 テストランナー作成時の PowerShell の使い方
① PowerShell のファイル種別
1. .ps1 実行可能なスクリプトファイル
2. .psm1 他のスクリプトから利用するスクリプトモジュールファイル
3. .psd1 スクリプトのマニフェストを記述したスクリプトマニフェストファイル
② TmpRunner を作成する場合のファイル構成
1. TmpRunner.psm1
Runner の本体
2. TmpRunner.psd1
Runner のマニフェストファイルで、Runner が必要とするモジュールを定義
3. TmpRunnerTest.ps1
Runner の単体テスト、実際のテスト実行時には使用しません
4. AutoTestSetUp.ps1
Runner の基本機能を提供するモジュール(dll)を読み込むスクリプトファイル
③ 注意点(Version 5.0.10586.117)2016/8/25
このバージョンの PowerShell ISE では、利用するクラスを変更してデバッグを行う場合、ISE の再立ち上
げが必要になります。(別プロセスで立ち上げでも回避可能です)再立ち上げを行わないと、利用クラスの
変更が反映されません。これは、修正前の利用クラスが動的にコンパイルされ、そのアセンブリが読み込ま
れており、アセンブリの開放と再読み込みが行われないためです。
Step 10 PowerShell のクラス用ユニットテスト
PowerShell のバージョン5以降では、独自クラスを定義することができるようになりました。このク
ラスは、.NetFramework のクラスを継承することもできます。今回のテストランナー作成では、C#で
作成されたクラスを継承して、テストランナーを作成します。テストランナー用のユニットテストもテ
スト専用のクラスを作成して行います。今回、PowerShell で作成した独自クラス用のユニットテスト
フレームワークを利用します。
① ユニットテストのフレームワーク(UnitTest.psm1)について
属性ベースのユニットテストフレームワークです。属性は、NUnit を参考にしています。
ユニットテストは、以下のようにテスト単位に SetUp と TearDown が呼び出されます。結果、テスト単位に初
期処理と終了処理が実行さます。
SetUp > テスト 1 > TearDown > SetUp > テスト 2 > TearDown
② ユニットテストで用意されている属性
1. SetUp
初期処理メソッドであることを示す属性です。
2. TearDown
終了処理メソッドであることを示す属性です。
3. Test
テストメソッドであることを示す属性です。
13
③ 確認用メソッド
1. AssertEquals(予測値,実行値,コメント)
予測値と実行値を比較して、正しくなければエラー
2. Assert(条件,コメント)
条件が false だとエラー
④ ユニットテスト例
using module .¥UnitTest.psm1
class TestTarget
{
[int]Add([int]$a,[int]$b)
{
Write-host "TestTarget:Add"
return $a + $b;
}
}
class TestSample : TestBase
{
[SetUp()]
[void]SetUp()
{
Write-host "TestSample:SetUp"
$this.target = [TestTarget]::new();
}
[TearDown()]
[void]TearDown()
{
Write-host "TestSample:TearDown"
$this.target = $null;
}
[Test()]
[void]足し算テスト()
{
Write-host "TestSample:TestAdd1"
$this.AssertEquals( 3, $this.target.Add(1,2), "Error TestAdd1" );
}
}
$error.Clear()
[void](([TestSample]::new()).RunTest());
#スクリプトのエラー処理は、ここで行う必要がある
if( ( $error -ne $null ) -and ( $error.Count -ne 0 ) )
{
$errFlag = $false
foreach($err in $error)
{
if( $err.Exception.GetType().Name -ne 'UnitTestException' )
{
if( $errFlag -eq $false )
{
$errFlag = $true
Write-host "`n*****Error info*****"
}
$err
}
}
}
テスト対象のクラス
テストのクラス
TestBase を継承する
初期化処理
テスト対象のインスタンス生成
終了処理
テスト
AssertEquals で結果確認
テストの実行
エラーの表示
14
Step 11 CalcRunner の作成準備
金額計算で通常の計算を行うテストランナーを作成します。通常の計算では、下記のテストシナリオ内
の 3 から 5 をテストランナーが行うことで、テストコードから共通部分をなくすことができます。結果、
テストコードの作成コストが下げることになります。
注意:ファイルを作成するフォルダは、「C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps」です。
① CalcRunner が実行するテストシナリオ
1. テスト対象のプログラム「CalcApp.exe」を起動する。
2. 値を設定する。(キーワード駆動)
3. 計算ボタンを押して、計算を実行する。
4. 計算結果をログに出力する。
5. プログラムを終了する。
「CalcRunner.psm1」を使用した、テストコードは以下のようになります。
#Runner=CalcRunner
単価 2
個数 3
以降では、CalcRunner 自体のユニットテストを作成しながら最終的に上記のテストコードを実行する
CalcRunner を作成していきます。
② CalcRunner.psm1 の作成手順
1. ランナーのベースクラスを継承して、ランナークラスを定義します。
Class CalcRunner : STAR.RunnerFramework.RunnerBase{
}
2. コンストラクターを作成します。
処理が速すぎると目で確認できないので、実行に待ちを入れる設定を行います。
CalcRunner(){
$this.WaitFlag = $true;
$this.WaitTime = 100;
}
3. 空のメソッドを定義します。
本来は、ユニットテストとランナーを段階的に作成します。今回は、空のメソッドを定義する形で作業を進め
ます。
class CalcRunner : STAR.RunnerFramework.RunnerBase {
CalcRunner(){
$this.WaitFlag = $true;
$this.WaitTime = 100;
}
[string]結果取得()
{
return "";
}
[void]計算実行()
{
}
[string]テスト実行([string[]]$testCase)
{
return "";
}
}
計算処理の実行はテストランナーが行うので、
テストコードには記述しません。
15
③ CalcRunnerTest.ps1 の最終形(CalcRunner を作るためのユニットテスト)
sing module .¥Lib¥UnitTest.psm1
using module .¥CalcRunner.psd1
using module .¥CalcRunner.psm1
class CalcRunnerTest : TestBase
{
[SetUp()]
[void]SetUp()
{
$this.target = [CalcRunner]::new();
$this.target.TargetPath = 'C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe';
$this.target.LogFilePath = 'C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥Test.log';
Remove-item $this.target.LogFilePath -Force -ErrorAction Ignore
$this.target.SetUp();
}
[TearDown()]
[void]TearDown()
{
$this.target.TearDown();
}
[Test()]
[void]結果取得テスト()
{
$result = $this.target.結果取得();
$this.AssertEquals('計算結果:金額=[円]', $result );
}
[Test()]
[void]計算実行テスト()
{
#値を設定
$testCase = "単価`t2","個数`t3";
$this.target.SetKeywordValues($testCase);
#計算を実行
$this.target.計算実行();
#計算結果を確認
$result = $this.target.結果取得();
$this.AssertEquals('計算結果:金額=[6 円]', $result );
}
[Test()]
[void]テスト実行テスト()
{
#処理の実行
$testCase = "単価`t12","個数`t34";
$result = $this.target.テスト実行($testCase);
#出力されたログの内容を確認
$lines = Get-Content $this.target.LogFilePath -Encoding UTF8
$this.AssertEquals('NumericUpDown[単価]値[12]セット', $lines[0] );
$this.AssertEquals('NumericUpDown[個数]値[34]セット', $lines[1] );
$this.AssertEquals('計算実行', $lines[2] );
$this.AssertEquals('計算結果:金額=[408 円]', $lines[3] );
}
}
$error.Clear()
[void](([CalcRunnerTest]::new()).RunTest());
#以下省略
テスト対象の CalcRunner クラス
ログファイルを削除
テストケース単位で初期状態にするために
結果の確認
テストコードを文字列の配列で設定
運用時は、テキストファイルから読み込む
「計算実行」呼び出して、結果を確認
最終的に呼び出される「テスト実行」のテスト
16
Step 12 課題3:CalcRunner の作成
① CalcRunnerTest.ps1 で使用するの作業手順
1. 実行しないテストメソッドの属性「[Test()]」をコメントアウトします。
「CalcRunnerTest.ps1」ファイルを開き、下記の部分をコメントアウト(先頭に#を記述)しま
す。
[Test()]
[void]計算実行テスト()
中略
[Test()]
[void]テスト実行テスト()
② テストの実行
run.bat を実行します。
[1]NG:結果取得テスト
+ AssertEquals Fail
+ Message : Test failed.
+ Expected: 計算結果:金額=[円]
+ Actual :
Result:NG=1:OK=0
と表示されればテスト実行は成功です。(テストは失敗です。)
③ 結果取得メソッドの作成
1. テストメソッド。
最初は計算ではなく、状態(初期状態)を取得するテストです。
$this.target がランナークラスのインスタンスです。このインスタンスの結果取得メソッドを呼び出します。
その後、取得結果を AssertEquals で予想結果と実行結果を比較することで確認します。
[Test()]
[void]結果取得テスト()
{
$result = $this.target.結果取得();
$this.AssertEquals('計算結果:金額=[円]', $result );
}
2. 「CalcRunner.psm1」に正しいコードを実装します。
$this.GetText(ID)を使って文字列を取得します。金額コントロールの ID は、「金額」です。
次に、結果の文字列を成型します。
ヒント:PowerShell では、文字列に続けて –F を記述することで、文字列の成型ができます。
$金額 = $this.GetText("金額");
$result = "計算結果:金額=[{0}]" -F $金額;
return $result;
3. run.bat でテストを実行します。
以下のように表示されれば、実行は成功です。
[1]OK:結果取得テスト
Result:OK=1
17
④ 計算処理メソッドの作成
計算を実行するメソッドを作成します。
1. テストメソッド
テストランナーの値を設定するメソッドを呼び出し、コントロールに値を設定します。
コントロールの値は、「コントロールの ID+タブ+値」形式の文字列配列で指定し、SetKeywordValues
メソッドを呼び出すことで設定することができます。
その後、計算実行メソッドを呼び出します。
最後に結果を取得して、動作の判定を行います。
属性のコメントを削除します。
[Test()]
[void]計算実行テスト()
{
#値を設定
$testCase = "単価`t2","個数`t3";
$this.target.SetKeywordValues($testCase);
#計算を実行
$this.target.計算実行();
#計算結果を確認
$result = $this.target.結果取得();
$this.AssertEquals('計算結果:金額=[6 円]', $result );
}
2. run.bat でテストを実行します。
一件成功、一件失敗すれば、実行は正しく失敗しています。このとき、テスト対象のプログラムには、値
がセットされています。
[1]OK:結果取得テスト
[2]NG:計算実行テスト
3. 正しい計算実行メソッドを作成します。
Invoke(ID)メソッドを使って、処理の実行を行います。計算ボタンの ID は「計算」です。
[void]計算実行()
{
$this.Invoke("計算");
}
4. run.bat でテストを実行します。
以下のように表示されれば、実行は成功です。
[1]OK:結果取得テスト
[2]OK:計算実行テスト
Result:OK=2
18
⑤ テスト実行メソッドの作成
1. テストを実行するテストメソッド
コントロールの値を「コントロールの ID+タブ+値」の配列で指定し、テスト実行メソッドを呼び出します。
その後、結果と出力されるログを確認して動作の判定を行います。
[Test()]
[void]テスト実行テスト()
{
#処理の実行
$testCase = "単価`t12","個数`t34";
$result = $this.target.テスト実行($testCase);
#出力されたログの内容を確認
$lines = Get-Content $this.target.LogFilePath -Encoding UTF8
$this.AssertEquals('NumericUpDown[単価]値[12]セット', $lines[0] );
$this.AssertEquals('NumericUpDown[個数]値[34]セット', $lines[1] );
$this.AssertEquals('計算実行', $lines[2] );
$this.AssertEquals('計算結果:金額=[408 円]', $lines[3] );
}
2. run.bat でテストを実行します。
二件成功、一件失敗すれば、実行は正しく失敗しています。
[1]OK:結果取得テスト
[2]OK:計算実行テスト
<<省略>>
[3]NG:テスト実行テスト
Result:NG=1:OK=2
3. 正しいテスト実行メソッドを作成します。
仮コードを削除し正しい処理を実装します。値の設定/計算の実行/結果の取得を順次呼び出します。
#キーワードで値を設定
$this.SetKeywordValues($testCase);
#計算の実行
$this.計算実行();
#結果取得
return $this.結果取得();
4. ログ出力を実装します。
テ ス ト 実 行 を 実 装 し て も 、 エ ラ ー が 発 生 し ま す 。 ロ グ 出 力 の 実 行 を 行 い ま す 。 ロ グ は 、
$this.WriteLog(ログ)で出力できます。実行して、「Result:OK=3」が表示されれば成功です。
[string]結果取得()
{
#省略
$this.WriteLog($result);
return $result;
}
[void]計算実行()
{
$this.WriteLog("計算実行");
$this.Invoke("計算");
}
19
⑥ テストランナーの完成形(CalcRunner.psm1)
class CalcRunner : STAR.RunnerFramework.RunnerBase {
CalcRunner(){
$this.WaitFlag = $true;
$this.WaitTime = 100;
}
[string]結果取得()
{
#結果取得
$金額 = $this.GetText("金額");
$result = "計算結果:金額=[{0}]" -F $金額;
$this.WriteLog($result);
return $result;
}
[void]計算実行()
{
#計算の実行
$this.WriteLog("計算実行");
$this.Invoke("計算");
}
[string]テスト実行([string[]]$testCase)
{
#キーワードで値を設定
$this.SetKeywordValues($testCase);
#計算の実行
$this.計算実行();
#結果取得
return $this.結果取得();
}
}
⑦ テストコードの例
「CalcRunner.psm1」を使用した、テストコードは以下のようになります。
#Runner=CalcRunner
単価 2
個数 3
以前のテストコードとの違いで気がついがことを記入してください。
20
運用スクリプトおよび環境構築
Step 1 運用スクリプトの機能
今回の運用スクリプトでは、以下の機能を実現します。
1. テスト結果用のフォルダの準備
実行単位で異なるフォルダを作成します。フォルダ名は、実行を開始した日時を基に作成します。
2. テストセットの実行
指定されたテストセットを順次実行します。テストセット単位に、テスト結果としてのログをテストセット名
で出力します。
3. テスト結果の判定
準備された予想結果のログファイルと比較し、テストセット単位で判定を行います。
実際の自動テストでは、要求される機能は異なります。
Step 2 実行環境のフォルダ構成
今回の実行環境のフォルダは、以下の通りです。また、テストセットのルートフォルダ配下に、テスト
セットごとにサブフォルダを作成します。このフォルダ内に、テストケースごとに一つのテストコード
ファイルを作成します。
Step 3 処理の流れとフォルダの役割
テストの実行は、RunTest.ps1 で行います。以下の手順でテストが実行されます。
21
Step 4 課題4:テストセットの追加作成
テストセットは、一つ以上のテストコード(テストケース)を持ちます。テストセットは以下の手順で
作成します。
① テストセットフォルダの作成
テストセットのルートフォルダ配下に、「ID.テストセット名」でサブフォルダを作成します。
今回は、04.TestSet フォルダ配下に「01.金額計算基本テスト」を作成します。
② テストコードの作成
テストケース単位に、テストコードをテキストファイルで作成します。ファイル名は、テストケース名となるので、
テストの目的をファイル名とします。テストコードは、「ID タブ 値」の形式で作成します。#から始まる行は、
コメント行となります。最初の行のコメントだけは特別な意味を持ち、テストランナーを「Runner=テストランナ
ー名」の形で指定します。以下は、テストコードの例です。これを例に、テストコードを作成して下さい。
1. 01.最小値計算.txt
#Runner=CalcRunner
単価 1
個数 1
2. 02.最大値計算.txt
#Runner=CalcRunner
単価 1000
個数 1000
3. 03.三桁結果.txt
#Runner=CalcRunner
単価 10
個数 99
③ テストケースの実行
テスト運用スクリプトフォルダ(03.AutoScript)内の RunTest.bat を実行して、テストセットの実行を行いま
す。
この時、「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」フォルダの「TestList.txt」内のテストセ
ットの一覧で実行対象にします。(先頭に#があるテストセットは対象外となります)
00.キーワードサンプル
01.金額計算基本テスト
#02.消費税ありテスト
#03.消費税複数テスト
以下のダイアログボックスが表示されれば、テストセットの実行は成功です。
22
Step 5 テスト運用スクリプト
テスト運用スクリプトは、以下の機能を持ちます。
1. テストセットの選択
実行するテストセットは、「TestList.txt」ファイル内に記述します。先頭の#をつけるとコメント扱いとなり、
実行対象から除外されます。
2. テストセットの実行
テストセットを実行します。テストセットフォルダに含まれる、テストコードを読み込み、指定されているラ
ンナーを利用して、実行します。
3. テスト結果の判定
実行で作成作成されたログファイルと成功時に想定したログファイルを比較して、テストの判定を行い
ます。
using module ..¥02.Runner.ps¥CalcRunner.psd1
using module ..¥02.Runner.ps¥CalcRunner.psm1
function Main()
{
$Error.Clear();
Add-Type -Assembly System.Windows.Forms
#各種設定
$currentPath = Get-Location
$target = '{0}¥..¥01.TestTarget¥CalcApp.exe' -F $currentPath
$testSetRoot = '{0}¥..¥04.TestSet¥' -F $currentPath
$testExpectedRoot = '{0}¥..¥05.TestExpected¥' -F $currentPath
$resultRoot='{0}¥..¥06.TestResult¥{1}¥' -f $currentPath,( [System.DateTime]::Now.ToString('yyyyMMdd_HHmmss') )
[void](New-Item $resultRoot -ItemType Directory)
#テストセットの一覧を読み込む
$testSetList = @(Get-Content '.¥TestList.txt' -Encoding UTF8)
$errorFlag = $false
#テストセットの実行処理
$testSetCount = 0
ForEach( $testSet in $testSetList )
{
# #から始まる行はコメントとして処理しない
if( ( $testSet -ne '' ) -and ( $testSet.SubString(0,1) -ne '#' ))
{
$testSetPath = $testSetRoot + $testSet
$testLogPath = $resultRoot + $testSet + '.log'
[void]( RunTestSet $testSetPath $testLogPath )
$result = CheckLog $testExpectedRoot $testLogPath
if( $result -ne $null )
{
$errorFlag = $true
[System.Windows.Forms.MessageBox]::Show( ( "テストエラー[{0}]`n{1}" -f $testSet,$result), "エラー" )
}
$testSetCount++
}
}
if( $errorFlag -eq $false )
{
[System.Windows.Forms.MessageBox]::Show( ('テスト成功 実行テストセット数[{0}]' -f $testSetCount ) , "成功" )
}
}
テストランナーの利用定義
各種フォルダの定義
テストセットの一覧を読み込む義
テストセットの実行
先頭が#は除外
テストセットの結果比較
23
function RunTestSet([string] $testSetPath, [string]$testLogPath )
{
$testCaseList = @(Get-ChildItem $testSetPath)
ForEach( $testCase in $testCaseList )
{
if($testCase.Extension.ToUpper() -ne ".TXT")
{
continue;
}
$testKeyValue = @(Get-Content $testCase.FullName -Encoding UTF8)
$index = $testKeyValue[0].IndexOf('#Runner=')
if( $index -eq -1 )
{
continue;
}
$runnerName = $testKeyValue[0].SubString(($index+8) );
$testRunner = $null
if( $runnerName -eq 'CalcRunner' )
{
$testRunner = [CalcRunner]::new();
}
if( $testRunner -eq $null )
{
continue;
}
$testRunner.TargetPath = $target;
$testRunner.LogFilePath = $testLogPath;
$testRunner.WriteLog( ( "※※※テストケース[{0}]※※※" -F $testCase.Name ) );
$testRunner.SetUp();
$testRunner.テスト実行( $testKeyValue );
$testRunner.TearDown();
}
}
function CheckLog([string] $testExpectedRoot, [string]$testLogPath, [string]$msg )
{
$result = $null
$logFileInfo = [System.IO.FileInfo]::new( $testLogPath )
$testExpectedFilePath = '{0}{1}' -f $testExpectedRoot,$logFileInfo.Name
$logLines = @(Get-Content $testLogPath -Encoding UTF8)
$expectedLines = @(Get-Content $testExpectedFilePath -Encoding UTF8)
if( $logLines.Length -eq $expectedLines.Length )
{
$result = $null
For( $i=0;$i -lt $logLines.Length; $i++ )
{
if( $logLines[$i] -ne $expectedLines[$i] )
{
$result = "NG`t[{0}]`nEx`t[{1}]" -f $logLines[$i],$expectedLines[$i]
break
}
}
}
else
{
$result = "NG 行数違い";
}
return $result
}
main
テストコード一覧の取得
テストランナーの識別
テストコードの実行
内容比較
読み込み
行数比較
テストケース名をログに出力
24
Step 6 テストの予想結果
今回は、テストの成功時の予想結果をテキストファイルで用意します。最初から作成するのが難しい場
合、成功時の実行結果のログを予想結果とします。テストの予想結果フォルダ「05.TestExpected」内
に、テストセット単位に用意します。
例
1. 01.金額計算基本テスト.log
※※※テストケース[01.最小値計算.txt]※※※
NumericUpDown[単価]値[1]セット
NumericUpDown[個数]値[1]セット
計算実行
計算結果:金額=[1 円]
※※※テストケース[02.最大値計算.txt]※※※
NumericUpDown[単価]値[1000]セット
NumericUpDown[個数]値[1000]セット
計算実行
計算結果:金額=[1,000,000 円]
※※※テストケース[03.三桁結果.txt]※※※
NumericUpDown[単価]値[10]セット
NumericUpDown[個数]値[99]セット
計算実行
計算結果:金額=[990 円]
Step 7 テストセットの追加手順
テストセットを追加する手順は、以下の通りです。
① テストの目的と内容を決定
追加するテストセットの目的とテストセットに含まれるテストケースについて、その名前と内容を決定します。
② テストセットフォルダの作成
③ テストコードの作成
テストセットフォルダ内に、テストケースを元にテストコードを作成します。
④ テストセット一覧へ追加
テスト運用スクリプトフォルダ内の、「TestList.txt」にテストセットを追加します。
⑤ テストセットの実行
テストセットを実行します。このとき、まだ予測結果がないため、エラーとなります。テスト結果フォルダ
「06.TestResult」内にできたログファイルを確認し、正常に動作したことを確認します。
⑥ 予想結果
正常に実行されたときに作成されたログファイルを成功時の予想結果とします。作成されたログファイルを
予想結果フォルダにコピーします。
⑦ テストセットの再実行
テストセットを再実行し、テストが成功することを確認します。
25
テスト対象の変更対応
Step 1 テスト対象の仕様変更
金額計算に消費税を考慮した計算ができる機能が追加されました。
Step 2 課題6:既存テストの対応とテストセットの追加
① 既存テストの対応
対象プログラムを変更して、既存のテストを実行して見ましょう。変更なく、そのまま動作します。
② テストセットの追加
消費税を考慮したテストセットを追加しましょう。テストセット名は「02.消費税ありテスト」とします。消費税の
値を変更するためのキーワードは、消費税で、値は「パーセント 8」「パーセント 10」「内税」です。下記は、8
パーセントの計算を行うテストコードです。テストセット「02.消費税ありテスト」を追加し、実行して見ましょう。
1. 01.消費性 8 パーセント計算.txt
#Runner=CalcRunner
単価 100
個数 2
消費税 パーセント 8
③ 対応理由
今回の変更に対して、容易に対応できた理由を書いてください。
26
テストランナーの追加
Step 1 全ての消費税を変更して計算するランナーの作成
消費税の選択肢をテストコード内に記載することもできますが、ランナー側で消費税の選択と金額計算
を行わせることもできます。「TaxCalcRunner」を作成して見ましょう。
① ユニットテストの作成「TaxCalcRunnerTest.ps1」
using module .¥TaxCalcRunner.psd1
using module .¥Lib¥UnitTest.psm1
using module .¥CalcRunner.psm1
using module .¥TaxCalcRunner.psm1
class TaxCalcRunnerTest : TestBase
{
[SetUp()]
[void]SetUp()
{
$this.target = [TaxCalcRunner]::new();
$this.target.TargetPath = 'C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe';
$this.target.LogFilePath = 'C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥Test.log';
Remove-item $this.target.LogFilePath -Force -ErrorAction Ignore
$this.target.SetUp();
}
[TearDown()]
[void]TearDown()
{
$this.target.TearDown();
}
[Test()]
[void]消費税計算テスト()
{
#処理の実行
$testCase = "単価`t100","個数`t2";
$result = $this.target.テスト実行($testCase);
$this.AssertEquals('計算結果:金額=[216 円]計算結果:金額=[220 円]計算結果:金額=[200 円]', $result );
#出力されたログの内容を確認
$lines = Get-Content $this.target.LogFilePath -Encoding UTF8
$this.AssertEquals('NumericUpDown[単価]値[100]セット', $lines[0] );
$this.AssertEquals('NumericUpDown[個数]値[2]セット', $lines[1] );
$this.AssertEquals('GroupBox[パーセント 8]をチェック', $lines[2] );
$this.AssertEquals('計算実行', $lines[3] );
$this.AssertEquals('計算結果:金額=[216 円]', $lines[4] );
$this.AssertEquals('GroupBox[パーセント 10]をチェック', $lines[5] );
$this.AssertEquals('計算実行', $lines[6] );
$this.AssertEquals('計算結果:金額=[220 円]', $lines[7] );
$this.AssertEquals('GroupBox[内税]をチェック', $lines[8] );
$this.AssertEquals('計算実行', $lines[9] );
$this.AssertEquals('計算結果:金額=[200 円]', $lines[10]);
}
}
$error.Clear()
[void](([TaxCalcRunnerTest]::new()).RunTest());
#スクリプトのエラー処理は、ここで行う必要がある
#以下は同じ
TaxCalcRunner のテストクラス
TaxCalcRunner の生成
消費税テスト
一度の実行で、内税、8%、10%で計算
計算は、8%、10%、内税の順番で計算
27
② 最初の TaxCalcRunner
TaxCalcRunner は CalcRunner を継承して実装します。実行するバッチファイル「taxRun.bat」を作成し
て、テストを実行します。
using module .¥CalcRunner.psm1
class TaxCalcRunner : CalcRunner {
TaxCalcRunner(){
}
[string]テスト実行([string[]]$testCase)
{
return "";
}
}
③ 最終的な TaxCalcRunner
値の設定、計算の実行を消費税のパターン数実行します。
using module .¥CalcRunner.psm1
class TaxCalcRunner : CalcRunner {
TaxCalcRunner(){
}
[string]テスト実行([string[]]$testCase)
{
#キーワードで値を設定
$this.SetKeywordValues($testCase);
$values = 'パーセント 8', 'パーセント 10', '内税'
$result = ''
foreach($value in $values)
{
$this.SetValue('消費税',$value)
#計算の実行
$this.計算実行();
$result += $this.結果取得();
}
#結果取得
return $result;
}
}
④ taxRun.bat
CD C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps
%SystemRoot%¥syswow64¥WindowsPowerShell¥v1.0¥powershell.exe
C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥TaxCalcRunnerTest.ps1
pause
計算は、8%、10%、内税の順番で計算
ループで、値の設定と計算を実行
28
Step 2 実行スクリプトへの追加
実行スクリプトに、新しいテストランナーを追加します。
① 利用モジュールの追加
using module ..¥02.Runner.ps¥CalcRunner.psd1
using module ..¥02.Runner.ps¥SimpleRunner.psd1
using module ..¥02.Runner.ps¥TaxCalcRunner.psd1
using module ..¥02.Runner.ps¥CalcRunner.psm1
using module ..¥02.Runner.ps¥SimpleRunner.psm1
using module ..¥02.Runner.ps¥TaxCalcRunner.psm1
② テストランナー生成部分の変更
$runnerName = $testKeyValue[0].SubString(($index+8) );
$testRunner = $null
if( $runnerName -eq 'CalcRunner' )
{
$testRunner = [CalcRunner]::new();
}
elseif( $runnerName -eq 'SimpleRunner' )
{
$testRunner = [SimpleRunner]::new();
}
elseif( $runnerName -eq 'TaxCalcRunner' )
{
$testRunner = [TaxCalcRunner]::new();
}
Step 3 テストセットの追加
新しいテストランナーを使用したテストセット「03.消費税複数テスト」を作成します。
テストコード(01.消費税計算.txt)は、以下の通りです。
#Runner=TaxCalcRunner
単価 100
個数 2
テストセットを実行して見ましょう。
Step 4 新テストランナーの利点
新しいテストランナーは、CalcRunner と比較したときの利点を書いてください。
新しいテストランナーを生成
新しいテストランナーを
指定
29
テスト対象の変更対応 メッセージボックス
Step 1 テスト対象の仕様変更
消費税で 10 パーセントを選択したときに、確認のメッセージボックスが表示される機能が追加されま
した。メッセージボックスの「はい」を選択すると 10 パーセントに変更され、「いいえ」が選択される
と元の状態となり、10 パーセントの設定になりません。
Step 2 課題7:キーワードの機能追加
値の設定は、「消費税△パーセント 10」(△は区切り文字)という形式(ルール)でした。今回の機能変更に
合わせて、メッセージボックスを操作するキーワードを追加する必要があります。
どの様な形式を追加するのが良いか書いて下さい。
注意点、キーワードによる値のセットは、同期処理(対象プログラムの処理が終わってから、次のキーワード
を処理する)でした。メッセージボックスは、値のセットの処理内で行われるため通常の値セットと異なること
を明示する必要があります。
30
システムテスト自動化のアーキテクチャ
自動テストはシステムです。したがって、統一された品質を達成するためには、システムとして求めら
れる品質特性と対象(ステークホルダ)を定義することが必要です。
Step 1 システムアーキテクチャ
① システムアーキテクチャとは
システムの構造や構造化の原則です。
② システムアーキテクチャの目的
システムの品質特性を強制(支配)する構造を構築することです。
Step 2 システムテスト自動化のアーキテクチャ
自動テストには、テスト対象のシステムと自動テストシステムの二つがあります。したがって、システ
ムテスト自動化の目的を達成するためには、二つのシステムに対して自動テストに関するシステムアー
キテクチャを定義する必要があります。
① 「テスト対象システム」に対する品質特性
1. 操作性(実行性)
自動テストのプログラムから対象のプログラムを実行し、制御できること。
2. 確認性
対象のプログラムを実行した結果が正確に確認できること。
3. 再現性
テストを行う特定の状況を再現できること。
② 「テストコード(スクリプト)」に関する品質特性
1. 理解性
読みやすく理解しやすいこと。
容易に作成することができること。
できるだけ多くのメンバーが作成できること。
2. 効率性
多様で効果的なテストコード(スクリプト)を適切なコストで作成できること。
3. 保守性
テスト対象の変更に素早く対応できること。
変更が容易であること。
4. 拡張性
機能を必要に応じて拡張できること。
31
③ 「自動テストの実行」に関する品質特性
1. 安定性
自動テストを安定して実行できること。
同じテストを何度でも安定して実行できること。
2. 信頼性
テスト結果の判定が信頼できること。
④ 「自動テストの運用」に関する品質特性
1. 効率性
必要な自動テストを効率的に運用することができること。
2. 柔軟性
状況に合わせて、柔軟な運用ができること。
3. 障害許容性
対象のプログラムで予測しないエラーが発生しても、他のテストスクリプトが継続的に実行できること。
4. 並列性
複数の環境で効率的にテストを並列して実行できること。
32
Step 3 アーキテクチャ定義の例
① 指針
1. テスト対象システム
テスト容易性
自動テストを考慮した設計と実装を行うこと。
2. テストコード(スクリプト)の作成
効率性
テストスクリプトはプログラミング技術を持たないメンバーでも作成可能とすること。
システムが変更されてもテストコード(スクリプト)の変更を最低限とすること。
理解性
テストコードは、意味が分かる単語で記述可能とすること。
3. 自動テストの実行
効率性
自動テストで問題が発生した時、効率的に問題箇所を特定できること。
4. 自動テストの運用
効率性
必要なテストセットを選択して実行することができること。
② ルール
1. テスト対象システム
コントロールにドメインの名詞を name プロパティに設定すること。
2. テストコード(スクリプト)の作成
ユースシナリオのグループ単位に、Runner クラスを作成すること。
Runner クラスは、動作と情報の取得を行い、結果判定は行わないこと。
Runner クラスは、共通操作と結果取得を行うこと。
Runner クラスは、PowerShell のクラスで作成すること。
Friendly は、RunnerBase クラス(C#)のみで利用すること。
個別のテストコードは、キーワード駆動によるテキストファイルで記述すること。
3. 自動テストの実行
実行結果は、テキストファイルとすること。
テストの実行履歴をログファイルに出力すること。
ひとつのテストセット(複数のテストスクリプト)の実行は、5分以内とすること。
4. 自動テストの運用
実行するテストセットを選択することができるようにすること。
結果判定は、正常時の結果と実行時の結果を比較して行うこと。
33
補足資料
PowerShell 5 のインストール
Windows 10 に標準搭載さてた PowerShell 5 は、Windows Management Framework 5.0 に含まれた
形で提供されます。したがって、他の OS で利用するために Windows Management Framework 5.0 を
インストールする必要あります。
1. 入手:Windows Management Framework 5.0
https://www.microsoft.com/en-us/download/details.aspx?id=50395
また、PowerShell でスクリプトを作成する場合、実行ポリシーを変更することをお勧めします。
Set-ExecutionPolicy Remotesigned
ブロック解除コマンド
インターネットからダウンロードしたファイルを使用するとき、セキュリティエラーが発生することが
あります。エラーを回避するためには、ファイルに書き込まれている ZoneId と呼ばれる代替データス
トリームをリセットする必要があります。ZoneId をリセットするには、ファイルのプロパティから「ブ
ロックの解除」を実行します。
複数のファイルを一括で行いたい場合、Streams コマンドを使います。以下は実行例です。
streams.exe -s -d C:¥KeywordAutoTest
2. 入手:Streams
https://technet.microsoft.com/ja-jp/sysinternals/bb897440?f=255&MSPPError=-2147217396
3. 情報:streams コマンドで NTFS の代替データ・ストリーム情報を表示/削除する
http://www.atmarkit.co.jp/fwin2k/win2ktips/1363streams/streams.html
RunnerBase 解説
RunnerBase のキーワード駆動機能は、Codeer.Friendly を使用して作成しています。RunnerBase は、
主に以下の機能を提供しています。
① Process の管理
LaunchTarget メソッド内で、Process クラスを使用して、プロセスを起動し、プロセスを操作します。また、
起動したプロセス内のFormを操作します。操作を行うために、WindowsAppFriendのインスタンスを作成
します。下記のコードで、「t_」が接頭辞となっているものは、起動したプロセスを操作するための変数です。
Runner 側で、プロキシ(Proxy)となります。下記のコードは、プロセスを起動し、ウィンドウをアクティブにす
る部分です。
public void LaunchTarget()
{
_process = Process.Start(this.TargetPath);
SetUpProcess();
}
private void SetUpProcess()
{
_controlInfoList = new List<ControlInfo>();
t_app = new WindowsAppFriend(_process);
t_mainForm = t_app.Type<Application>().OpenForms[0];
t_mainForm.Activate();
}
34
② コントロールの管理と操作
ウィンドウが持っているコントロールを操作します。下記のコードは、操作するためにコントロールの一覧を作
成しています。この一覧を利用して、コントロールに値を設定したり、値を取得したりします。また、ボタンで
あれば、クリックの動作を実行します。
public int SetUpControls()
{
int count = t_mainForm.Controls.Count;
ControlInfo newInfo;
for (int i = 0; i < count; ++i)
{
dynamic tName = t_mainForm.Controls[i].Name;
dynamic tControlType = t_mainForm.Controls[i].GetType();
dynamic tTabIndex = t_mainForm.Controls[i].TabIndex;
newInfo = new ControlInfo();
newInfo.Name = tName.ToString();
newInfo.TabIndex = (int)tTabIndex;
③ キーワード駆動機能
キーワードを含むテキストの配列を受け取り、上記の機能を利用して、各コントロールを操作します。
下記のコードは、キーワードで振り分けを行い処理を実行する部分の一部です。
public void SetKeywordValues(string[] values)
{
foreach(string value in values)
{
//文字列の先頭が[#]の場合は、コメント扱いとして処理しない
if(string.IsNullOrWhiteSpace(value) == false &&
value.Substring(0,1) != "#" )
{
string[] parts = value.Split('¥t');
if ( parts.Length >= 2)
{
if (parts.Length >= 3 && parts[2].ToUpper().Trim() == "CLICK")
{
Invoke(parts[0]);
}
35
④ 非同期処理
操作によってメッセージボックスが表示される場合などは、非同期処理を行う必要があります。
下記のコードでは、Async を使って非同期で処理を実行し、WaitForCompletion で非同期処理の終了を
待っています。
public void SetValueAndMessageBox(string controlName, string value, string button)
{
int index = GetControlIndex(controlName);
ControlInfo info = _controlInfoList[index];
(t_mainForm.Controls[index]).Focus();
TakeWait();
if (info.Category == ControlInfo.ControlCategory.GroupBox)
{
dynamic tRadioButtonList = t_mainForm.Controls[index].Controls;
int count = tRadioButtonList.Count;
for (int i = 0; i < count; ++i)
{
dynamic tRadioButton = tRadioButtonList[i];
string name = tRadioButton.Name;
if (name == value)
{
var async1 = new Async();
WriteLog(String.Format("GroupBox[{0}]をチェック", name));
tRadioButton.Checked(true,async1);
TakeWait();
WriteLog(String.Format("Messagebox の[{0}]を押下", button));
CloseMessagebox(button);
async1.WaitForCompletion();
break;
}
}
}
}
private void CloseMessagebox(string button)
{
WindowControl dlg = WindowControl.FromZTop(t_app); ;
var msgBox = new NativeMessageBox(dlg);
msgBox.EmulateButtonClick(button);
}

キーワード駆動テストチュートリアルハンズアウト.03.06

  • 1.
  • 2.
    目次 事前の確認 ..................................................................................................................1 動作環境 ...................................................................................................................................................................................................1 チュートリアル用のモジュール及びスクリプトの入手.....................................................................................................................1 ブロック解除 ...................................................................................................................................................................................................1 自動テストの実行............................................................................................................................................................................................2 チュートリアルの準備 .......................................................................................................3 Step 1 概要.........................................................................................................................................................................................3 Step 2 目的と達成目標ついて...................................................................................................................................................4 Step 3 言葉の説明..........................................................................................................................................................................4 自動テストの基礎.............................................................................................................5 Step 1 システムテストとは............................................................................................................................................................5 Step 2 自動テストとは....................................................................................................................................................................5 自動テスト(テストコード、テストランナー)の作成 ................................................................6 Step 1 自動化の手法と作業手順.............................................................................................................................................6 Step 2 テストシナリオの作り方 ..................................................................................................................................................6 Step 3 課題1:テストシナリオの作成......................................................................................................................................7 Step 4 テストランナーとは............................................................................................................................................................8 Step 5 テストランナーの基本機能............................................................................................................................................9 Step 6 自動テストのルール.........................................................................................................................................................9 Step 7 テストランナー用キーワード駆動機能について ................................................................................................10 Step 8 課題 2:自動テストシナリオの作成..........................................................................................................................11 Step 9 テストランナー作成時の PowerShell の使い方 .................................................................................................12 Step 10 PowerShell のクラス用ユニットテスト .....................................................................................................................12 Step 11 CalcRunner の作成準備 ..............................................................................................................................................14 Step 12 課題3:CalcRunner の作成.........................................................................................................................................16 運用スクリプトおよび環境構築........................................................................................20 Step 1 運用スクリプトの機能....................................................................................................................................................20 Step 2 実行環境のフォルダ構成............................................................................................................................................20 Step 3 処理の流れとフォルダの役割 ...................................................................................................................................20 Step 4 課題4:テストセットの追加作成 ................................................................................................................................21 Step 5 テスト運用スクリプト.......................................................................................................................................................22 Step 6 テストの予想結果............................................................................................................................................................24 Step 7 テストセットの追加手順................................................................................................................................................24
  • 3.
    テスト対象の変更対応....................................................................................................25 Step 1 テスト対象の仕様変更..................................................................................................................................................25 Step2 課題6:既存テストの対応とテストセットの追加 .................................................................................................25 テストランナーの追加 .....................................................................................................26 Step 1 全ての消費税を変更して計算するランナーの作成.........................................................................................26 Step 2 実行スクリプトへの追加...............................................................................................................................................28 Step 3 テストセットの追加..........................................................................................................................................................28 Step 4 新テストランナーの利点...............................................................................................................................................28 テスト対象の変更対応 メッセージボックス.......................................................................29 Step 1 テスト対象の仕様変更..................................................................................................................................................29 Step 2 課題7:キーワードの機能追加 .................................................................................................................................29 システムテスト自動化のアーキテクチャ ...........................................................................30 Step 1 システムアーキテクチャ ...............................................................................................................................................30 Step 2 システムテスト自動化のアーキテクチャ...............................................................................................................30 Step 3 アーキテクチャ定義の例..............................................................................................................................................32 補足資料 ................................................................................................................33 PowerShell 5 のインストール..................................................................................................................................................................33 ブロック解除コマンド....................................................................................................................................................................................33 RunnerBase 解説.........................................................................................................................................................................................33
  • 4.
    1 事前の確認 本チュートリアルは、PCを使用して進めます。そのため、以下の条件を整える必要があります。 注意点として、これらの設定を行う場合、レジストリ等を操作することがあるため、管理者権限で実行 する必要があります。チュートリアルに参加する前に、下記の作業を行ってください。作業内容は次項 を参照してください。 □ PowerShell 5.0のインストール □ PowerShell の実行ポリシーの設定 □ チュートリアルの実行モジュールや資料のダウンロード □ ブロックの解除 □ 自動テストの実行 動作環境 ① OS Microsoft Windows7 以降。推奨は、Microsoft Windows10 64Bit。 ② PowerShell 5.0 Windows 10 に標準搭載された PowerShell 5 が必要です。Windows10 以外の場合は、Windows Management Framework 5.0 をインストールする必要があります。 入手は、以下のサイトから行います。 https://www.microsoft.com/en-us/download/details.aspx?id=50395 バージョンは、コマンドプロンプトで「PowerShell $PSVersionTable」を実行することで確認できます。 ③ PowerShell の実行ポリシーの設定 実行ポリシーをコマンドプロンプト(管理者)で「PowerShell Set-ExecutionPolicy Remotesigned」を実 行して、ポリシーの設定を行います。 チュートリアル用のモジュール及びスクリプトの入手 以下のサイトから実行モジュールなどを入手する必要があります。サイト内の「SOURCE CODE」タ グの「DownLoad」を実行する Zip ファイルがダウンロードされます。「C:¥KeywordAutoTest」フォル ダを作成して、Zip の中身をコピーすれば入手は完了です。フォルダ名やドライブは、必ず合わせてく ださい。https://keyworddriventesttutorial.codeplex.com/ ブロック解除 インターネットからダウンロードしたファイルを使用するとき、セキュリティエラーが発生することが あります。エラーを回避するためには、ファイルに書き込まれている ZoneId と呼ばれる代替データス トリームをリセットする必要があります。ZoneId をリセットするには、ファイルのプロパティから「ブ ロックの解除」を実行します。解除する必要があるファイルには、exe/bat/ps1 などです。 複数のファイルを一括で行なう場合、Streams コマンドを使います。以下は実行例です。 streams.exe -s -d C:¥KeywordAutoTest 1. 入手:Streams https://technet.microsoft.com/ja-jp/sysinternals/bb897440?f=255&MSPPError=-2147217396 2. 情報:streams コマンドで NTFS の代替データ・ストリーム情報を表示/削除する http://www.atmarkit.co.jp/fwin2k/win2ktips/1363streams/streams.html
  • 5.
    2 自動テストの実行 ① テストの実行確認 エクスプローラーから「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript¥RunTest.bat」を実行して ください。 RunTest.bat の内容 CDC:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript %SystemRoot%¥system32¥WindowsPowerShell¥v1.0¥powershell.exe C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript¥RunTest.ps1 pause 以下のメッセージボックスが表示されれば、環境が整っています。 ② エラー「テスト対象と自動テスト側の 32 ビット/64 ビットの不整合」 bat ファイルを実行したときに、下記のエラー「Platform targets differ…」と表示された場合は、テスト対象 の exe と powershell のプラットフォームが異なっています。 「C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe」を 「C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥01.Target¥86¥V1¥ CalcApp.exe」で 置換えて再度実行してください。
  • 6.
    3 チュートリアルの準備 はじめに ここでは、「キーワード駆動を利用したシステムテスト自動化」チュートリアルの目指す方向、出発点と到着 点を確認します。主な内容は以下の通りです。 ステップ 主な内容 概要 チュートリアルの概要と予定 目的・達成目標本チュートリアルに期待すること 言葉の説明 本チュートリアルで使用する言葉の説明 Step 1 概要 ③ チュートリアルの概要 テスト自動化において、テストコードの作成コストや保守性の悪化、テスト記述の可読性の悪さなどの問題が 発生することがあります。この対処方法の一つがキーワード駆動テストです。本チュートリアルでは、キーワ ード駆動テストの考え方や自動テストの環境構築手順について説明します。 ④ チュートリアルのアジェンダ 内容 1 自動テストの基礎 2 テストシナリオを利用したテストランナーの作成 3 テストコードの作成とテスト運用スクリプトを利用したテストの実行 4 仕様変更への対応と強化 ⑤ チュートリアルの進め方 本チュートリアルを有意義なものとするために、講義だけではなく、演習を行ないながら進めます。積極的な 参加をお願いします。 ⑥ 注意 テキストファイルは、全て「UTF-8」で作成します。
  • 7.
    4 Step 2 目的と達成目標ついて ①目的 本チュートリアルの目的は、システムテストの自動化の中でキーワード駆動の使いどころや使い方について、修 得することです。また、システムテストを自動化する上で注意すべきことを理解することです。 ② 達成目標 ・ システムテストの自動化について理解する ・ キーワード駆動とデータ駆動の違いを理解する ・ キーワード駆動テストの構築手順を理解する ・ テストコードを実行する、スクリプトの作り方を理解する ・ システムテスト自動化のアーキテクチャを理解する ③ あなたがつかみたいと思うことについて書いてください。また、その理由も書いてください。 つかみたいと思うこと その理由 Step 3 言葉の説明 チュートリアルで使用する言葉について説明します。この説明は、一般的な定義と異なるものもありま すがご了承ください。 ① テストケース テストケースとは、テストの前条件・操作(入力)・期待結果・後条件を組み合わせたものです。 ② テストシナリオ テストの操作(入力)の流れを具体な例で記述したものです。 ③ テストスクリプト テストの手順をスクリプト言語で記述したものです。 ④ テストコード テストシナリオを自動で実行するために記述したコードです。特定のルールに則って記述します。テストコー ドは、プログラム言語以外で記述されることもあります。通常、テストケース・テストシナリオに対応します。 ⑤ テストセット 一つ以上のテストケースの集まりです。 ⑥ テストランナー テストコードを実行するためにスクリプト等で記述されたものです。本チュートリアルでは、複数のテストシナ リオをグループ化して、特定のグループのシナリオを実行するためのものをテストランナーと呼びます。 ⑦ テスト運用スクリプト テストセットを実行し、運用するためのスクリプトです。
  • 8.
    5 自動テストの基礎 Step 1 システムテストとは ①システムテストとは システムテストとは、システム全体が正しく動作することを確認するテストです。したがって、システムテストは、 End to End(端から端まで)で行われます。 ② システムテストの例 1. 運用テスト 実運用に近い環境で、実際に運用するテスト 2. 操作性テスト 利用ユーザー視点で、操作を行うテスト 3. 構成テスト 様々な構成パターンでのテスト 4. マニュアルテスト マニュアル通りに操作して問題なく動作することを確認するテスト 5. 回帰テスト 今回のリリースと前回のリリースで動作が同じことを確認するテスト Step 2 自動テストとは ① 自動テストとは 自動テストとは、各種ツールなどを使用してシステム化されたテストです。したがって、自動テストの環境を構 築することは、自動テストのシステムを開発することと同じです。 ② 自動テストの対象 すべてのシステムテストを自動化の対象にすることは、得策ではありません。自動化するシステムテストは、 繰り返し実行する必要があるものが効果的です。主に、回帰テストが対象となります。 ③ 自動テストの保守性 回帰テストは、システムやシステムが利用するミドルウェアなどに変更が発生した時に、その変更が現状の 機能について悪い影響が出ていないことを確認するために行います。 システムの変更が頻繁に行われるような場合、何度もテストを実行することが必要になるため、自動テストは 非常に有効です。しかし、システムの変更に対応するために自動テストの対応コストが大きいと、即時性や 有効性が下がってしまいます。 ④ DRY 原則「Don’t Repeat Yourself」 自動テストは、ソフトウェアです。したがって、ソフトウェア開発の原則が有効です。 DRY の法則をテストコードに適応した場合、テストコードから重複をなくすことになります。そのためには、バ リエーションが必要な部分と必要がない部分に分けることが重要です。重複をなくすことで効率性や保守性 を高くすることになります。 参考:https://www.infoq.com/jp/news/2012/05/DRY-code-duplication-coupling
  • 9.
    6 自動テスト(テストコード、テストランナー)の作成 Step 1 自動化の手法と作業手順 ①データ駆動テスト テストスクリプトとデータを分離し、スクリプトがファイルからデータを読み込んで実行します。 例:キャプチャで作成したスクリプトから値の部分を変数にし、外部ファイルから読み込みます。 ② キーワード駆動テスト スクリプトに、テストのすべての情報を簡易な方法で記述します。 論理的なキーワードを用いて記述されたテストコードをツールが解釈し、テスト対象を操作するテストです。 操作として、値の設定以外に、状態や値の取得を提供します。 ③ システムテストのステップ システムテストは、大きく分けると準備(テストの準備)実行(システムの起動、操作および結果の収集、シス テムの終了)判定(テスト結果の判定)の3ステップで行います。自動テストでは、この3つのステップを自動 化する必要があります。 最近は、問題が発生した場合に、素早く対処するための情報収集も重要性が増しています。 ④ テストシナリオの作成と共通部分の抜出 テストシナリオを複数作成し、共通部分と個別部分に分けます。 ⑤ データ駆動(パラメータ駆動)とキーワード駆動の併用 共通部分は細かい制御を行うためデータ駆動を採用して、バリエーションが必要な個別部分はキーワード 駆動を採用します。キーワード駆動を採用することで、作りやすさと保守性を良くすることができます。 Step 2 テストシナリオの作り方 テストシナリオは、テストの手順を箇条書きにしたものです。ユーザーが行う具体的な作業をシナリオ として記述します。自動化を前提としたシナリオの場合、より具体的に書く必要があります。曖昧な記 述では自動化することはできません。 ① シナリオ名 テストの目的が分かる名前を付けます。 ② シナリオの範囲 システムの起動からシステムの終了までを記述します。 ③ シナリオの内容 操作だけではなく、テストの結果を判定するための手順も記述します。具体的には、「XX の値が YY である ことを確認する」などと記述します。 ④ シナリオの例:「日本語タイトルのメール送信テスト」の一部(本来、起動や確認などが必要です) 1. メールタイトルに「日本語タイトル」と入力します。 2. 送信先の To に「test@test.co.jp」と入力します。 3. 送信ボタンをクリックします。
  • 10.
    7 Step 3 課題1:テストシナリオの作成 ①金額計算プログラムをテストのテストシナリオを複数書いてください。テストシナリオには、テス ト目的をシナリオ名とします。シナリオは箇条書きで記述します。 【機能説明】 単価と個数の入力可能な値は、0から1000まで。 計算ボタンを押すと、金額計算が計算され、結果が表示されます。 結果は、3桁のカンマ区切りで表示されます。 【ヒント】 「同値分割法」や「境界値分析」を意識して、テストシナリオを作成してく ださい。 例:シナリオ名:最小値の計算テスト 計算プログラムを起動する。 単価として 1 円を入力する。個数として 1 個を入力する。 計算ボタンを押下して、計算を実行する。 金額が 1 円であることを確認する。 計算プログラムを終了する。 シナリオ名: シナリオ名: ② 上記のシナリオの共通部分抜き出して記入してください。 シナリオの共通部分: ボタン
  • 11.
    8 Step 4 テストランナーとは ①テストランナーとは テストシナリオをグループ化して、特定グループのテストシナリオを実行するためのスクリプト(プログラム)で す。 ② テストランナーの目的 テストシナリオのグループに属するテストシナリオには、共通部分と可変部分があります。このままテストシナ リオをテストコード化すると共通部分がテストコード数だけ複製されることになります。これでは、作成コストも 悪く、修正が必要になれば保守コストも増えることになります。テストランナーに共通部分を実装し、テストコ ードから共通部分を削除します。この手法によって、効率化と保守性を向上されることがテストランナーの目 的です。これは、効率化と保守性を確保する手法のひとつです。 単価 1 個数 1 計算 Click 金額 金額は[{0}] Log ③ テストランナーの粒度 テストランナーは、テスト対象と同じ粒度となります。一般的には、ビジネスレイヤの粒度となります。 ④ テストランナーのシステム構造 テストランナーの開発は、キーワード駆動基盤の上で行います。テスト対象のシステム種別ごとに自動実行 のエンジンが必要です。 本チュートリアルでは、.NetFramework で作成されたシステムをテストするためのエンジンとして Codeer.Friendlyを使用しています。本チュートリアルでは、テストランナーのキーワード駆動基盤について 解説を行います。チュートリアルに、基盤開発は含まれていません。 今回の自動テストシステムは、以下のような構造となっています。 例えば、金額計算のテストコードの場合は、 この部分を削除します。
  • 12.
    9 Step 5 テストランナーの基本機能 テストランナーは、基本機能として以下の機能を提供します。 ①プログラムの起動 テスト対象のプログラムを起動する機能です。 ② 入力域へ値の設定 ID や名前で入力域を特定し、値を設定します。 ③ 処理の実行 ID や名前でボタンなどを特定し、処理を実行します。 ④ 値の取得 ID や名前で入力域や表示領域を特定し、値を取得しログに出力します。 ⑤ ログ出力 ログに文字列を出力します。 ⑥ プログラムの終了 テスト対象のプログラムを終了する機能です。 Step 6 自動テストのルール 今回の自動テストでは、以下のルールに従っています。 ① テストコードはテキストファイルで作成する テストコードの学習コストを下げ、容易に作成できるようにするためです。 ② テストの結果判定には、前回実行時の結果を使用可能とする テストコードにテスト結果を定義して判定することもできますが、今回はテストコードには結果(判定)を含み ません。その代わりに、テストを実行した結果を正常時の結果とすることができます。これは、回帰テストを自 動テストの対象とする場合に採用できるルールです。 このルールを採用するのは、テスト結果の作成コストを下げるためです。 ③ できるだけ定義ファイルなどを用意しないで、フォルダ名やファイル名を使用する フォルダ名やファイル名をそのままテストセット名やテストコード名とします。このルールによって、定義ファイ ルの記述などが最低限となり、テストセットやテストコードが保守し易くなります。 ④ テストの対象を選択可能とする 「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」フォルダ内の「TestList.txt」内にテストセットを 記述することで、テストセットを対象とすることができます。また、テストセットの先頭に#を付けることで一時的 に、テスト対象外とすることもできます。 ⑤ テストランナーは PowerShell で作成する テストランナーはプログラムの一種です。判断や繰り返し処理を行い場合があるため、プログラム言語で作 成する必要があります。今回は、できるだけ容易に作成できるようにするため、 C#などではなく、 PowerShell を採用しています。 ⑥ テストランナーの単体テスト(ユニットテスト)を記述する プログラムの一種であるテストランナーを確実に作成するために、単体テストを作成します。単体テストも、 PowerShell で記述します。
  • 13.
    10 Step 7 テストランナー用キーワード駆動機能について 今回のキーワード駆動の機能は今回のテスト用に最低限になっています。強化することで、マイクロソ フト社が提供するコントロールを使ったプログラムであれば自動テストすることができます。 ①キーワード駆動機能について 今回のチュートリアルで利用する、キーワード駆動のキーワードは以下の通りです。 1. Set(値セット) 値をコントロールにセットします。設定は同期で行います。省略可。 2. Click(ボタンクリック) ボタンをクリックします。 3. Log(値を取得して出力) コントロールの値を取得して、指定された文字列と組み合わせてをログファイルに出力します。ログファ イルは、結果判定を行うための情報となります。コントロールを ID で指定することができます。コントロ ールの ID を指定する場合、続く文字列内の{0}と置き換えて成型することができます。 4. Wait(待ち) ミリ秒を指定し、指定した時間処理を待つ。通常処理が速いため、目で確認する場合に使用します。 ② キーワード駆動のテストコード テストコードは、タブ区切りのテキストファイル(UTF-8)で作成します。拡張子は.txt。 各行は、「コントロール ID タブ 値 タブ キーワード」で指定します。 #で始まる行は、コメント扱いとなる。先頭行は、必ずコメントで、テストランナーの種類を指定します。 ③ テストコードのサンプル #Runner=SimpleRunner 単価 2 500 Wait 個数 3 500 Wait 計算 Click 金額 金額は[{0}] Log 500 Wait 処理正常終了 Log ④ テストコードの実行ログ ※※※テストケース[01.サンプルテスト.txt]※※※ NumericUpDown[単価]値[2]セット NumericUpDown[個数]値[3]セット 金額は[6 円] 処理正常終了 ⑤ SimpleRunner.psm1 class SimpleRunner : STAR.RunnerFramework.RunnerBase { SimpleRunner(){ } [void]テスト実行([string[]]$testCase) { #キーワードで値を設定 $this.SetKeywordValues($testCase); } }
  • 14.
    11 Step 8 課題2:自動テストシナリオの作成 エディター(メモ帳など)でテストシナリオを作成します。 ① テストシナリオをテキストファイルで作成します。 全ページのサンプルを参考に、フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥04.TestSet¥00.キーワ ードサンプル」内に、拡張子.txt でテストシナリオを作成します。 ファイル「00.テストケース.txt」をコピーして、リネームしてください。ファイル名は、任意で結 構です。 ② 注意点 新規にファイルを作成した場合、文字コードは必ず「UTF-8」を選択してください。 ③ 自動テストシナリオの実行 フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」内の「RunTest.bat」を実行します。 テスト対象のプログラムが二度起動されることを確認してください。 ④ 自動結果の確認 以下の様なメッセージボックスが表示されれば、実行は成功です。エラーとなるのは、テストシナリオを追加 したことで、実行結果が変わったためです。 ⑤ 結果を予想結果として、再度自動テストシナリオの実行 自動テストを実行すると、フォルダ「C:¥KeywordAutoTest¥02.AutoTest¥06.TestResult」内に、実行時 間の日時のフォルダが作成され、その中にテスト結果が作成されます。 フォルダ内の「00.キーワードサンプル.log」ファイルを開いて、内容を確認します。 内容が予想した通りであれば、これを正式なテスト結果とします。 ファイルをフォルダ「C:¥KeywordAutoTest¥02.AutoTest¥05.TestExpected」にコピー(置き換え)してく ださい。 再度「RunTest.bat」を実行して、下記のメッセージボクスが表示されれば成功です。
  • 15.
    12 Step 9 テストランナー作成時のPowerShell の使い方 ① PowerShell のファイル種別 1. .ps1 実行可能なスクリプトファイル 2. .psm1 他のスクリプトから利用するスクリプトモジュールファイル 3. .psd1 スクリプトのマニフェストを記述したスクリプトマニフェストファイル ② TmpRunner を作成する場合のファイル構成 1. TmpRunner.psm1 Runner の本体 2. TmpRunner.psd1 Runner のマニフェストファイルで、Runner が必要とするモジュールを定義 3. TmpRunnerTest.ps1 Runner の単体テスト、実際のテスト実行時には使用しません 4. AutoTestSetUp.ps1 Runner の基本機能を提供するモジュール(dll)を読み込むスクリプトファイル ③ 注意点(Version 5.0.10586.117)2016/8/25 このバージョンの PowerShell ISE では、利用するクラスを変更してデバッグを行う場合、ISE の再立ち上 げが必要になります。(別プロセスで立ち上げでも回避可能です)再立ち上げを行わないと、利用クラスの 変更が反映されません。これは、修正前の利用クラスが動的にコンパイルされ、そのアセンブリが読み込ま れており、アセンブリの開放と再読み込みが行われないためです。 Step 10 PowerShell のクラス用ユニットテスト PowerShell のバージョン5以降では、独自クラスを定義することができるようになりました。このク ラスは、.NetFramework のクラスを継承することもできます。今回のテストランナー作成では、C#で 作成されたクラスを継承して、テストランナーを作成します。テストランナー用のユニットテストもテ スト専用のクラスを作成して行います。今回、PowerShell で作成した独自クラス用のユニットテスト フレームワークを利用します。 ① ユニットテストのフレームワーク(UnitTest.psm1)について 属性ベースのユニットテストフレームワークです。属性は、NUnit を参考にしています。 ユニットテストは、以下のようにテスト単位に SetUp と TearDown が呼び出されます。結果、テスト単位に初 期処理と終了処理が実行さます。 SetUp > テスト 1 > TearDown > SetUp > テスト 2 > TearDown ② ユニットテストで用意されている属性 1. SetUp 初期処理メソッドであることを示す属性です。 2. TearDown 終了処理メソッドであることを示す属性です。 3. Test テストメソッドであることを示す属性です。
  • 16.
    13 ③ 確認用メソッド 1. AssertEquals(予測値,実行値,コメント) 予測値と実行値を比較して、正しくなければエラー 2.Assert(条件,コメント) 条件が false だとエラー ④ ユニットテスト例 using module .¥UnitTest.psm1 class TestTarget { [int]Add([int]$a,[int]$b) { Write-host "TestTarget:Add" return $a + $b; } } class TestSample : TestBase { [SetUp()] [void]SetUp() { Write-host "TestSample:SetUp" $this.target = [TestTarget]::new(); } [TearDown()] [void]TearDown() { Write-host "TestSample:TearDown" $this.target = $null; } [Test()] [void]足し算テスト() { Write-host "TestSample:TestAdd1" $this.AssertEquals( 3, $this.target.Add(1,2), "Error TestAdd1" ); } } $error.Clear() [void](([TestSample]::new()).RunTest()); #スクリプトのエラー処理は、ここで行う必要がある if( ( $error -ne $null ) -and ( $error.Count -ne 0 ) ) { $errFlag = $false foreach($err in $error) { if( $err.Exception.GetType().Name -ne 'UnitTestException' ) { if( $errFlag -eq $false ) { $errFlag = $true Write-host "`n*****Error info*****" } $err } } } テスト対象のクラス テストのクラス TestBase を継承する 初期化処理 テスト対象のインスタンス生成 終了処理 テスト AssertEquals で結果確認 テストの実行 エラーの表示
  • 17.
    14 Step 11 CalcRunnerの作成準備 金額計算で通常の計算を行うテストランナーを作成します。通常の計算では、下記のテストシナリオ内 の 3 から 5 をテストランナーが行うことで、テストコードから共通部分をなくすことができます。結果、 テストコードの作成コストが下げることになります。 注意:ファイルを作成するフォルダは、「C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps」です。 ① CalcRunner が実行するテストシナリオ 1. テスト対象のプログラム「CalcApp.exe」を起動する。 2. 値を設定する。(キーワード駆動) 3. 計算ボタンを押して、計算を実行する。 4. 計算結果をログに出力する。 5. プログラムを終了する。 「CalcRunner.psm1」を使用した、テストコードは以下のようになります。 #Runner=CalcRunner 単価 2 個数 3 以降では、CalcRunner 自体のユニットテストを作成しながら最終的に上記のテストコードを実行する CalcRunner を作成していきます。 ② CalcRunner.psm1 の作成手順 1. ランナーのベースクラスを継承して、ランナークラスを定義します。 Class CalcRunner : STAR.RunnerFramework.RunnerBase{ } 2. コンストラクターを作成します。 処理が速すぎると目で確認できないので、実行に待ちを入れる設定を行います。 CalcRunner(){ $this.WaitFlag = $true; $this.WaitTime = 100; } 3. 空のメソッドを定義します。 本来は、ユニットテストとランナーを段階的に作成します。今回は、空のメソッドを定義する形で作業を進め ます。 class CalcRunner : STAR.RunnerFramework.RunnerBase { CalcRunner(){ $this.WaitFlag = $true; $this.WaitTime = 100; } [string]結果取得() { return ""; } [void]計算実行() { } [string]テスト実行([string[]]$testCase) { return ""; } } 計算処理の実行はテストランナーが行うので、 テストコードには記述しません。
  • 18.
    15 ③ CalcRunnerTest.ps1 の最終形(CalcRunnerを作るためのユニットテスト) sing module .¥Lib¥UnitTest.psm1 using module .¥CalcRunner.psd1 using module .¥CalcRunner.psm1 class CalcRunnerTest : TestBase { [SetUp()] [void]SetUp() { $this.target = [CalcRunner]::new(); $this.target.TargetPath = 'C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe'; $this.target.LogFilePath = 'C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥Test.log'; Remove-item $this.target.LogFilePath -Force -ErrorAction Ignore $this.target.SetUp(); } [TearDown()] [void]TearDown() { $this.target.TearDown(); } [Test()] [void]結果取得テスト() { $result = $this.target.結果取得(); $this.AssertEquals('計算結果:金額=[円]', $result ); } [Test()] [void]計算実行テスト() { #値を設定 $testCase = "単価`t2","個数`t3"; $this.target.SetKeywordValues($testCase); #計算を実行 $this.target.計算実行(); #計算結果を確認 $result = $this.target.結果取得(); $this.AssertEquals('計算結果:金額=[6 円]', $result ); } [Test()] [void]テスト実行テスト() { #処理の実行 $testCase = "単価`t12","個数`t34"; $result = $this.target.テスト実行($testCase); #出力されたログの内容を確認 $lines = Get-Content $this.target.LogFilePath -Encoding UTF8 $this.AssertEquals('NumericUpDown[単価]値[12]セット', $lines[0] ); $this.AssertEquals('NumericUpDown[個数]値[34]セット', $lines[1] ); $this.AssertEquals('計算実行', $lines[2] ); $this.AssertEquals('計算結果:金額=[408 円]', $lines[3] ); } } $error.Clear() [void](([CalcRunnerTest]::new()).RunTest()); #以下省略 テスト対象の CalcRunner クラス ログファイルを削除 テストケース単位で初期状態にするために 結果の確認 テストコードを文字列の配列で設定 運用時は、テキストファイルから読み込む 「計算実行」呼び出して、結果を確認 最終的に呼び出される「テスト実行」のテスト
  • 19.
    16 Step 12 課題3:CalcRunnerの作成 ① CalcRunnerTest.ps1 で使用するの作業手順 1. 実行しないテストメソッドの属性「[Test()]」をコメントアウトします。 「CalcRunnerTest.ps1」ファイルを開き、下記の部分をコメントアウト(先頭に#を記述)しま す。 [Test()] [void]計算実行テスト() 中略 [Test()] [void]テスト実行テスト() ② テストの実行 run.bat を実行します。 [1]NG:結果取得テスト + AssertEquals Fail + Message : Test failed. + Expected: 計算結果:金額=[円] + Actual : Result:NG=1:OK=0 と表示されればテスト実行は成功です。(テストは失敗です。) ③ 結果取得メソッドの作成 1. テストメソッド。 最初は計算ではなく、状態(初期状態)を取得するテストです。 $this.target がランナークラスのインスタンスです。このインスタンスの結果取得メソッドを呼び出します。 その後、取得結果を AssertEquals で予想結果と実行結果を比較することで確認します。 [Test()] [void]結果取得テスト() { $result = $this.target.結果取得(); $this.AssertEquals('計算結果:金額=[円]', $result ); } 2. 「CalcRunner.psm1」に正しいコードを実装します。 $this.GetText(ID)を使って文字列を取得します。金額コントロールの ID は、「金額」です。 次に、結果の文字列を成型します。 ヒント:PowerShell では、文字列に続けて –F を記述することで、文字列の成型ができます。 $金額 = $this.GetText("金額"); $result = "計算結果:金額=[{0}]" -F $金額; return $result; 3. run.bat でテストを実行します。 以下のように表示されれば、実行は成功です。 [1]OK:結果取得テスト Result:OK=1
  • 20.
    17 ④ 計算処理メソッドの作成 計算を実行するメソッドを作成します。 1. テストメソッド テストランナーの値を設定するメソッドを呼び出し、コントロールに値を設定します。 コントロールの値は、「コントロールのID+タブ+値」形式の文字列配列で指定し、SetKeywordValues メソッドを呼び出すことで設定することができます。 その後、計算実行メソッドを呼び出します。 最後に結果を取得して、動作の判定を行います。 属性のコメントを削除します。 [Test()] [void]計算実行テスト() { #値を設定 $testCase = "単価`t2","個数`t3"; $this.target.SetKeywordValues($testCase); #計算を実行 $this.target.計算実行(); #計算結果を確認 $result = $this.target.結果取得(); $this.AssertEquals('計算結果:金額=[6 円]', $result ); } 2. run.bat でテストを実行します。 一件成功、一件失敗すれば、実行は正しく失敗しています。このとき、テスト対象のプログラムには、値 がセットされています。 [1]OK:結果取得テスト [2]NG:計算実行テスト 3. 正しい計算実行メソッドを作成します。 Invoke(ID)メソッドを使って、処理の実行を行います。計算ボタンの ID は「計算」です。 [void]計算実行() { $this.Invoke("計算"); } 4. run.bat でテストを実行します。 以下のように表示されれば、実行は成功です。 [1]OK:結果取得テスト [2]OK:計算実行テスト Result:OK=2
  • 21.
    18 ⑤ テスト実行メソッドの作成 1. テストを実行するテストメソッド コントロールの値を「コントロールのID+タブ+値」の配列で指定し、テスト実行メソッドを呼び出します。 その後、結果と出力されるログを確認して動作の判定を行います。 [Test()] [void]テスト実行テスト() { #処理の実行 $testCase = "単価`t12","個数`t34"; $result = $this.target.テスト実行($testCase); #出力されたログの内容を確認 $lines = Get-Content $this.target.LogFilePath -Encoding UTF8 $this.AssertEquals('NumericUpDown[単価]値[12]セット', $lines[0] ); $this.AssertEquals('NumericUpDown[個数]値[34]セット', $lines[1] ); $this.AssertEquals('計算実行', $lines[2] ); $this.AssertEquals('計算結果:金額=[408 円]', $lines[3] ); } 2. run.bat でテストを実行します。 二件成功、一件失敗すれば、実行は正しく失敗しています。 [1]OK:結果取得テスト [2]OK:計算実行テスト <<省略>> [3]NG:テスト実行テスト Result:NG=1:OK=2 3. 正しいテスト実行メソッドを作成します。 仮コードを削除し正しい処理を実装します。値の設定/計算の実行/結果の取得を順次呼び出します。 #キーワードで値を設定 $this.SetKeywordValues($testCase); #計算の実行 $this.計算実行(); #結果取得 return $this.結果取得(); 4. ログ出力を実装します。 テ ス ト 実 行 を 実 装 し て も 、 エ ラ ー が 発 生 し ま す 。 ロ グ 出 力 の 実 行 を 行 い ま す 。 ロ グ は 、 $this.WriteLog(ログ)で出力できます。実行して、「Result:OK=3」が表示されれば成功です。 [string]結果取得() { #省略 $this.WriteLog($result); return $result; } [void]計算実行() { $this.WriteLog("計算実行"); $this.Invoke("計算"); }
  • 22.
    19 ⑥ テストランナーの完成形(CalcRunner.psm1) class CalcRunner: STAR.RunnerFramework.RunnerBase { CalcRunner(){ $this.WaitFlag = $true; $this.WaitTime = 100; } [string]結果取得() { #結果取得 $金額 = $this.GetText("金額"); $result = "計算結果:金額=[{0}]" -F $金額; $this.WriteLog($result); return $result; } [void]計算実行() { #計算の実行 $this.WriteLog("計算実行"); $this.Invoke("計算"); } [string]テスト実行([string[]]$testCase) { #キーワードで値を設定 $this.SetKeywordValues($testCase); #計算の実行 $this.計算実行(); #結果取得 return $this.結果取得(); } } ⑦ テストコードの例 「CalcRunner.psm1」を使用した、テストコードは以下のようになります。 #Runner=CalcRunner 単価 2 個数 3 以前のテストコードとの違いで気がついがことを記入してください。
  • 23.
    20 運用スクリプトおよび環境構築 Step 1 運用スクリプトの機能 今回の運用スクリプトでは、以下の機能を実現します。 1.テスト結果用のフォルダの準備 実行単位で異なるフォルダを作成します。フォルダ名は、実行を開始した日時を基に作成します。 2. テストセットの実行 指定されたテストセットを順次実行します。テストセット単位に、テスト結果としてのログをテストセット名 で出力します。 3. テスト結果の判定 準備された予想結果のログファイルと比較し、テストセット単位で判定を行います。 実際の自動テストでは、要求される機能は異なります。 Step 2 実行環境のフォルダ構成 今回の実行環境のフォルダは、以下の通りです。また、テストセットのルートフォルダ配下に、テスト セットごとにサブフォルダを作成します。このフォルダ内に、テストケースごとに一つのテストコード ファイルを作成します。 Step 3 処理の流れとフォルダの役割 テストの実行は、RunTest.ps1 で行います。以下の手順でテストが実行されます。
  • 24.
    21 Step 4 課題4:テストセットの追加作成 テストセットは、一つ以上のテストコード(テストケース)を持ちます。テストセットは以下の手順で 作成します。 ①テストセットフォルダの作成 テストセットのルートフォルダ配下に、「ID.テストセット名」でサブフォルダを作成します。 今回は、04.TestSet フォルダ配下に「01.金額計算基本テスト」を作成します。 ② テストコードの作成 テストケース単位に、テストコードをテキストファイルで作成します。ファイル名は、テストケース名となるので、 テストの目的をファイル名とします。テストコードは、「ID タブ 値」の形式で作成します。#から始まる行は、 コメント行となります。最初の行のコメントだけは特別な意味を持ち、テストランナーを「Runner=テストランナ ー名」の形で指定します。以下は、テストコードの例です。これを例に、テストコードを作成して下さい。 1. 01.最小値計算.txt #Runner=CalcRunner 単価 1 個数 1 2. 02.最大値計算.txt #Runner=CalcRunner 単価 1000 個数 1000 3. 03.三桁結果.txt #Runner=CalcRunner 単価 10 個数 99 ③ テストケースの実行 テスト運用スクリプトフォルダ(03.AutoScript)内の RunTest.bat を実行して、テストセットの実行を行いま す。 この時、「C:¥KeywordAutoTest¥02.AutoTest¥03.AutoScript」フォルダの「TestList.txt」内のテストセ ットの一覧で実行対象にします。(先頭に#があるテストセットは対象外となります) 00.キーワードサンプル 01.金額計算基本テスト #02.消費税ありテスト #03.消費税複数テスト 以下のダイアログボックスが表示されれば、テストセットの実行は成功です。
  • 25.
    22 Step 5 テスト運用スクリプト テスト運用スクリプトは、以下の機能を持ちます。 1.テストセットの選択 実行するテストセットは、「TestList.txt」ファイル内に記述します。先頭の#をつけるとコメント扱いとなり、 実行対象から除外されます。 2. テストセットの実行 テストセットを実行します。テストセットフォルダに含まれる、テストコードを読み込み、指定されているラ ンナーを利用して、実行します。 3. テスト結果の判定 実行で作成作成されたログファイルと成功時に想定したログファイルを比較して、テストの判定を行い ます。 using module ..¥02.Runner.ps¥CalcRunner.psd1 using module ..¥02.Runner.ps¥CalcRunner.psm1 function Main() { $Error.Clear(); Add-Type -Assembly System.Windows.Forms #各種設定 $currentPath = Get-Location $target = '{0}¥..¥01.TestTarget¥CalcApp.exe' -F $currentPath $testSetRoot = '{0}¥..¥04.TestSet¥' -F $currentPath $testExpectedRoot = '{0}¥..¥05.TestExpected¥' -F $currentPath $resultRoot='{0}¥..¥06.TestResult¥{1}¥' -f $currentPath,( [System.DateTime]::Now.ToString('yyyyMMdd_HHmmss') ) [void](New-Item $resultRoot -ItemType Directory) #テストセットの一覧を読み込む $testSetList = @(Get-Content '.¥TestList.txt' -Encoding UTF8) $errorFlag = $false #テストセットの実行処理 $testSetCount = 0 ForEach( $testSet in $testSetList ) { # #から始まる行はコメントとして処理しない if( ( $testSet -ne '' ) -and ( $testSet.SubString(0,1) -ne '#' )) { $testSetPath = $testSetRoot + $testSet $testLogPath = $resultRoot + $testSet + '.log' [void]( RunTestSet $testSetPath $testLogPath ) $result = CheckLog $testExpectedRoot $testLogPath if( $result -ne $null ) { $errorFlag = $true [System.Windows.Forms.MessageBox]::Show( ( "テストエラー[{0}]`n{1}" -f $testSet,$result), "エラー" ) } $testSetCount++ } } if( $errorFlag -eq $false ) { [System.Windows.Forms.MessageBox]::Show( ('テスト成功 実行テストセット数[{0}]' -f $testSetCount ) , "成功" ) } } テストランナーの利用定義 各種フォルダの定義 テストセットの一覧を読み込む義 テストセットの実行 先頭が#は除外 テストセットの結果比較
  • 26.
    23 function RunTestSet([string] $testSetPath,[string]$testLogPath ) { $testCaseList = @(Get-ChildItem $testSetPath) ForEach( $testCase in $testCaseList ) { if($testCase.Extension.ToUpper() -ne ".TXT") { continue; } $testKeyValue = @(Get-Content $testCase.FullName -Encoding UTF8) $index = $testKeyValue[0].IndexOf('#Runner=') if( $index -eq -1 ) { continue; } $runnerName = $testKeyValue[0].SubString(($index+8) ); $testRunner = $null if( $runnerName -eq 'CalcRunner' ) { $testRunner = [CalcRunner]::new(); } if( $testRunner -eq $null ) { continue; } $testRunner.TargetPath = $target; $testRunner.LogFilePath = $testLogPath; $testRunner.WriteLog( ( "※※※テストケース[{0}]※※※" -F $testCase.Name ) ); $testRunner.SetUp(); $testRunner.テスト実行( $testKeyValue ); $testRunner.TearDown(); } } function CheckLog([string] $testExpectedRoot, [string]$testLogPath, [string]$msg ) { $result = $null $logFileInfo = [System.IO.FileInfo]::new( $testLogPath ) $testExpectedFilePath = '{0}{1}' -f $testExpectedRoot,$logFileInfo.Name $logLines = @(Get-Content $testLogPath -Encoding UTF8) $expectedLines = @(Get-Content $testExpectedFilePath -Encoding UTF8) if( $logLines.Length -eq $expectedLines.Length ) { $result = $null For( $i=0;$i -lt $logLines.Length; $i++ ) { if( $logLines[$i] -ne $expectedLines[$i] ) { $result = "NG`t[{0}]`nEx`t[{1}]" -f $logLines[$i],$expectedLines[$i] break } } } else { $result = "NG 行数違い"; } return $result } main テストコード一覧の取得 テストランナーの識別 テストコードの実行 内容比較 読み込み 行数比較 テストケース名をログに出力
  • 27.
    24 Step 6 テストの予想結果 今回は、テストの成功時の予想結果をテキストファイルで用意します。最初から作成するのが難しい場 合、成功時の実行結果のログを予想結果とします。テストの予想結果フォルダ「05.TestExpected」内 に、テストセット単位に用意します。 例 1.01.金額計算基本テスト.log ※※※テストケース[01.最小値計算.txt]※※※ NumericUpDown[単価]値[1]セット NumericUpDown[個数]値[1]セット 計算実行 計算結果:金額=[1 円] ※※※テストケース[02.最大値計算.txt]※※※ NumericUpDown[単価]値[1000]セット NumericUpDown[個数]値[1000]セット 計算実行 計算結果:金額=[1,000,000 円] ※※※テストケース[03.三桁結果.txt]※※※ NumericUpDown[単価]値[10]セット NumericUpDown[個数]値[99]セット 計算実行 計算結果:金額=[990 円] Step 7 テストセットの追加手順 テストセットを追加する手順は、以下の通りです。 ① テストの目的と内容を決定 追加するテストセットの目的とテストセットに含まれるテストケースについて、その名前と内容を決定します。 ② テストセットフォルダの作成 ③ テストコードの作成 テストセットフォルダ内に、テストケースを元にテストコードを作成します。 ④ テストセット一覧へ追加 テスト運用スクリプトフォルダ内の、「TestList.txt」にテストセットを追加します。 ⑤ テストセットの実行 テストセットを実行します。このとき、まだ予測結果がないため、エラーとなります。テスト結果フォルダ 「06.TestResult」内にできたログファイルを確認し、正常に動作したことを確認します。 ⑥ 予想結果 正常に実行されたときに作成されたログファイルを成功時の予想結果とします。作成されたログファイルを 予想結果フォルダにコピーします。 ⑦ テストセットの再実行 テストセットを再実行し、テストが成功することを確認します。
  • 28.
    25 テスト対象の変更対応 Step 1 テスト対象の仕様変更 金額計算に消費税を考慮した計算ができる機能が追加されました。 Step2 課題6:既存テストの対応とテストセットの追加 ① 既存テストの対応 対象プログラムを変更して、既存のテストを実行して見ましょう。変更なく、そのまま動作します。 ② テストセットの追加 消費税を考慮したテストセットを追加しましょう。テストセット名は「02.消費税ありテスト」とします。消費税の 値を変更するためのキーワードは、消費税で、値は「パーセント 8」「パーセント 10」「内税」です。下記は、8 パーセントの計算を行うテストコードです。テストセット「02.消費税ありテスト」を追加し、実行して見ましょう。 1. 01.消費性 8 パーセント計算.txt #Runner=CalcRunner 単価 100 個数 2 消費税 パーセント 8 ③ 対応理由 今回の変更に対して、容易に対応できた理由を書いてください。
  • 29.
    26 テストランナーの追加 Step 1 全ての消費税を変更して計算するランナーの作成 消費税の選択肢をテストコード内に記載することもできますが、ランナー側で消費税の選択と金額計算 を行わせることもできます。「TaxCalcRunner」を作成して見ましょう。 ①ユニットテストの作成「TaxCalcRunnerTest.ps1」 using module .¥TaxCalcRunner.psd1 using module .¥Lib¥UnitTest.psm1 using module .¥CalcRunner.psm1 using module .¥TaxCalcRunner.psm1 class TaxCalcRunnerTest : TestBase { [SetUp()] [void]SetUp() { $this.target = [TaxCalcRunner]::new(); $this.target.TargetPath = 'C:¥KeywordAutoTest¥02.AutoTest¥01.TestTarget¥CalcApp.exe'; $this.target.LogFilePath = 'C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥Test.log'; Remove-item $this.target.LogFilePath -Force -ErrorAction Ignore $this.target.SetUp(); } [TearDown()] [void]TearDown() { $this.target.TearDown(); } [Test()] [void]消費税計算テスト() { #処理の実行 $testCase = "単価`t100","個数`t2"; $result = $this.target.テスト実行($testCase); $this.AssertEquals('計算結果:金額=[216 円]計算結果:金額=[220 円]計算結果:金額=[200 円]', $result ); #出力されたログの内容を確認 $lines = Get-Content $this.target.LogFilePath -Encoding UTF8 $this.AssertEquals('NumericUpDown[単価]値[100]セット', $lines[0] ); $this.AssertEquals('NumericUpDown[個数]値[2]セット', $lines[1] ); $this.AssertEquals('GroupBox[パーセント 8]をチェック', $lines[2] ); $this.AssertEquals('計算実行', $lines[3] ); $this.AssertEquals('計算結果:金額=[216 円]', $lines[4] ); $this.AssertEquals('GroupBox[パーセント 10]をチェック', $lines[5] ); $this.AssertEquals('計算実行', $lines[6] ); $this.AssertEquals('計算結果:金額=[220 円]', $lines[7] ); $this.AssertEquals('GroupBox[内税]をチェック', $lines[8] ); $this.AssertEquals('計算実行', $lines[9] ); $this.AssertEquals('計算結果:金額=[200 円]', $lines[10]); } } $error.Clear() [void](([TaxCalcRunnerTest]::new()).RunTest()); #スクリプトのエラー処理は、ここで行う必要がある #以下は同じ TaxCalcRunner のテストクラス TaxCalcRunner の生成 消費税テスト 一度の実行で、内税、8%、10%で計算 計算は、8%、10%、内税の順番で計算
  • 30.
    27 ② 最初の TaxCalcRunner TaxCalcRunnerは CalcRunner を継承して実装します。実行するバッチファイル「taxRun.bat」を作成し て、テストを実行します。 using module .¥CalcRunner.psm1 class TaxCalcRunner : CalcRunner { TaxCalcRunner(){ } [string]テスト実行([string[]]$testCase) { return ""; } } ③ 最終的な TaxCalcRunner 値の設定、計算の実行を消費税のパターン数実行します。 using module .¥CalcRunner.psm1 class TaxCalcRunner : CalcRunner { TaxCalcRunner(){ } [string]テスト実行([string[]]$testCase) { #キーワードで値を設定 $this.SetKeywordValues($testCase); $values = 'パーセント 8', 'パーセント 10', '内税' $result = '' foreach($value in $values) { $this.SetValue('消費税',$value) #計算の実行 $this.計算実行(); $result += $this.結果取得(); } #結果取得 return $result; } } ④ taxRun.bat CD C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps %SystemRoot%¥syswow64¥WindowsPowerShell¥v1.0¥powershell.exe C:¥KeywordAutoTest¥02.AutoTest¥02.Runner.ps¥TaxCalcRunnerTest.ps1 pause 計算は、8%、10%、内税の順番で計算 ループで、値の設定と計算を実行
  • 31.
    28 Step 2 実行スクリプトへの追加 実行スクリプトに、新しいテストランナーを追加します。 ①利用モジュールの追加 using module ..¥02.Runner.ps¥CalcRunner.psd1 using module ..¥02.Runner.ps¥SimpleRunner.psd1 using module ..¥02.Runner.ps¥TaxCalcRunner.psd1 using module ..¥02.Runner.ps¥CalcRunner.psm1 using module ..¥02.Runner.ps¥SimpleRunner.psm1 using module ..¥02.Runner.ps¥TaxCalcRunner.psm1 ② テストランナー生成部分の変更 $runnerName = $testKeyValue[0].SubString(($index+8) ); $testRunner = $null if( $runnerName -eq 'CalcRunner' ) { $testRunner = [CalcRunner]::new(); } elseif( $runnerName -eq 'SimpleRunner' ) { $testRunner = [SimpleRunner]::new(); } elseif( $runnerName -eq 'TaxCalcRunner' ) { $testRunner = [TaxCalcRunner]::new(); } Step 3 テストセットの追加 新しいテストランナーを使用したテストセット「03.消費税複数テスト」を作成します。 テストコード(01.消費税計算.txt)は、以下の通りです。 #Runner=TaxCalcRunner 単価 100 個数 2 テストセットを実行して見ましょう。 Step 4 新テストランナーの利点 新しいテストランナーは、CalcRunner と比較したときの利点を書いてください。 新しいテストランナーを生成 新しいテストランナーを 指定
  • 32.
    29 テスト対象の変更対応 メッセージボックス Step 1テスト対象の仕様変更 消費税で 10 パーセントを選択したときに、確認のメッセージボックスが表示される機能が追加されま した。メッセージボックスの「はい」を選択すると 10 パーセントに変更され、「いいえ」が選択される と元の状態となり、10 パーセントの設定になりません。 Step 2 課題7:キーワードの機能追加 値の設定は、「消費税△パーセント 10」(△は区切り文字)という形式(ルール)でした。今回の機能変更に 合わせて、メッセージボックスを操作するキーワードを追加する必要があります。 どの様な形式を追加するのが良いか書いて下さい。 注意点、キーワードによる値のセットは、同期処理(対象プログラムの処理が終わってから、次のキーワード を処理する)でした。メッセージボックスは、値のセットの処理内で行われるため通常の値セットと異なること を明示する必要があります。
  • 33.
    30 システムテスト自動化のアーキテクチャ 自動テストはシステムです。したがって、統一された品質を達成するためには、システムとして求めら れる品質特性と対象(ステークホルダ)を定義することが必要です。 Step 1 システムアーキテクチャ ①システムアーキテクチャとは システムの構造や構造化の原則です。 ② システムアーキテクチャの目的 システムの品質特性を強制(支配)する構造を構築することです。 Step 2 システムテスト自動化のアーキテクチャ 自動テストには、テスト対象のシステムと自動テストシステムの二つがあります。したがって、システ ムテスト自動化の目的を達成するためには、二つのシステムに対して自動テストに関するシステムアー キテクチャを定義する必要があります。 ① 「テスト対象システム」に対する品質特性 1. 操作性(実行性) 自動テストのプログラムから対象のプログラムを実行し、制御できること。 2. 確認性 対象のプログラムを実行した結果が正確に確認できること。 3. 再現性 テストを行う特定の状況を再現できること。 ② 「テストコード(スクリプト)」に関する品質特性 1. 理解性 読みやすく理解しやすいこと。 容易に作成することができること。 できるだけ多くのメンバーが作成できること。 2. 効率性 多様で効果的なテストコード(スクリプト)を適切なコストで作成できること。 3. 保守性 テスト対象の変更に素早く対応できること。 変更が容易であること。 4. 拡張性 機能を必要に応じて拡張できること。
  • 34.
    31 ③ 「自動テストの実行」に関する品質特性 1. 安定性 自動テストを安定して実行できること。 同じテストを何度でも安定して実行できること。 2.信頼性 テスト結果の判定が信頼できること。 ④ 「自動テストの運用」に関する品質特性 1. 効率性 必要な自動テストを効率的に運用することができること。 2. 柔軟性 状況に合わせて、柔軟な運用ができること。 3. 障害許容性 対象のプログラムで予測しないエラーが発生しても、他のテストスクリプトが継続的に実行できること。 4. 並列性 複数の環境で効率的にテストを並列して実行できること。
  • 35.
    32 Step 3 アーキテクチャ定義の例 ①指針 1. テスト対象システム テスト容易性 自動テストを考慮した設計と実装を行うこと。 2. テストコード(スクリプト)の作成 効率性 テストスクリプトはプログラミング技術を持たないメンバーでも作成可能とすること。 システムが変更されてもテストコード(スクリプト)の変更を最低限とすること。 理解性 テストコードは、意味が分かる単語で記述可能とすること。 3. 自動テストの実行 効率性 自動テストで問題が発生した時、効率的に問題箇所を特定できること。 4. 自動テストの運用 効率性 必要なテストセットを選択して実行することができること。 ② ルール 1. テスト対象システム コントロールにドメインの名詞を name プロパティに設定すること。 2. テストコード(スクリプト)の作成 ユースシナリオのグループ単位に、Runner クラスを作成すること。 Runner クラスは、動作と情報の取得を行い、結果判定は行わないこと。 Runner クラスは、共通操作と結果取得を行うこと。 Runner クラスは、PowerShell のクラスで作成すること。 Friendly は、RunnerBase クラス(C#)のみで利用すること。 個別のテストコードは、キーワード駆動によるテキストファイルで記述すること。 3. 自動テストの実行 実行結果は、テキストファイルとすること。 テストの実行履歴をログファイルに出力すること。 ひとつのテストセット(複数のテストスクリプト)の実行は、5分以内とすること。 4. 自動テストの運用 実行するテストセットを選択することができるようにすること。 結果判定は、正常時の結果と実行時の結果を比較して行うこと。
  • 36.
    33 補足資料 PowerShell 5 のインストール Windows10 に標準搭載さてた PowerShell 5 は、Windows Management Framework 5.0 に含まれた 形で提供されます。したがって、他の OS で利用するために Windows Management Framework 5.0 を インストールする必要あります。 1. 入手:Windows Management Framework 5.0 https://www.microsoft.com/en-us/download/details.aspx?id=50395 また、PowerShell でスクリプトを作成する場合、実行ポリシーを変更することをお勧めします。 Set-ExecutionPolicy Remotesigned ブロック解除コマンド インターネットからダウンロードしたファイルを使用するとき、セキュリティエラーが発生することが あります。エラーを回避するためには、ファイルに書き込まれている ZoneId と呼ばれる代替データス トリームをリセットする必要があります。ZoneId をリセットするには、ファイルのプロパティから「ブ ロックの解除」を実行します。 複数のファイルを一括で行いたい場合、Streams コマンドを使います。以下は実行例です。 streams.exe -s -d C:¥KeywordAutoTest 2. 入手:Streams https://technet.microsoft.com/ja-jp/sysinternals/bb897440?f=255&MSPPError=-2147217396 3. 情報:streams コマンドで NTFS の代替データ・ストリーム情報を表示/削除する http://www.atmarkit.co.jp/fwin2k/win2ktips/1363streams/streams.html RunnerBase 解説 RunnerBase のキーワード駆動機能は、Codeer.Friendly を使用して作成しています。RunnerBase は、 主に以下の機能を提供しています。 ① Process の管理 LaunchTarget メソッド内で、Process クラスを使用して、プロセスを起動し、プロセスを操作します。また、 起動したプロセス内のFormを操作します。操作を行うために、WindowsAppFriendのインスタンスを作成 します。下記のコードで、「t_」が接頭辞となっているものは、起動したプロセスを操作するための変数です。 Runner 側で、プロキシ(Proxy)となります。下記のコードは、プロセスを起動し、ウィンドウをアクティブにす る部分です。 public void LaunchTarget() { _process = Process.Start(this.TargetPath); SetUpProcess(); } private void SetUpProcess() { _controlInfoList = new List<ControlInfo>(); t_app = new WindowsAppFriend(_process); t_mainForm = t_app.Type<Application>().OpenForms[0]; t_mainForm.Activate(); }
  • 37.
    34 ② コントロールの管理と操作 ウィンドウが持っているコントロールを操作します。下記のコードは、操作するためにコントロールの一覧を作 成しています。この一覧を利用して、コントロールに値を設定したり、値を取得したりします。また、ボタンで あれば、クリックの動作を実行します。 public intSetUpControls() { int count = t_mainForm.Controls.Count; ControlInfo newInfo; for (int i = 0; i < count; ++i) { dynamic tName = t_mainForm.Controls[i].Name; dynamic tControlType = t_mainForm.Controls[i].GetType(); dynamic tTabIndex = t_mainForm.Controls[i].TabIndex; newInfo = new ControlInfo(); newInfo.Name = tName.ToString(); newInfo.TabIndex = (int)tTabIndex; ③ キーワード駆動機能 キーワードを含むテキストの配列を受け取り、上記の機能を利用して、各コントロールを操作します。 下記のコードは、キーワードで振り分けを行い処理を実行する部分の一部です。 public void SetKeywordValues(string[] values) { foreach(string value in values) { //文字列の先頭が[#]の場合は、コメント扱いとして処理しない if(string.IsNullOrWhiteSpace(value) == false && value.Substring(0,1) != "#" ) { string[] parts = value.Split('¥t'); if ( parts.Length >= 2) { if (parts.Length >= 3 && parts[2].ToUpper().Trim() == "CLICK") { Invoke(parts[0]); }
  • 38.
    35 ④ 非同期処理 操作によってメッセージボックスが表示される場合などは、非同期処理を行う必要があります。 下記のコードでは、Async を使って非同期で処理を実行し、WaitForCompletionで非同期処理の終了を 待っています。 public void SetValueAndMessageBox(string controlName, string value, string button) { int index = GetControlIndex(controlName); ControlInfo info = _controlInfoList[index]; (t_mainForm.Controls[index]).Focus(); TakeWait(); if (info.Category == ControlInfo.ControlCategory.GroupBox) { dynamic tRadioButtonList = t_mainForm.Controls[index].Controls; int count = tRadioButtonList.Count; for (int i = 0; i < count; ++i) { dynamic tRadioButton = tRadioButtonList[i]; string name = tRadioButton.Name; if (name == value) { var async1 = new Async(); WriteLog(String.Format("GroupBox[{0}]をチェック", name)); tRadioButton.Checked(true,async1); TakeWait(); WriteLog(String.Format("Messagebox の[{0}]を押下", button)); CloseMessagebox(button); async1.WaitForCompletion(); break; } } } } private void CloseMessagebox(string button) { WindowControl dlg = WindowControl.FromZTop(t_app); ; var msgBox = new NativeMessageBox(dlg); msgBox.EmulateButtonClick(button); }