Selenium+pythonによる自動UIテスト(外部テストデータとログ編)

メールフォームで自動UIテストをすることが前回できました。

しかし現状の自動UIテストは、「プログラムを書いてまで実行したいか?」と言われれば疑問です。

プログラムで書いたからにはいろんなパターンのテストを"自動で"、"高速で"、実行してもらわないと書いた甲斐がありません。

そこで本稿ではより利便性を高めるため下記の修正を加えていきます。

  • 複数のテストパターンを自動テストできるにする
  • テスト結果はログに記録できるようにする
  • プログラマーでなくてもテストが書けるようにする

スポンサーリンク

ファイル・ディレクトリの追加

ファイル・ディレクトリの構造

テストデータ、ログを記録するためのファイル・ディレクトリは下記の構造とします。

●プロジェクト名
  ┗main.py ※テスト実行ファイル
  ┗log ※新規ディレクトリ
  ┗config ※新規ディレクトリ
    ┗data.csv  ※新規

テストデータの作成

configディレクトリに、テストデータを記載したdata.csvを作成します。

data.csvの中身は1行目が見出し(name属性と同じ)、2行目以降はテストデータとして下記のように用意します。※データは適当に

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

テストデータは複数記載し、繰り返し自動でテストできるようにします。

Pythonファイルの外側に出したので、プログラマーでなくてもテストパターンを作成することができるようになりました。

ログファイルで記録できるようにする

クラス化をする

print関数でプロンプト上に表示させるだけで終わってしまうと、後日テスト結果を見返すことができません。都度テストをするのも面倒ですので、記録として残しておきたいところです。

ここではテスト結果を残すためにログ出力を追加します。

諸々都合が良くなるので、まず前回のPythonコードを丸ごとクラス化します。

クラスの中身を作る

まず下記のように全体をクラス内に納めます。

import os
from selenium import webdriver

url = "http://192.168.0.8/form/"

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

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

name1 = "日常"
name2 = "プログラマー"
...

↓class名は"UiTest"、コンストラクタで日付を名前にしたログを書き出す準備をします。

import datetime
import os
import csv
import shutil
from selenium import webdriver

class UiTest:
    def __init__(self,date):
        UiTest.log = open(os.getcwd()+"\\log\\"+date+"_log.csv", 'a',encoding="utf-8",newline="")

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

        url = "http://192.168.0.8/form/"

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

        name1 = "日常"
        name2 = "プログラマー"
...

クラスを呼び出す処理を追加

↓クラスの外は以下のようにして、作成したUiTestクラスの関数を実行します。

date = datetime.datetime.now ().strftime ("%Y%m%d_%H%M%S")
shutil.copyfile(os.getcwd()+"\\config\\data.csv",os.getcwd()+"\\log\\"+date+"_data.csv")
UiTest().exec(line)

ログを書き出すようにする

print("お名前でエラーしています(必須)")

↓コンストラクタで初期化した変数で書き込み

UiTest.log.write("お名前でエラーしています(必須)\n")

これで実行するたびに結果をログファイルに書き出すようになりました。エラーした内容が出力されます。

外部テストデータを読み込ませる

テストを繰り返し実行させる

クラスのコンストラクタに行数のカウンター変数を追加

行数のカウンター変数をクラスに持たせます。ログにエラーを書き出すとき、何行目のデータがエラーしたのか判別するためです。

class UiTest:
    def __init__(self,date):
        UiTest.log = open(os.getcwd()+"\\log\\"+date+"_log.csv", 'a',encoding="utf-8",newline="")

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

class UiTest:
    cnt = 0
    def __init__(self,date):
        UiTest.cnt += 1
        UiTest.log = open(os.getcwd()+"\\log\\"+date+"_log.csv", 'a',encoding="utf-8",newline="")

    def exec(self,data):
...
        name1 = data["name1"]
        name2 = data["name2"]
        title = data["title"]
        mail = data["mail"]
        message = data["message"]
...

ログの書き出し内容に行数のカウンター変数を使用

書き出し内容にカウンター変数を加えます。

UiTest.log.write("お名前でエラーしています(必須)\n")

UiTest.log.write(str(UiTest.cnt)+"行目:お名前でエラーしています(必須)\n")

クラスの呼び出し箇所をループ処理に変更

date = datetime.datetime.now ().strftime ("%Y%m%d_%H%M%S")
shutil.copyfile(os.getcwd()+"\\config\\data.csv",os.getcwd()+"\\log\\"+date+"_data.csv")
UiTest().exec(line)

date = datetime.datetime.now ().strftime ("%Y%m%d_%H%M%S")
shutil.copyfile(os.getcwd()+"\\config\\data.csv",os.getcwd()+"\\log\\"+date+"_data.csv")
with open(os.getcwd()+"\\config\\data.csv", "r",encoding="utf-8") as f:
    reader = csv.DictReader(f, delimiter=",")
    for line in reader:
        UiTest(date).exec(line)

まとめ

テストを繰り返し実行し、結果をログに出力することで、大分テストの手間を削減することができました。

しかもテストパターンはcsvファイルで管理されているので、テストプログラムの作成はプログラマー、テストパターンの作成をプログラマー以外と役割分担をすることが可能になったこともメリットです。

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