←
▼
▲
Sub T_Test1( Opt, AppKey )
Dim x
Dim xx : Set xx = ReadTestCase( "T_Test1_Data.xml", Empty ) '// xx as <TestCases>
Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
For Each x In cases.Items
Dic_add x, xx
T_Test1_main Opt, AppKey, x
Next
Pass
End Sub
'// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする
Sub T_Test1_main( Opt, AppKey, x )
echo x
FuncA CInt( x("InputData") )
FuncB x("CommonData1")
End Sub
T_Test1_Data.xml
<?xml version="1.0" encoding="UTF-8"?>
<TestCases
CommonData1 = "Sample.exe"
>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="Number"
InputData = "123"
Answer = "ans%Num%.txt" _comment2= "FilePath with variable"
/>
<SubCase name="Alphabet"
InputData = "ABC"
Answer = "ans2.txt"
/>
</TestCase>
</TestCases>
CommonData1
TestCases
CommonData1
複数のテストケースで共通のデータを、XML ファイルの TestCases タグの属性からリードするときは、
ReadTestCase の第2引数を Empty に指定してください。
サンプル XML ファイル: T_Test1_Data.xml
Empty
T_Test1
T_Test1
T_Test1
複数のテスト・プログラムで共通のデータは、親フォルダーにある共通の XML ファイルからリードして
ください。
Set xx = ReadTestCase( SearchParent("TestCommon_Data.xml"), Empty ) '// xx as <TestCases>
←
▼
▲
ReadTestCase がリードする XML ファイルは、データの記述が冗長にならないように、データの継承や集約
ができる特殊な XML が使えます。
XML 属性を継承します
継承した XML 属性は CSV 形式で追加します
子の XML 要素を集約します
<!ELEMENT TestCases (TestCase*)>
<!ELEMENT TestCase (SubCase*)>
<!ATTLIST TestCases
* CDATA #IMPLIED
name ID #IMPLIED
base_data IDREFS #IMPLIED
plus_attr NMTOKENS #IMPLIED
>
<!ATTLIST TestCase
* CDATA #IMPLIED
id ID #REQUIRED
base_data IDREFS #IMPLIED
plus_attr NMTOKENS #IMPLIED
aggregate IDREFS #IMPLIED
>
<!ATTLIST SubCase
* CDATA #IMPLIED
name ID #IMPLIED
base_data IDREFS #IMPLIED
plus_attr NMTOKENS #IMPLIED
>
テストデータを記述する XML ファイルの DTD
←
▼
▲
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="Number" InputData = "123" base_data="#T_Test1_Common"/>
<SubCase name="Alphabet" InputData = "ABC" base_data="#T_Test1_Common"/>
<SubCase name="AlphaNum" InputData = "1AB" Answer="ans2.txt"/>
</TestCase>
<TestCase id="TestCase_for_T_Test1_Common">
<SubCase name="T_Test1_Common" Answer="ans1.txt"/>
</TestCase>
</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
データの多くは共通で、一部のデータだけ変えるときは、base_data 属性を使って属性を継承することが
できます。 base_data 属性は、A タグの href 属性と同じ記述形式です。 別のファイルから継承する
こともできます。
T_Test1_Common
T_Test1_Common
T_Test1_Common
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="Number" InputData = "123" Answer="ans1.txt"/>
<SubCase name="Alphabet" InputData = "ABC" Answer="ans1.txt"/>
<SubCase name="AlphaNum" InputData = "1AB" Answer="ans2.txt"/>
</TestCase>
</TestCases>
上のファイルと下のファイルは、同じデータになります。
Answer="ans1.txt"
Answer="ans1.txt"
ファイルパスに、ピリオドを3つ並べると、親フォルダー、親の親フォルダー … と探していきます。
参考
テスト
→ T_TestCaseData.vbs # [T_BaseTestCaseData]
→ T_TestCaseData.xml # T_BaseTestCaseData_1 など
←
▼
▲
CSV 形式のデータを、別のタグから追加するときは、plus_attr 属性を使います。
plus_attr 属性の値は、属性の値を CSV 形式で並べます。
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="a" InputDataA="123" InputDataB="123"
base_data="#T_Test1_Common" plus_attr="InputDataA"/>
</TestCase>
<TestCase id="TestCase_for_T_Test1_Common">
<SubCase name="T_Test1_Common" InputDataB="ABC" InputDataB="ABC"/>
</TestCase>
</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
InputDataA
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="a" InputDataA="123, ABC" InputDataB="123"/>
</TestCase>
</TestCases>
上のファイルと下のファイルは、同じデータになります。
InputDataA
テスト
→ T_TestCaseData.vbs # [T_BaseTestCaseData]
→ T_TestCaseData2.xml # T_BaseTestCaseData_22 など
InputDataA
←
▼
▲
TestCase タグの子の SubCase タグに、別の TestCase タグの子を追加するときは、
aggregate 属性を使います。
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1" aggregate="#TestCase_Common">
<SubCase name="a" InputDataA="123" InputDataB="123"/>
</TestCase>
<TestCase id="TestCase_for_T_Test2" aggregate="#TestCase_Common">
<SubCase name="b" InputDataA="123" InputDataB="ABC"/>
</TestCase>
<TestCase id="TestCase_Common">
<SubCase name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>
</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="a" InputDataA="123" InputDataB="123"/>
<SubCase name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>
<TestCase id="TestCase_for_T_Test2">
<SubCase name="b" InputDataA="123" InputDataB="ABC"/>
<SubCase name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>
</TestCases>
上のファイルと下のファイルは、同じデータになります。
TestCase_Common
TestCase_Common
TestCase_Common
テスト
→ T_TestCaseData.vbs # [T_BaseTestCaseData]
→ T_TestCaseData.xml # T_AggregateTestCaseData_1 など
SubCase
SubCase
SubCase
←
▼
▲
Sub T_Test1( Opt, AppKey )
Dim x, y, mix
Dim cases_x : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_x" )
Dim cases_y : Set cases_y = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_y" )
Set mix = CreateObject( "Scripting.Dictionary" )
For Each y In cases_y.Items
For Each x In cases_x.Items
mix.RemoveAll : Dic_add mix, x : Dic_add mix, y
T_Test1_main Opt, AppKey, mix
Next
Next
Pass
End Sub
'// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする
Sub T_Test1_main( Opt, AppKey, x )
echo x
FuncA x("InputData"), ReadFile( x("CurrentFolder") +"\file.txt" )
End Sub
<?xml version="1.0" encoding="UTF-8"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1_x">
<SubCase name="Number"
InputData = "123"
Answer = "ans%Num%.txt" _comment2= "FilePath with variable"
/>
<SubCase name="Alphabet"
InputData = "ABC"
Answer = "ans2.txt"
/>
</TestCase>
<TestCase id="TestCase_for_T_Test1_y"> <!-- This is cross case -->
<SubCase name="CurrentFolder"
CurrentFolder = "."
StepPath = "Data\"
/>
<SubCase name="SubFolder"
CurrentFolder = "Data"
StepPath = ""
/>
</TestCase>
</TestCases>
InputData
CurrentFolder
サンプル XML ファイル: T_Test1_Data.xml
テストケースの値が、表の縦軸と横軸にあり、表の全てをテストする場合は、下記のように二重ループに
して、Dic_add を使ってテストデータを結合します。
T_Test1
T_Test1
T_Test1
Sub T_Test1( Opt, AppKey )
Set t = CreateObject( "Scripting.Dictionary" )
For Each endian In Array( "LittleEndian", "BigEndian" )
For Each language In Array( "VBScript", "C" )
t("Endian") = endian
t("Language") = language
T_Test1_Main t
Next
Next
Pass
End Sub
'// ループが増えてもインデントを深くさせないため、テストの実施は *_Main 関数にする
Sub T_Test1_Main( Opt, AppKey, x )
echo x
FuncA x("Endian"), x("Language")
End Sub
←
▼
▲
Sub T_Test1( Opt, AppKey )
Dim x
Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
Set x = cases.LookUpDic( "name", "Alphabet" )
T_Test1_main Opt, AppKey, x
Pass
End Sub
SubCase タグの中から、特定のタグだけ選択するときは、ArrayClass の LookUpDic を使ってください。
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="Number"
InputData = "123"
Answer = "ans%Num%.txt"
/>
<SubCase name="Alphabet"
InputData = "ABC"
Answer = "ans2.txt"
/>
</TestCase>
</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
"name", "Alphabet"
←
▼
▲
Sub T_Test1( Opt, AppKey )
Dim x, y
Dim cases : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
For Each x In cases_x.Items
For Each y In Array( 2, 3 )
x("y") = y
T_Test1_main Opt, AppKey, x
x.Remove "y"
Next
Next
Pass
End Sub
'// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする
Sub T_Test1_main( Opt, AppKey, x )
echo x
FuncA x("InputData"), ReadFile( x("y") +"\file.txt" )
End Sub
テストケースの値を XML ファイルではなく、スクリプトに埋め込む場合は、下記のように代入します。
x("y") = y
( 2, 3 )
T_Test1
T_Test1
T_Test1
x("y")
x.Remove "y"
←
▼
▲
C言語の標準ライブラリだけを使うときは、fgets を使った1行ずつ読み込むような単純なファイル・リード
しかできませんが、VBScript で XML などのデータを整理することで、C言語のプログラムに複雑な
動きをさせることができるようになります。
Test.vbs
C言語のプログラム
T_Test1.xml
TempParams.txt
Sub T_Test1_main( tests, x ) // x is from ReadTestCase
Dim f : Set f = OpenForWrite( "TempParams.txt", Empty )
f.WriteLine x("Param1") & " // Param1"
f = Empty
r= RunProg( "CLangProg.exe /TempParams:TempParams.txt", "" )
del "TempParams.txt"
vbs スクリプトのサンプル (Test.vbs)
int Params_read( Params* m, FILE* f );
int T_Sample()
{
int e;
errno_t et;
FILE* f = NULL;
TCHAR s[256];
TCHAR path[256];
//=== ReadTestCase
e= GetCommandLineNamed( _T("TempParams"), false, s, sizeof(s) ); IF(e)goto fin;
e= StrT_getFullPath( path, sizeof(path), s, NULL );
et= _tfopen_s( &f, path, _T("rt") ); IF(et)goto err_no;
e= Params_read( ¶ms, f ); IF(e)goto fin;
//=== Test Main
// Write here ...
e=0;
fin:
if(f!=NULL){ee= fclose( f ); IF(ee&&!e)e=E_Errno;}
}
int Params_read( Params* m, FILE* f )
{
int e;
int i;
TCHAR line[256];
line[0] = '\0';
_fgetts( line, _countof(line), f );
e= StrT_cutLineComment( line, sizeof(line), line, _T("//") ); IF(e)goto fin;
m->BufferSize = _ttoi( line );
_fgetts( line, _countof(line), f ); // skip space line
e=0;
fin:
return e;
}
C言語のテスト・プログラムのサンプル (CLangProg.exe)
StrT_cutLineComment
TempParams.txt ファイルの データ型の名前
テスト・データが複数のデータ構造を持つときは、データ構造を識別するシンボルを
TempParams.txt ファイルに記述する必要があります。
DataTypeA // データ型の名前
100 // DataTypeA の1つ目のデータ
200 // DataTypeA の2つ目のデータ
DataTypeB // データ型の名前
100 // DataTypeB の1つ目のデータ
200 // DataTypeB の2つ目のデータ
300 // DataTypeB の3つ目のデータ
TempParams.txt ファイルの フラグド構造体パラメーター
→ フラグド構造体パラメーター
参考
TempParams.txt ファイルの基本形
100 // 1つ目のテスト・ケースの1つ目のデータ
200 // 1つ目のテスト・ケースの2つ目のデータ
110 // 2つ目のテスト・ケースの1つ目のデータ
210 // 2つ目のテスト・ケースの2つ目のデータ
多くの場合、テスト・データを単純に並べていくだけで、テストを実施することはできるでしょう。
テスト・ケースが複数あるときは、空行で区切るとよいでしょう。
clib の StrT_cutLineComment 関数を使えば、コメントを入れることができます。
下記は、struct { int a; int b; } TestData[2]; という構造になります。
1つのテスト・ケースにおいて、それぞれのデータを使うかどうかを表すには、1つ目のデータを
ビットフィールドの数値として使い、ビットが1であれば対応するデータが記述されているように
します。
0x07 // ビットフィールド。 ビット0、1、2が1
100 // 1つ目のデータ
200 // 2つ目のデータ
300 // 3つ目のデータ
0x02 // ビットフィールド。 ビット1のみが1
200 // 2つ目のデータ
TempParams.txt
TempParams.txt
TempParams.txt
←
▼
▲
If IsEmpty( g_ReadTestCase ) Then Set g_ReadTestCase = new XmlObjReader
g_ReadTestCase.IsVerbose = True
Skipped
下記のように IsVerbose を True にすると、XML をリードする処理のステップを表示します。
←
▼
▲
Sub SetReadTestCase( XmlPath as string, TestCaseID as string, Condition as string )
デバッグ用に、テストケースを指定します。
【引数】
XmlPath
TestCaseID
テストケースが書かれた XML ファイルのパス
XML ファイルの中の <TestCase> タグの id 属性の値
Condition
テストケースを指定する条件文
TestScript.vbs
ファイル:
Sub T_Test1( Opt, AppKey )
Dim testcases, x
SetReadTestCase "T_Test1_Data.xml", "TestCase_for_T_Test1", "name='Alphabet'" : Skipped
Set x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
For Each x In testcases.Items '// x は、InputData="ABC" の1回ループのみになる
T_Test1_main Opt, AppKey, x
Next
Pass
End Sub
サンプル・コード:
<?xml version="1.0" encoding="UTF-8"?>
<TestCases>
<TestCase id="TestCase_for_T_Test1">
<SubCase name="Number"
InputData = "123"
Answer = "ans%Num%.txt" _comment2= "FilePath with variable"
/>
<SubCase name="Alphabet"
InputData = "ABC"
Answer = "ans2.txt"
/>
</TestCase>
</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
SetReadTestCase
を呼び出す前に、SetReadTestCase を呼び出すコードを追加すると、
ReadTestCase の返り値が、SetReadTestCase で指定した1つのケースだけになります。
(src)
テスト
→ T_TestCaseData.vbs # [T_SetReadTestCase]
←
▼
▲
Sub SetStartSectionTree( SectionNames as string )
実行するセクションを設定します。
【引数】
SectionNames
セクション名。 CSV形式
ファイル:
vbslib.vbs
SetStartSectionTree "Sec1"
サンプル
SetStartSectionTree "Sec1, SubSec2"
サンプル
Sec1 セクションの中の SubSec2 セクションから実行します。
Sec1 セクションから実行します。
テスト
→ T_SectionTree.vbs # [T_SectionTree_SetStart]
(src)
関連
→ T_SectionTree.vbs # [T_SectionTree_SetStart2]
→ T_SectionTree.vbs # [T_SectionTree_SetStart3]
→ T_SectionTree.vbs # [T_SectionTree_SetStartMiss]
←
▼
▲
Sub Pass
テストがパスしたことを、テストスクリプトに知らせて、プログラムを終了します。
(src)
内部的には、エラー 21 が発生します。
テスト
参考
→ T_SomeTests.vbs # T_TestReport
の T_SampA
←
▼
▲
Sub Fail
テストが失敗したことを、ユーザーやテストスクリプトに知らせて、プログラムを終了します。
エラーが発生したときと同じ動きをします。つまり、Fail の後は実行しません。
(src)
テスト
→ T_SomeTests.vbs # T_TestReport
の T_SampB
←
▼
▲
Sub Skip
テストが実行できる状況ではないことを、テストスクリプトに知らせて、プログラムを終了します。
エラーが発生したときと同じ動きをします。つまり、Skip の後は実行しないで、次のテストを実行します。
(src)
テスト
→ T_SomeTests.vbs # T_TestReport
の T_SampC
←
▼
▲
Sub Skipped
デバッグなどの理由で、テストの一部を一時的にスキップしたことを、テストスクリプトに
知らせます。 Skipped を呼んだテスト項目は、Pass を呼び出しても Fail します。
このときのエラーメッセージは、次のようになります。
(src)
Pass But Skipped. Cut calling "Skipped" function.
テスト
←
▼
▲
Sub ManualTest( TestSymbol as string )
テストが手動テストであることを、テストスクリプトに知らせます。
ManualTest tests.Symbol
サンプル
参考
(src)
手動テストは最低限にしてください。
ManualTest "T_Sample1"
参考