再利用コード
それを避ける方法はありません。繰り返しはテストにおいては人生の現実です。 Fortunately, there are several easy ways to let scripts and handlers do the repeating for you:
- Calling Scripts from Other Scripts
- Code Refactoring
- Handlers
- Helper Suites
- Cross-Platform Applications
- Testing Across Desktop and Mobile Devices
- Running from a Master Script
Calling Scripts from Other Scripts
コードを再利用する最も一般的な方法のひとつは、別のスクリプトからスクリプトを呼びだす事です。 スクリプトを呼ぶには、コード内にスクリプトの名前を挿入して、スクリプトに必要なパラメータをそれに続けます。 スクリプトの呼び出しは、スクリプト自身がコマンドあるいはファンクションであるかのように扱えます。 他のスクリプトを呼びだす事に関する詳細情報は、Running Other Scripts and Handlers(他のスクリプトとハンドラの実行)を参照してください。
以下はスクリプト内からスクリプトを呼ぶ例です。
CycleWindows // Calls a simple script name as a command
ConnectionScript "Old SUT", "New SUT" // Calls a simple script name with parameters
put CaptureTheScreen("SomePrefix",1) into myScreenCapture
// Calls a script as a function with parameters and puts the result in a variable
コマンド呼び出しを使うか、ファンクション呼び出しを使うかはスクリプト自身に依存します。 どちらのタイプも入力パラメータを取り、どの場合でも呼ばれたスクリプトはパラメータ宣言から始める必要があります。 ファンクションは返り値も呼びだせますが、その場合、呼びだされたスクリプトにはreturn文が含まれていなければなりません。
単一のスクリプト名(スペースまたは特殊文字は無し)を使ってスクリプトを同じスイートまたはhelper suite(ヘルパースイート)に保存する場合、スクリプト名をRun(実行) コマンドとして、必要なパラメータをコマンドに続けて使用します。
For a script in an unrelated suite, or a script with spaces or special characters in its name, you can type the Run command, followed by the script path:
Run "/Users/Seiji/Documents/EggPlant Suites/Validation.suite/Scripts/ConnectionScript"
// Calls the Run command to open a script from an unrelated suite
他のスクリプト内からスクリプトを呼ぶこの機能により、スクリプトをセグメント化して特定のタスクやアクションを実行させるように書く事は有益です。 この「モジュラー」アプローチで異なるコンテキストでスクリプトを最大限に再利用する事ができます。 このような場合は、「主要」スクリプトはテスト用または環境用に特有のコードを含む事がありますが、しかし別のスクリプトを呼びだして包括的なタスクを完了するようにします。
ハンドラ と ヘルパースイートの使用についての詳細情報は以下にあります。どちらの機能もコードの再利用とモジュールの設計に役立ちます。
Code Refactoring
時々、スクリプトを書いていて、スクリプトの1セクションが他のコンテキストや他のスクリプトに流用できる事に気付く事があります。 例えば、デスクトップに戻るといったような頻繁に繰り返す必要のあるSUT上のアクションを実行する手順を書く場合などです。 スクリプトの別の部分でこのアクションを実行する必要があるでしょうし、同じSUTを別のテストで使う場合は、同じ手順を別のスクリプトで使用できる事もあるでしょう。
Extract New Script(新しいスクリプトの抽出)機能を使ってコードのリファクタリングを行い、コードのセクションから新しいスクリプトを作成する事ができます。 この機能を使うには、Script Editor(スクリプトエディター)で再利用したいコードを選択(またはハイライト化)して、次に右クリックしてExtract New Script(新しいスクリプトの抽出)を選択します。 メニューのEdit(編集) > Extract New Script(新しいスクリプトの抽出)でこのオプションを選ぶ事もできます。 このオプションを選ぶ際、2、3の注意点があります。
- Script Editor(スクリプトエディター)で選択したコードが移転され新しいスクリプトに配置されると、それは最初はUntitled(タイトルなし)と呼ばれます。 スクリプトリストが開かれていないにも関わらず、新しいスクリプトがそこに追加されるのが分かります。
- Script Editor(スクリプトエディター)にコードを配置すると、新しいスクリプトの名前がハイライト化されて見えますので、その名を手順を説明するような名前に変えます。 Script Editor(スクリプトエディター)で名前を付けると、スクリプトリストの名前も同様に変わります。
抽出を選択したコードが、コードのセクション外から参照される変数を含んでいた場合、Extract New Script(新しいスクリプトの抽出)機能はこの変数をどう渡すかを扱います。
- 選択の中で使用されている、スクリプト内に以前から存在するどの変数も新しいスクリプトのparams(パラメータ)宣言に追加されます。 The new script is called as a command, so in the Script Editor, the variable will be listed after the new script name as a parameter when it executes.
ExtractedScript MyVar
- 選択の中で使用されている、スクリプト内に後から存在するどの変数も新しいスクリプトのreturn(リターン)宣言に追加されます。 In this case, the new script is called as a function instead of a command, and the returned value is put into the variable:
put ExtractedScript(MyVar) into MyOutVar
Extract New Script(新しいスクリプトの抽出)機能は複数の入出力変数を扱います。 実は、この方法でコードの複雑なセクションを新しいスクリプトに抽出できます。 覚えておくべき事は、しかしながら、スクリプトのモジュラー化を試みるべきで、そうすれば多くの異なるコンテキストで再利用できます。
新たに作成したスクリプトは、抽出されたスクリプトに加えて他のスクリプトからも名前で呼ばれる事を忘れないでください。 他のスクリプトを呼びだす事に関する詳細情報は、上記のCalling Scripts from Other Scripts(他のスクリプトからスクリプトを呼びだす)またはRunning Other Scripts and Handlers(他のスクリプトとハンドラの実行)ページを参照してください。
Handlers
同じスクリプト内でコードを再利用するには、本来サブスクリプトであるハンドラを書いてもできます。 ハンドラはいつでも呼び出せる主なスクリプトの一部で、他のスクリプトを呼ぶように使用できます。
例: CaptureTheScreenハンドラ
to CaptureTheScreen prefix, count // Starts the handler
set fileName to prefix & "ScreenShot" & count // Puts prefixScreenShotCount into fileName
set tempFile to "/tmp/" & fileName // Puts "/tmp/filename" into tempFile
CaptureScreen tempFile //Captures a screenshot
return fileName // Sets fileName as the function return value
end CaptureTheScreen //Ends the handler
ハンドラのリターン結果
スクリプトまたはハンドラが値を返したら、この例のように、次の行のResults(結果)ファンクションを呼んで値にアクセスできます。 上の例を使用する場合は、ハンドラを呼んで以下に示すように結果にアクセスできます。
Example: Returning results of a handler
CaptureTheScreen "MacTest", 6 // Calls the CaptureTheScreen handler
Set newFile to the result // Puts the returned value into a variable
コマンドまたはファンクションとしてのハンドラ
CaptureTheScreenハンドラは包括的なハンドラなので、ファンクションとして呼ぶ事も出来るでしょう。 使用においての大きな違いはコマンドはそれ自身で完全な文で、返り値を返すかどうかに関わらずに使用される事がありますが、一方ファンクションは表式の一部として呼ばれる必要があります。
Example: Calling handlers as commands and functions
CaptureTheScreen "MacTest", 6 // Called as a command; runs the handler
put CaptureTheScreen ("MacTest",6) // Called as a function; returns the value of the handler. Note parentheses.
他のスクリプトからハンドラの呼びだし
他のスクリプトからハンドラを呼びだすには3つの方法があります。
- スクリプト名に所有の‘sを付けて呼びだし、ハンドラの名前とパラメータをその後に続けます。
- スクリプト名を呼びだして、ドットとハンドラの名前を追加します。
- ハンドラ名を呼びだして、of とスクリプト名をその後に続けます。
Example: Calling a handler from another script
run Logging's CaptureTheScreen "MacTest", 6 // Calls handler with script name and possessive 's
run Logging. CaptureTheScreen "MacTest", 6 // Calls handler in the form script.handler
run CaptureTheScreen of Logging "MacTest", 6 // Calls handler with handler "of" script
Helper Suites
ヘルパースイートの追加。
- スイートウィンドウ下部のSettings(設定)ボタンをクリックします。
- 設定タブが開くと、ヘルパースイートペイン下部のAdd(追加)をクリックして一つ以上のヘルパースイートを追加します。 ファイルシステムブラウザダイアログが開かれ、ナビゲートに従ってヘルパースイートとして指定したいスイートを選択します。
To create a new helper suite, you can use one of two methods.
- From the File menu, select New Helper Suite OR from the Helper Suites pane, click New.
- Name the new suite and choose where to save it.
Helper Suites Pane
スイートの位置を示すパス
他のスイートへのパスの参照は、特に相対パスを使っている場合、またはソース管理がされている時にもされていない時にもスイートとファイルをチェックしている場合には、扱いにくいかもしれません。 このパスを扱う他の方法もいくつかあります。 その方法のひとつは、以下の文に示すようにスイートの位置を取得するスクリプトを書いて変数に保存する事です。
例:
put SuiteInfo().path // Returns the path to suite containing this script
例:
put the folder of me // Returns the full path to the Scripts folder containing this script
See Using a Relative Path for a Helper Suite to learn more.
スイートのグローバルプロパティ
As an alternative to using helper suites, Eggplant Functional provides the following global properties to specify suites a script can search before or after it searches its own suite:
- InitialSuitesグローバルプロパティで、スクリプトが自身のスイートを検索する前に検索するべきスイートを表示したリストを指定する事ができます。
- FinalSuitesグローバルプロパティで、スクリプトが自身のスイートを検索した後に検索するべきスイートを表示したリストを指定する事ができます。
例:
set the InitialSuites to (DSD & "myFirstSuite.suite", DSD & "mySecondSuite.suite")
例:
set the FinalSuites to (DSD & "mySuite.suite", DSD & "myOtherSuite.suite")
In the code above, DSD is a variable used to represent the Default Suite Directory. You would have to set the variable to the appropriate path for this directory (or to the location for your specific suites) before running these lines of code.
Helper Suites Organization in Eggplant Functional
The following video describes organizational features in Eggplant Functional, including those related specifically to helper suites.
Cross-Platform Applications
このセクションは現在のスクリプトをどのように構築すれば、テストを複数のオペレーティングシステムに展開できるかを説明します。
Creating Platform- and Language-Specific Suites
最初にテストする必要のある全プラットフォームのスクリプトの新セットを作成するのが簡単なように思えますが、しかしアプリケーションの進化に伴ってこれらのスクリプトの一貫性を保つのは実際には困難です。
扱いやすい長期的視野に立ったソリューションとは、基本となるスクリプトで始めて、オペレーティングシステムによって変更する手仕事のために外部のスクリプトを呼ぶ事です。 各プラットフォーム固有のスイート用にスクリプトを書き分けることができ、それからスクリプトに既定の実行のためにどのスイートを使用するのかを通知します。
Example: Quit scripts
Windowsスイートの場合:
TypeText ControlKey & AltKey & "x"
in a Mac suite:
TypeText CommandKey & "q"
この例では、スクリプト名 Quit(中止)が基本スクリプトでコマンドとして呼ばれる事になります。 Windows版またはMac版のどちらで実行するかは、どちらのスイートを指定するかに依存します。
Designating the Correct Suite
InitialSuitesグローバルプロパティはスクリプトに、スクリプトや画像リソースを検索する場合にどのスイートを最初にチェックするかを指示します。 (These suites even precede the suite in which the current script is running.) If you name more than one initial suite, remember that each suite’s helpers (and their helpers) are searched before the next "top level" suite.
上の例では、基本スクリプトが適切な Quit(中止)スクリプトを検出できるのは、適切なスイートにInitialSuites値を設定する事によることを確認してください。
Example: the InitialSuites
Set the InitialSuites to ("Windows") // Names the Windows suite as the first suite to check for resources
Quit // Runs the first Quit script found
Using Multilingual Text Images
インターフェース要素がテキストだけで識別される場合は常に、スクリプト内でキャプチャした画像では無く、生成したText Image(テキスト画像)を使用します。 これで多言語のスイートを作成する手間が大幅に省けます。
例えば、英語、フランス語、スペイン語版のアプリケーションで同じOpen(開く)ボタンをクリックする場合を考えてみましょう。 各言語ごとに別々のボタン画像をキャプチャすることもできますが、単一のText Image(テキスト画像)を生成して必要に応じて調節する方がずっと早いのです。
Example: using language-specific Text Images
Click (text: "Open", textStyle: "Button")
Click (text: "Ouvrir", textStyle: "Button")
Click (text: "Abierto", textStyle: "Button")
One Step Further—Translation Scripts
以下に示すように、各言語に翻訳スクリプトを設定すれば、言語固有のスイートをより効果的に使用できます。
Example: Translate script
params EnglishWord// Takes an English word...
set translation to {Hello: "Bonjour",Open: "Ouvrir",Yes: "Oui"} // Sets the translation variable to a property list, in which each English key is assigned a French value
return translation's (EnglishWord) // Returns the French value of the English key that was passed in
Now, to generate a Text Image in your base script, you could set the Text value to be the returned value of the "Translate" script.
Example: Calling the translate script
Set the InitialSuites to ("French") // Ensures that the "Translate" script comes from the French suite
Click (text: Translate ("Hello")) // Runs the "Translate" script with "Hello" as the EnglishWord parameter. Uses the returned value of "Translate" as the Text value in this property list.
翻訳スクリプトを使用している場合、基本言語で作動する版の作成を忘れないでください。 自身の言語への翻訳は必要ないにしても、基本スクリプトは、Translate(翻訳)の呼び出しを受けた場合は何かをする必要はあります。 The base-to-base "Translate" script does not need to go through the motions of translating anything; just taking a parameter and returning the same parameter is enough.
Example: Translate script
params BaseWord// Takes a word...
return BaseWord// Returns the same word.
Testing Across Desktop and Mobile Devices
This example uses a single master script to call four sub-scripts that test against the Evernote application on an Android device, as well as through a browser on a desktop machine and through the desktop version of the application.
For complete information about using parameters, see Parameters and Results.
Main Script (EvernoteTest.script)
//This script makes a note in Evernote on an Android device and then checks that the note was processed and shows up in a web browser on a Windows 7 VM//
//Populate variables (could also be drawn from a data file or database)
Put "Bananas" into MyFruit
Put "Carrots" into MyVeggie
AddItemsFromAndroid MyFruit, MyVeggie --Call script to add items to a grocery list from an Android device
CheckItemsInBrowser MyFruit, MyVeggie --Call script to connect to a Win 7 VM and login to Evernote online to see if the items updated
CheckItemsInDesktopApp MyFruit, MyVeggie --Call script that uses the Evernote desktop application to verify the list items
ClearList MyFruit, MyVeggie --Clear the List for Next Test Run
First Called Script (AddItemsFromAndroid.script)
//This script goes into Evernote on Android and adds items to the grocery list
Params Fruit, Veggie
Log "Entering Items in List via Android"
Connect GalaxyS3 //Connect to the device
Tap "AppMenu" //Navigate to the Evernote app
Tap "Evernote" //Navigate to the list
Tap "NoteIcon"
Tap "GroceryList"//Edit the list and add the items
Tap "EditIcon"
WaitFor 30.0, "Check"
TypeText Fruit, return
TypeText Veggie, return
//Save the list and navigate back to the home page
Tap "Check"
Wait 1
Tap "ElephantIcon"
TypeText HomeKey //Navigates to the home page using the home button on the device
WaitFor 30.0, "ChromeIcon" //Verifies that the home page of the device is displayed
Second Called Script (CheckItemsInBrowser.script)
//This script connects to a Win 7 VM and verifies the list items in Evernote through a web browser
Params Fruit, Veggie
Log "Checking the list items in a browser"
Connect Win7Demo //Connect to Win 7 VM
//Navigate to Evernote.com
DoubleClick "GoogleChrome"
WaitFor 30.0, "GoogleMenuLogo"
TypeText "Evernote.com",return
//Log In and make sure grocery list is selected
Click "SignIn"
TypeText "<email address>"
TypeText TabKey
TypeText "<password>"
Click "SignInButton"
Click "GroceryList"
//Find the Date Created and Log it
Put ReadText ("CreatedTLDate","CreatedBRDate") into DateCreated
Log "This List was Created on: " & DateCreated
//Find the Date Last Modified and Log it
Put ReadText ("ModifiedTLDate","ModifiedBRDate") into DateModified
Log "This List was Last Modified on: " & DateModified
//Read the Contents of Grocery List
Put ReadText ("TLList","BRList") into ListContents
Log "The list contained: " & ListContents
//Check to see if Fruit was properly synced
If ListContents contains Fruit
then
log "The list contained " & Fruit
else
logWarning "The item " & Fruit & " was not displayed"
end if
//Check to see if Veggie was properly synced
If ListContents contains Veggie
then
log "The list contained " & Veggie
else
logWarning "The item " & Veggie & " was not displayed"
end if
//Close out of Browser
Click "CloseButton"
Third Called Script (CheckItemsInDesktopApp.script)
//This script connects to a Win 7 VM and verifies the list items in the Evernote desktop application//
Params Fruit, Veggie
//Declares parameters. For an example on passing parameters, please see "Passing Parameters and Calling Functions"
Log "Checking the list items in the Evernote desktop application"
Connect Win7Demo //Connect to Win 7 VM
//Open Evernote desktop application and make sure Grocery List is selected
DoubleClick "EvernoteDesktopApp"
If not imagefound (30.0, "GroceryListSelected")
then
Click "GroceryList"
Click foundImageLocation()
end if
//Sync the list to update any modifications
Click "ToolsMenu"
Click "Sync"
Wait 5
Put ReadText ("CreatedTLDate","CreatedBRDate") into AppDateModified
Log "This List was Created on: " & AppDateModified
//Find the Date Created and Log it
Put ReadText ("CreatedTLDate","CreatedBRDate") into AppDateCreated
Log "This List was Created on: " & AppDateCreated
//Find the Date Last Modified and Log it
Put ReadText ("ModifiedTLDate","ModifiedBRDate") into AppDateModified
Log "This List was Last Modified on: " & AppDateModified
//Read the Contents of Grocery List
Put ReadText ("TLList","BRList") into AppListContents
Log "The list contained: " & AppListContents
//Check to see if Fruit was properly synced
If AppListContents contains Fruit
then
log "The list contained " & Fruit
else
logWarning "The item " & Fruit & " was not displayed"
end if
//Check to see if Veggie was properly synced
If AppListContents contains Veggie
then
log "The list contained " & Veggie
else
logWarning "The item " & Veggie & " was not displayed"
end if
//Close out of Browser
Click "CloseButton"
Last Called Script: Cleanup Script (ClearList.script)
//This script accesses Evernote via Android and clears the contents
Params Fruit, Veggie //Declares parameters
Log "Clearing the list on the Android device"
Connect GalaxyS3 //Connect to the device
//Navigate to the Evernote app
Tap "AppMenu"
Tap "EverNote"
//Navigate to the list and go into edit mode
Tap "NoteIcon"
Tap "GroceryList"
Tap "EditIcon"
WaitFor 30.0, "Check"
//Delete Item 1
TypeText ShiftKey, DownArrow
Click "DeleteButton"
//Delete Item 2
TypeText ShiftKey, DownArrow
Click "DeleteButton"
//Save the list and navigate back to the home page
Tap "Check"
Wait 1
Tap "ElephantIcon"
TypeText HomeKey
WaitFor 30.0, "ChromeIcon"
Running from a Master Script
Schedules(スケジュール)ペインはSuite Window(スイートウインドウ)にありますが、これはスクリプトのバッチを組織して実行するための便利なグラフィックインターフェースです。しかしもっと動的にスクリプトを実行する必要がある時は、マスタースクリプトを書かなければなりません。
マスタースクリプトの最も強力な機能はRunWithNewResults コマンドで、これで返されたスクリプトの結果を元に将来のスケジュールを作成する事ができます。
RunWithNewResultsは他のスクリプトをパラメータとして取り込んで作動します。 このパラメータスクリプトは自身の結果を生成し、その結果をマスタースクリプトに返します。 この利点は、以前の実行の返り値を基にして条件に応じてスクリプトの実行をスケジュールできる事です。 マスタースクリプトを通じていくらでもスクリプトを実行でき、同様にその結果を管理できます。
以下の例ではスクリプトがマスタースクリプトの機能をハイライト表示します。 最初に初期テストを実行します。 もしこのテストに失敗すれば、システム管理者に警告メールが送られます。さもなければ一連のテストを実行して文字列に結果を保存し、最終的にはログに記録します。
Example: Master Script
set TestList to ("Test1", "Test2", "Test3") // Creates a series of script executions.
RunWithNewResults "InitialTest"
set Outcome to the result
if the status of Outcome is not "Success" then
// If the result of "InitialTest" is not "Success", gets the date and time of the run...
convert Outcome's runDate to date and long time
sendMail (to: "administrator@yourcompany.com", from: "JoeTester@yourcompany.com", subject: "Initial Test Failed", body: "Test run at" && rundate of Outcome && "had" && errors of Outcome && "errors")
// Sends email to report the date and errors of the execution. (&& joins text strings with a space between them.)
else
// Otherwise...
repeat with each testScript of TestList
// For every script in TestList,
RunWithNewResults testScript // Runs the script, then...
set Outcome to the result // puts the results into Outcome
put testScript & ":" && status of Outcome && Return after currentReport
// Adds "Script: Status", then a return character to currentReport
if the status of Outcome is "Failure" then
// If the status property is Failure...
run "CleanupScript" // runs CleanupScript
end if
end repeat // Ends after the final test in TestList
Log "Final Results" // Logs "Final Results"
repeat with each line of currentReport
log it // Logs each line in currentReport
end repeat
end if