Selenium+pythonによる自動UIテスト(メールフォーム編)

各種設定が済んだので、いよいよSeleniumを使って自動テストを行います。

テストしたい機能はいろいろありますが、、、手始めに簡単なメールフォームでテストしてみます。

スポンサーリンク

テスト用のメールフォーム

メールフォームのファイル構成

ファイル構成はスタンダードに入力、確認、完了の3種類とします。

それぞれ仕様が満たせているか、Seleniumによってテストします。

入力画面 (index.php)

  • お名前、タイトル、メールアドレス、お問い合わせ内容の入力項目を持つ
  • 各入力項目は必須入力とし、入力せずに送信ボタンを押した場合はエラーを表示し再入力を促す
  • メールアドレスに「@」を含めずに送信ボタンを押した場合はエラーを表示し再入力を促す
  • 送信ボタンを押したときエラーがなければ確認画面(confirm.php)に遷移する

確認画面(confirm.php)

  • 入力画面で入力された各入力項目を表示する
  • 戻るボタンを押すと入力画面に遷移する
  • 送信ボタンを押すと完了画面に遷移する

完了画面(thanks.php)

  • メールを送信し、結果メッセージ(成功しましたor失敗しました)を表示する

各画面のソースコード

入力画面(index.php)のソース抜粋

<form method="POST" action="confirm.php">
	<table border="1">
		<tr>
			<th>お名前</th>
			<td>
				姓: <input name="name1" type="text" value="<?=$value["name1"] ?>"> 
				名: <input name="name2" type="text" value="<?=$value["name2"] ?>"><br>
				<span name="err_name"><?=$error["name"] ?></span>
			</td>
		</tr>

		<tr>
			<th>タイトル</th>
			<td>
				<input name="title" type="text" value="<?=$value["title"] ?>"><br>
				<span name="err_title"><?=$error["title"] ?></span>
			</td>
		</tr>

		<tr>
			<th>メールアドレス</th>
			<td>
				<input name="mail" type="text" value="<?=$value["mail"] ?>"><br>
				<span name="err_mail"><?=$error["mail"] ?></span>
			</td>
		</tr>

		<tr>
			<th>お問い合わせ内容</th>
			<td>
				<textarea name="message" rows="5" cols="55"><?=$value["message"] ?></textarea><br>
				<span name="err_message"><?=$error["message"] ?></span>
			</td>
		</tr>
	</table>
	<input name="submit" type="submit" value="送信">
</form>

よくあるメールフォームを用意してテストします。

$valueはエラー時、確認画面から戻った時の値を出力し、$errorはエラーがあった場合のエラーメッセージを格納します。

確認画面(confirm.php)のソース抜粋

<table border="1">
	<tr>
		<th>お名前</th>
		<td>
			<span name="name1"><?=$_SESSION["form"]["name1"]?></span> 
			<span name="name2"><?=$_SESSION["form"]["name2"]?></span>
		</td>
	</tr>

	<tr>
		<th>タイトル</th>
		<td><span name="title"><?=$_SESSION["form"]["title"]?></span></td>
	</tr>

	<tr>
		<th>メールアドレス</th>
		<td><span name="mail"><?=$_SESSION["form"]["mail"]?></span></td>
	</tr>

	<tr>
		<th>お問い合わせ内容</th>
		<td><span name="message"><?=nl2br($_SESSION["form"]["message"])?></span></td>
	</tr>
</table>
<input type="button" name="back" value="戻る" onClick="location.href='./index.php'"> 
<input type="button" name="send" value="送信" onClick="location.href='./thanks.php'">

$SESSIONは入力画面で入力した値を出力します。

完了画面(thanks.php)のソース抜粋

<span name="result"></span>

spanタグの中に結果メッセージを出力するようにします。

エラーなしの成功テスト

最初はエラーさせず、完了画面まで遷移させ全体の流れを構築します。

フォームへの入力

各入力項目にテストデータを入力するため、WebDriverのインスタンス経由で入力先のテキストボックスを指定します。

今回は各種name属性をもとに入力先を指定しようと思うので、find_element_by_nameと、send_keys関数で入力していきます。※ChromeWebDriverは適当な場所に

#ChromeWebdriverファイルのパス指定
driver = webdriver.Chrome(executable_path=os.getcwd()+"\\venv\\webdriver\\chromedriver.exe")

#ブラウザを起動し指定のURLを開く
driver.get(url)

driver.find_element_by_name("name1").send_keys("日常") #お名前(姓)
driver.find_element_by_name("name2").send_keys("プログラマー") #お名前(名)
driver.find_element_by_name("title").send_keys("メールフォームテスト") #タイトル
driver.find_element_by_name("mail").send_keys("selenium_python@xxx.xxx") #メールアドレス
driver.find_element_by_name("message").send_keys("お問い合わせ内容\nいろいろなメッセージ") #お問い合わせ内容

実行すると、すべての入力項目に指定したテキストが入力されるはずです。

続けて送信ボタンを押したいので、name属性をもとに下記でクリックをさせます。

driver.find_element_by_name("submit").click()

確認画面から完了画面へ

確認画面に遷移したら送信ボタンを押して完了画面に遷移したいので、ボタンのname属性に沿ってクリックさせます。

driver.find_element_by_name("send").click()

完了画面でメール送信は成功したか

完了画面でメールが送信できたかをチェックします。

結果メッセージはspanタグで囲われているのでtext関数で取得します。

if driver.find_element_by_name("result").text == "成功しました":
    print("テスト成功です")
else:
    print("テスト失敗です")

ここでprintしたメッセージはPyCharmのプロンプト上に表示されます。

以上の流れで、入力~確認~完了までを自動実行できるようになりました。

入力画面のエラーチェックを行う

上述したテストケースは”うまくいくケース”なのでエラーするケースをテストしていきます。

具体的には、このメールフォームは、下記のようにエラーチェックがかかる仕様なので、これらの条件を満たさないテストを行います。

  • すべての項目は入力が必須
  • メールアドレスは@が必要

必須エラーのテスト

必須項目に入力がなかった場合、エラー表示がされるかを確認します。

エラーした場合は入力項目の直下に赤字でエラーが出る仕様を想定します。各項目は下記のようにspanタグを用意し、エラーメッセージがある場合は$error変数に格納されるものとします。

<td>
 姓: <input name="name1" type="text" value="<?=$value["name1"] ?>"> 
 名: <input name="name2" type="text" value="<?=$value["name2"] ?>"><br>
 <span name="err_name"><?=$error["name"] ?></span>
</td>

Python側ではSeleniumでの入力を一切せずに送信ボタンを押すようにします。

driver.find_element_by_name("name1").send_keys("")  # お名前(姓)
driver.find_element_by_name("name2").send_keys("")  # お名前(名)
driver.find_element_by_name("title").send_keys("")  # タイトル
driver.find_element_by_name("mail").send_keys("")  # メールアドレス
driver.find_element_by_name("message").send_keys("")  # お問い合わせ内容

driver.find_element_by_name("submit").click()

POSTされたデータはPHPが適切にチェックし、エラーメッセージを格納できるものとします。

入力画面(index.php)でエラーメッセージが適切に表示されているか確認するため、「driver.find_element_by_name("submit").click()」を実行した直後に下記のエラーチェック処理を追加します。

現在のURLが入力画面であれば、spanタグにテキストが埋め込まれているかを確認し、埋め込まれていればPyCharmのプロンプト上にエラーしている項目と原因を表示させます。

if driver.current_url == "http://192.168.0.8/form/index.php":
    if driver.find_element_by_name("err_name").text != "":
        print("お名前でエラーしています(必須)")
    if driver.find_element_by_name("err_title").text != "":
        print("タイトルでエラーしています(必須)")
    if driver.find_element_by_name("err_mail").text != "":
        if not ("@" in driver.find_element_by_name("mail").get_attribute("value")):
            print("メールアドレスでエラーしています(形式):"+driver.find_element_by_name("mail").get_attribute("value"))
        else:
            print("メールアドレスでエラーしています(必須)")
    if driver.find_element_by_name("err_message").text != "":
        print("お問い合わせ内容でエラーしています(必須)")

すべての入力項目が空なので実行した結果は下記のようになります。

もしsend_keys関数のテキストが空でなかった場合はエラーが出ません。

お名前でエラーしています(必須)
タイトルでエラーしています(必須)
メールアドレスでエラーしています(必須)
お問い合わせ内容でエラーしています(必須)

プロセスは終了コード 0 で完了しました

メールアドレスの形式テスト

次にメールアドレスに@が含まれていなければエラーするかをテストします。

上述したエラーチェックのメールアドレス部分に含まれていて、入力値が存在し、@が含まれていなければエラーするようになっています。

if driver.find_element_by_name("err_mail").text != "":
    if not ("@" in driver.find_element_by_name("mail").get_attribute("value")):
        print("メールアドレスでエラーしています(形式):"+driver.find_element_by_name("mail").get_attribute("value"))
    else:
        print("メールアドレスでエラーしています(必須)")

この状態で下記のように@を含まない値を入力させます。

driver.find_element_by_name("mail").send_keys("selenium_pythonxxx.xxx")  # メールアドレス

実行した結果、下記のように必須とは異なったエラーメッセージがプロンプトに表示されます。

メールアドレスでエラーしています(形式):selenium_pythonxxx.xxx

これで入力内容がエラーしていた場合、どのようなエラーが発生しているか検知することができるようになりました。

確認画面のチェックを行う

入力した値と確認画面の値が一致しているかテスト

次に入力内容は正常であった場合、確認画面の表示内容がキチンと入力内容と一致しているかをテストします。

確認画面の表示は各項目で下記のようにspanタグで囲われていて、$_SESSIONによって入力値が表示されるようになっているものとします。

<tr>
	<th>お名前</th>
	<td>
		<span name="name1"><?=$_SESSION["form"]["name1"]?></span> 
		<span name="name2"><?=$_SESSION["form"]["name2"]?></span>
	</td>
</tr>

Python側で2点修正します。

まず入力画面でsend_keys関数に渡す入力値を変数化します。

name1 = "日常"
name2 = "プログラマー"
title = "メールフォームテスト"
mail = "selenium_python@xxx.xxx"
message = "お問い合わせ内容\nいろいろなメッセージ"

driver.find_element_by_name("name1").send_keys(name1)  # お名前(姓)
driver.find_element_by_name("name2").send_keys(name2)  # お名前(名)
driver.find_element_by_name("title").send_keys(title)  # タイトル
driver.find_element_by_name("mail").send_keys(mail)  # メールアドレス
driver.find_element_by_name("message").send_keys(message)  # お問い合わせ内容

またさきほどエラーチェックをしていたソースコードに対し、下記のようにelifの部分を追加します。

if driver.current_url == "http://192.168.0.8/form/index.php":
    if driver.find_element_by_name("err_name").text != "":
        print("お名前でエラーしています(必須)")
    if driver.find_element_by_name("err_title").text != "":
        print("タイトルでエラーしています(必須)")
    if driver.find_element_by_name("err_mail").text != "":
        if not ("@" in driver.find_element_by_name("mail").get_attribute("value")):
            print("メールアドレスでエラーしています(形式):"+driver.find_element_by_name("mail").get_attribute("value"))
        else:
            print("メールアドレスでエラーしています(必須)")
    if driver.find_element_by_name("err_message").text != "":
        print("お問い合わせ内容でエラーしています(必須)")

#▼ここから追加
elif driver.current_url == "http://192.168.0.8/form/confirm.php":
    if driver.find_element_by_name("name1").text != name1:
        print("確認画面のお名前(姓)が一致していません")
    if driver.find_element_by_name("name2").text != name2:
        print("確認画面のお名前(名)が一致していません")
    if driver.find_element_by_name("title").text != title:
        print("確認画面のタイトルが一致していません")
    if driver.find_element_by_name("mail").text != mail:
        print("確認画面のメールアドレスが一致していません")
    if driver.find_element_by_name("message").text != message:
        print("確認画面のお問い合わせ内容が一致していません")

追加した部分のif比較にname1やtitleなどの変数を用いています。

このように変数化しておけば、入力したときの値と、確認画面の値をチェックすることができます。同じ変数を使うため必ず一致するはずです。逆にエラーした場合は余計な処理が入っていると判断できます。

戻るボタンで戻り、入力画面の値が保持されているかテスト

確認画面の戻るボタンで入力画面に戻れること、戻った時各項目に入力値が保持されていることを確認します。

戻るボタンを押し、各項目のvalue値と入力値の変数とを比較する処理を、確認画面エラーチェックの直後に追加します。

#入力画面に戻る
driver.find_element_by_name("back").click()
if driver.find_element_by_name("name1").get_attribute("value") != name1:
    print("入力画面のお名前(姓)が一致していません")
if driver.find_element_by_name("name2").get_attribute("value") != name2:
    print("入力画面のお名前(名)が一致していません")
if driver.find_element_by_name("title").get_attribute("value") != title:
    print("入力画面のタイトルが一致していません")
if driver.find_element_by_name("mail").get_attribute("value") != mail:
    print("入力画面のメールアドレスが一致していません")
if driver.find_element_by_name("message").get_attribute("value") != message:
    print("入力画面のお問い合わせ内容が一致していません")

完了画面の結果をチェックする

最後に完了画面まで遷移し、メールの送信が成功したかを確認します。

完了画面の成否を持ってテストが完了となります。

戻るボタンで入力画面のテストをした直後から始めると、下記のようにして完了画面まで遷移します。

##↓確認画面に移動
driver.find_element_by_name("submit").click()

##↓完了画面に移動
driver.find_element_by_name("send").click()

最後に

ようやくPythonを使って自動UIテストを実行することができました。

自分で書いたとおりに自動でテストしてくれるので、テストの手間が省けます。

ただ、、、実務でのテストは、いろんなパターンでテストしないと、危険です。

次回はテストの仕方を工夫して、いろんなパターンで一括テストができるようにプログラムを修正していきます。

スポンサーリンク
おすすめの記事