Flying Cat Penguin

ゆるゆる仕事、ソフトウェアテスティング関連のことについて綴ります。

Seleniumコードサンプル#2 データ駆動テスト

自動テストのための学習のため、Seleniumコードサンプル(データ駆動テスト)を実施してみます。

以前、読んだpython用の書籍だとすでに試せるサイトが大幅に変わってしまったので、
自分でHTMLファイルを作成して、疑似的に下記の構成を確認しています。
今回は、CSV記述してある、username、password、monthのデータの組み合わせをテストする仕組みを実装してみました。

[画面イメージ]
f:id:dandan_611:20200602172807p:plain

今回は下記の内容を試してみました。
このサンプルのゴールは、単一ページの入力と操作に関するデータの組み合わせのテストを完遂することです。

【項目】
・データ駆動テスト
CSV読み込み

ちなみにデータは下記のようなものです。

[testdata.csv]

username,password,month
odan1,odanpass1,jan
odan2,odanpass2,feb
odan3,odanpass3,mar
odan4,odanpass4,apr
odan5,odanpass5,may
odan6,odanpass6,jun
odan1,odanpass1,jul
odan2,odanpass2,aug
odan3,odanpass3,sep
odan4,odanpass4,oct
odan5,odanpass5,nov
odan6,odanpass6,dec

[selenium_ddt_html.py]

import unittest
import csv
import time
from selenium import webdriver
from ddt import ddt, data, unpack
from selenium.webdriver.support.ui import Select

def get_data(file_name):
    # create an empty list to store rows
    rows = []
    # open the CSV file
    data_file = open(file_name, "r")
    # create a CSV Reader from CSV file
    reader = csv.reader(data_file)
    # skip the headers
    next(reader, None)
    # add rows from reader to list
    for row in reader:
        rows.append(row)
        
    return rows

@ddt
class SearchDDT(unittest.TestCase):
    def setUp(self): 
        # create a new Chrome session
        self.driver = webdriver.Chrome(executable_path=r'C:/tmp/selenium/chromedriver_win32/chromedriver.exe')
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()
        
        # navigate to page
        self.driver.get("file:///C:/cygwin64/home/User/selenium/01_sample.html")

    @data(*get_data("testdata.csv"))
    @unpack
    def test_samplehtml(self, username, password, month):
        # get the search textbox
        
        # input ID/PASS and push submit botton
        id = self.driver.find_element_by_name("Username")
        id.send_keys(str(username))
        
        password = self.driver.find_element_by_name("Password")
        password.send_keys(str(password))
        
        dropdownlist = self.driver.find_element_by_name("Month")
        month_select_element = Select(dropdownlist)
        month_select_element.select_by_value(str(month))
        
        time.sleep(2)
        
        self.driver.find_element_by_name("Submit").click();
        
        # true
        self.assertEqual(10, 10)

    def tearDown(self):
        # close the browser window
        self.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

[sample.html]

<html>
<body>
	<!-- 入力フォーム -->
    <form id="loginForm">
        <label>Enter Username: </label>
        <input type="text" name="Username"/>
        <label>Enter Password: </label>
        <input type="password" name="Password"/>
        
        <!-- ドロップダウンリスト -->
        <select name="Month">
	        <option value="jan">1月</option>
			<option value="feb">2月</option>
			<option value="mar">3月</option>
			<option value="apr">4月</option>
			<option value="may">5月</option>
			<option value="jun">6月</option>
			<option value="jul">7月</option>
			<option value="aug">8月</option>
			<option value="sep">9月</option>
			<option value="oct">10月</option>
			<option value="nov">11月</option>
			<option value="dec">12月</option>
		</select>
		
	<!-- ボタン -->
        <input type="submit" name="Submit"/>
    </form>
    <a href="forgotPassword.html">Forgot Password ?</a>
</body>
</html>

ちなみに実行すると下記のような出力になります。

$ python selenium_ddt_csv_samplehtml.py
test_samplehtml_01___odan1____odanpass1____jan__ (__main__.SearchDDT) ... ok
test_samplehtml_02___odan2____odanpass2____feb__ (__main__.SearchDDT) ... ok
test_samplehtml_03___odan3____odanpass3____mar__ (__main__.SearchDDT) ... ok
test_samplehtml_04___odan4____odanpass4____apr__ (__main__.SearchDDT) ... ok
test_samplehtml_05___odan5____odanpass5____may__ (__main__.SearchDDT) ... ok
test_samplehtml_06___odan6____odanpass6____jun__ (__main__.SearchDDT) ... ok
test_samplehtml_07___odan1____odanpass1____jul__ (__main__.SearchDDT) ... ok
test_samplehtml_08___odan2____odanpass2____aug__ (__main__.SearchDDT) ... ok
test_samplehtml_09___odan3____odanpass3____sep__ (__main__.SearchDDT) ... ok
test_samplehtml_10___odan4____odanpass4____oct__ (__main__.SearchDDT) ... ok
test_samplehtml_11___odan5____odanpass5____nov__ (__main__.SearchDDT) ... ok
test_samplehtml_12___odan6____odanpass6____dec__ (__main__.SearchDDT) ... ok

----------------------------------------------------------------------
Ran 12 tests in 158.901s

OK

【まとめ】
CSVを利用したテストを作成することができました。
実際には、汎用的な振る舞いを作成しておいて、データから振る舞いを少し変えるような実装でもいいかもしれません。
ただ、その場合はデータが同じようなもの同士を分離したテストスイートを作ったほうが良いような気も…(誰か教えて…)
気を付けないと、大量の効率化されてないテストができてしまいそうなので、テスト設計をきちんとやる甲斐がありそうです。

ちなみに、実装しているときにテストスイートがうまく利用できなかったので一旦断念しました。(要確認)
あと、get_data関数を利用するときに、"*"をつけて利用しているのですがここは単純にpythonの仕様きちんと復習します…。

次回は、ページオブジェクトパターンを利用した自動テストを作成してみたいと思います。