Selenium
SeleniumIDE
テスト自動化
KatalonStudio

Katalon Studioでテストを自作した(2)

はじめに

わたしはWebアプリケーションのUIをテストする作業をソフトウェアで自動化する技術に関心があります。2018年1月以来わたしは Katalon Studio というソフトウェアに注目しています。以前「Katalon Studioとはどんなソフトウエアか」で概要を紹介しました。前回はRecord機能を使って自動生成したコードを手直しして自動化テストと呼べる内容のKatalon Studioプロジェクトを作りました。

あなたのWebサイトが大規模であればそれに比例して自動化テストも大きくならざるをえません。前回作った CURA-Test-Project をそのまま大きくすると、あちこちでコードが重複し読みにくく理解しにくいプロジェクトになるでしょう。今回は CURA-Test-Project を更に手直ししながら、Katalon Studioプロジェクトを大規模なWebサイトに対応可能にするテクニックを紹介します。

前提条件

  • Katalon StudioはWindows、Linuxでも利用可能ですが、今回の記事を書くにあたっては macOS High Siera 10.16 , Katalon Studio 5.4.1で検証しました。
  • Katalon Studioのインストールについては「Katalon Studioをインストールした」を参考に

サンプル in GitHub

この記事が説明するKatalon Projectのファイル一式をGitHubにアップしました。

このレポジトリのmasterブランチをローカルにcloneする操作はコマンドラインでこうします。

$ cd ~
$ mkdir katalon-workspace
$ cd katalon-workspace
$ git clone https://github.com/kazurayam/CURA-Test-Project.git

このレポジトリにはmasterプランチだけでなく、途中経過を保存したブランチがいくつかあります。

ブランチ名 内容
step0 Record機能を使って自動生成したばかり。リファクタリングする前。verification無し。Runすれば成功する
step1 Object Repositoryにページ毎サブフォルダ4つを追加し、Test Object群を配置し直した。Test Objectの名前はもとのまま
step2 Test Objectの名前を見直した
step3 Test Objectのselectorを見直した
step4 不要なTest Objectを削除した
step5 ページ遷移のチェックを実装した
step6 データのチェックを実装した
step7 わざとverifyEqualがFAILするようにした、LogViewerの表示を確認するため

以上のブランチについては前回の記事が説明しています。今回の記事に対応するブランチは以下のとおりです。

ブランチ名 内容
step8 Test Caseのモジュール化。Common/Loginを追加
step9 GlobalVariableを導入した
step10 Execution Profileで複数環境をテスト対象にする
step11 Test Suiteを導入した
master 最終形

リモートのstep7をローカルにcloneするには下記の操作をします。

$ git checkout -b stepy origin/step7 

Test Caseのモジュール化

step7ブランチのCURA-Test-ProjectにはTest Caseがひとつだけありました。すなわち Basicです。Katalon StudioではTest Caseを1つしか作ることができないのでしょうか?そんなことはありません。Katalon Studioでは複数のTest Caseを作ることができます。例えばテスト対象のWebサイトが下記のように複数のURLから構成されているなら、そのURLごとにTest Caseを作るのが自然でしょう。

しかし複数のTest Caseを作り始めるとすぐ、複数のTest Caseに同じコードが重複して現れることに気づくでしょう。コードの重複を可能な限り少なくすることはプログラミングの基本です。Test Caseに生じたコードの重複部分を括り出してモジュール化すべきです。

Katalon Studioではモジュール化すべきコードをひとつの Test Case にします。そしてモジュールとしてのTest Caseを他のTest Caseが呼び出すことができます。具体的には WebUI.callTestCase() キーワードを使います。

step8のCURA-Test-Projectでモジュール化のサンプルを示しています。step7のTest Case Basic からログイン処理を括り出して別のTest Case Login を作りました。そして BasicLogin をcallする形に変更しました。同時に BasicLogin をcallするときにUsernameとPasswordをパラメータとして指定する形にしました。図にすると下記のような形です。

TestCase_calls_TestCase.png

なおサブフォルダを作ってTest Caseをグループに分類することができます。任意の名前のサブフォルダをいくつでも作ることができます。フォルダ名を工夫することによりTest Case群を性質によって分類して理解しやすくすることができます。step8でCommonフォルダとMainフォルダを導入しました。

  • Common/Login
  • Main/Basic

呼び出す側のTest Case Main/Basic のGroovyコードは下記のようになりました。

// Make AppointmentボタンをクリックしてLogin画面を呼び出しUsernameとPasswordを入力しログインするまでを
// 別のTest Caseで実行する
WebUI.callTestCase(findTestCase('Common/Login'),
    [
        'Username': 'John Doe',
        'Password': 'ThisIsNotAPassword'
    ],
    FailureHandling.STOP_ON_FAILURE)

呼び出される側のTest Case Common/Login のGroovyコードは下記のようになりました。

WebUI.click(findTestObject('Page_CuraHomepage/a_Make Appointment'))
// ここでログイン・ページに遷移
WebUI.verifyElementPresent(findTestObject('Page_Login/button_Login'),
    10, FailureHandling.STOP_ON_FAILURE)

WebUI.setText(findTestObject('Page_Login/input_username'), Username)
WebUI.setText(findTestObject('Page_Login/input_password'), Password)

WebUI.click(findTestObject('Page_Login/button_Login'))
// ここで入力ページに遷移
WebUI.verifyElementPresent(findTestObject('Page_CuraAppointment/button_Book Appointment'),
    10, FailureHandling.STOP_ON_FAILURE)

parameters

Callされる側である Common/Loginのスクリプトが UsernamePassword という名前の変数を参照している点に注目しましょう。この二つの変数の宣言がスクリプトの中には見当たりません。どこで変数を宣言するのでしょうか?

じつはTest Case Common/Login をGUIで開いたときに Manualタブ、Scriptタブの次に Variables タブがあります。VariablesタブのなかにcallTestCaseキーワードで渡されたパラメータ値を引き受けるための変数名と変数型を宣言します。次のスクリーンショットを参照のこと。
スクリーンショット 2018-05-13 20.13.51.png

なお公式ドキュメント Variable Types に変数のタイプにかんする説明が書いてあるのですが残念ながらその記述はいまいちの出来です。

step8

この段階をGitHub上のCURA-Testing-Projectのstep8ブランチとして保存しました。step8ブランチをローカルに取り出すには下記の操作をします。

$ cd ~/katalon-workspace/CURA-Test-Project
$ git checkout -b step5 origin/step8

定数値をGlobalVariableとして記述する

Test Caseが定数値を参照するのはよくあるはなしです。たとえば

定数値 意味
http://demoaut.katalon.com ホスト名ないしはURLのprefix部分
John Doe ログインするのに必要なUsername
ThisIsNotAPassword ログインするのに必要なPassword

これら定数値をTest Caseのあちこちに繰り返し書くのは良くありません。あとで値を変更したくなったときに探し回らなければならなくなるから。定数値を一箇所にだけ書くことにしたい。どうすればいいか?

こうします。

  1. Katalon Studioの画面左のTests Explorerペインのなかに Profile というモノがある。Profileのなかに default という入れ物がある。
  2. defaultプロファイルのなかに Username と Password を宣言する。Execution Profileに宣言された変数はGlobalVariableすなわちグローバル変数となる。Excution Profiles/defaultのUsernameとPasswordに初期値を設定することができる。
  3. Test CaseのスクリプトがGlobalVariableを参照するようにTest Caseを書く
  4. Test Caseを実行するときにはExceution Profileのなかからプロファイルをひとつ選択して実行する。

Profiles(GlobalVariables).png

上記リストの3.すなわちTest Case Basic がGlobalVariableのUsernameとPasswordを参照している箇所は下記のようなコードになりました:

...

import internal.GlobalVariable as GlobalVariable

...

// Make AppointmentボタンをクリックしてLogin画面を呼び出しUsernameとPasswordを入力しログインするまでを
// 別のTest Caseで実行する
WebUI.callTestCase(findTestCase('Common/Login'),
    [
        'Username': GlobalVariable.Username,
        'Password': GlobalVariable.Password
    ],
    FailureHandling.STOP_ON_FAILURE)

internal.GlobalVariableというクラスをimportする必要があります。ただし

import internal.GlobalVariable as GlobalVariable

という一行はTest Caseを新規に作成したときにKatalon Studioによって自動的に作成されます。もしもこのimport文が無くなっていたら追記しましょう。

GlobalVariableを導入することにより John Doe という定数値をTest Caseのスクリプトのなかに書くかわりに GlobalVariable.Username という変数名を書けるようになりました。変数の初期値を設定しているのはProfile/defaultプロファイル1箇所ですから、あとで初期値を変更するのは容易です。

GlobalVariableがどのように実装されているか

グローバル変数である Username をTest Caseが参照するために GlobalVariable.Username と記述するのですが、Groovy言語の構文の観点からみてこれが何を意味するのでしょうか?それはこうです。

  1. クラス internal.GlobalVariable が存在していてKatalon Studio実行時のクラスパスにより参照可能になっている
  2. internal.GlobalVariableクラスがstaticなメンバー変数 Username を持っている。
  3. GUIのProfileで指定された初期値によって Username 変数が初期化されている。

実際にこのとおりに実装されたGroovyコードがKatalon Studioによってプロジェクトのなかに動的に生成されています。

%CURA-Test-Project%/Libs/internal/GlobalVariable.groovy

package internal

import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.testobject.ObjectRepository as ObjectRepository
import com.kms.katalon.core.testdata.TestDataFactory as TestDataFactory
import com.kms.katalon.core.testcase.TestCaseFactory as TestCaseFactory
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase

/**
 * This class is generated automatically by Katalon Studio and should not be modified or deleted.
 */
public class GlobalVariable {
    public static Object Username     
    public static Object Password     
    public static Object Hostname
    static {
        def allVariables = [:]        
        allVariables.put('default', ['Username' : 'John Doe', 'Password' : 'ThisIsNotAPassword', 'Hostname' : 'demoaut.katalon.com'])
        allVariables.put('develop', allVariables['default'] + ['Hostname' : 'demoaut-mimic.kazurayam.com', 'Username' : 'foo', 'Password' : 'bar'])
        allVariables.put('product', allVariables['default'] + ['Hostname' : 'demoaut.katalon.com', 'Username' : 'John Doe', 'Password' : 'ThisIsNotAPassword'])
        allVariables.put('staging', allVariables['default'] + ['Hostname' : 'demoaut-staging.katalon.com', 'Username' : 'who knows', 'Password' : 'DK2mai7qli9ZS'])        
        String profileName = RunConfiguration.getExecutionProfile()        
        def selectedVariables = allVariables[profileName]
        Username = selectedVariables['Username']
        Password = selectedVariables['Password']
        Hostname = selectedVariables['Hostname']        
    }
}

これがGlobalVariableの実体です。わかってしまえば不思議なところはありません。

step9

この段階をGitHub上のCURA-Testing-Projectのstep9ブランチとして保存しました。step9ブランチをローカルに取り出すには下記の操作をします。

$ cd ~/katalon-workspace/CURA-Test-Project
$ git checkout -b step9 origin/step9

Execution Profileでテスト対象を切り替える

ひとつのWebアプリケーションのために複数の環境(開発環境+ステージング環境+本番環境とか)があるのはごく普通のことです。各環境にはきっと固有のホスト名があるでしょう。UsernameとPasswordも環境ごとに違っているかもしれません。いまKatalon Studioでテスト・プロジェクトをひとつ作成し複数環境に適用したい。ただし環境を切り替えるためにその都度ソースコードを手で書き直さなければならないのは嫌だ。こういう場合、どうすればいいか?

Execution Profileを利用すればひとつのテスト・プロジェクトを複数の環境に適用することができます。

Katalon Studioのウインドウの左サイドバーのTests Explorerの最下部に Profiles があり、その中にはdefaultというプロファイルがあります。ここにカスタムなプロファイルを複数追加することができます。developproductstaging、という3つのプロファイルを追加しましょう。

Profile名 GlobalVariable名 初期値
develop Hostname demoaut-mimic.kazurayam.com
develop Useraname foo
develop Password bar
Profile名 GlobalVariable名 初期値
product Hostname demoaut.katalon.com
product Username John Doe
product Password ThisIsNotAPassword
Profile名 GlobalVariable名 初期値
staging Hostname demoaut-staging.katalon.com
staging Username who knows
staging Password DK2mai7qli9ZS

Katalon StudioのGUIのどこでProfileを追加するかというと下記スクリーンショットのとおり。
more_profiles.png

ここまで準備ができたところで、GUIの右上にあるボタンをクリックしてProfileを選択します。選択されたProfileに登録されたGlobalVariableの初期値がTest Case実行時に参照されます。

selecting_a_profile_to_execute_with.PNG

本番環境をテストするにはGUI右上のドロップダウンリストで product を選択することにより GlobalVariable.Hostname の初期値として demoaut.katalon.com が設定されます。開発環境をテストするには develop を選択し、ステージング環境をテストするには staging を選択すれよい。このようにしてテスト対象としての環境を切り替えることが容易に可能です。

step10

この段階をGitHub上のCURA-Testing-Projectのstep10ブランチとして保存しました。step10ブランチをローカルに取り出すには下記の操作をします。

$ cd ~/katalon-workspace/CURA-Test-Project
$ git checkout -b step10 origin/step10

複数のTest Casesを一括実行する:Test Suite

ここまでCURA-Test-ProjectにはTest CaseがBasicひとつあるだけでした。ここで LoginTest を追加しましょう。LoginTestはトップページを開いてログインできるかどうかをテストするだけで診察予約の入力のことは省いたシンプルなテストであるとします。

さてわたしは LoginTestBasicをまとめて実行したい。LoginTestをRunするために1回ボタンを押し、BasicをRunするためにもう1回ボタンを押すのは面倒くさい。1回のRun操作で2つ以上複数個のTest Casesを一括して実行したい。こんごTest Casetが10個、50個、100個と増えても1回の操作でまとめて実行したい。どうすればいいか?

そんな要求を実現するために Test Suite があります。

下記スクリーンショットが示すように Test Suite TS1 を作りました。TS1は2つのTest Caseを単純に列挙したもので、Test Suite TS1 を実行することによって間接的に2つのTest Caseが上から下に順番に実行されます。
TestSuites_TS1.png

ひとつのTest Suiteの配下に登録できるTest Caseの数には上限がありません。わたしが試したことがあるのはせいぜい10個程度ですが、Katalon Forumによれば500個のTest CaseをひとつのTest Suiteで一括実行するという剛の者もいるようです。

Test SuiteをRunするには下記のように操作します。Test CaseひとつをRunするのと同じ操作です。

  1. Tests ExplorerでTest Suite TS1 をダブルクリックする。するとTS1がKatalon Studioによりロードされる。
  2. ウインドウ右上にあるRunボタンでブラウザを選択して実行する

run_testsuite.png

step11

この段階をGitHub上のCURA-Testing-Projectのstep11ブランチとして保存しました。step11ブランチをローカルに取り出すには下記の操作をします。

$ cd ~/katalon-workspace/CURA-Test-Project
$ git checkout -b step11 origin/step11

ReportsでTest Suiteの実行結果をみる

Test Caseの実行時ログはKatalon Studioのウインドウ右下のLogViewに表示されます。ではTest Suiteを実行したときつまり複数のTest Caseをまとめて実行したとき、各Test Caseを実行した時のログをどこで見ることができるのか?

Reports を使います。Katalon Studioのウインドウ左サイドのTests ExplorerのなかにReportsというアイコンがあります。Reportsをクリックすると、Test Suite TS1を実行したときのログがタイムスタンプ別に保存されているのがわかります。ひとつのタイムスタンプを選択してダブルクリックしましょう。

するとTest Suiteを構成するTest Casesが列挙されてそのログにアクセスできることがわかります。さらに
ShowTestCaseDetails.PNGというボタンをクリックすれば、各Test Caseのログの詳細が表示されます。

つまりReportsを使えば下記のようなGUIでTest Suitesの実行結果をみることができます。
Reports.png

テストの最終成果物 Test Suite Summery

Test Suite毎のSummeryをみればTest SuiteがいつStartしていつEndしたか、Test Caseをいくつ実行したか、FailedしたTest Caseがいくつあったか、Errorがいくつあったかがわかります。

TestSuiteSummary.PNG

Summaryに表示された判定内容こそが自動化テストの成果物です。もしも Failed>0 あるいは Error>0 だったら悪い兆候です。あなたのWebサイトに問題があるか又は自動化テストのどこかに問題があるにちがいありません。すぐに対処しましょう。

結び

Katalon Studioはテスト対象のWebページのスクリーンショットをとる機能を提供しています。次回はスクリーンショットの撮り方を紹介するつもりです。