selenium+Python Page Object自動化測試

本文是我在學習了selenium+Python進行自動化測試後的總結,方便以後回顧和填坑吧(確實遇到了不少坑~~),也希望各位大神能多多指教!
本文主要包含Page Object模式設計測試用例,selenium元素定位和常用操作,同時包含自己在實踐中遇到的各種坑。
我設計的場景是用火狐瀏覽器登錄百度首頁,在首頁上測試輸入框,以及含有‘百度’的鏈接數量;然後點擊“設置”–>”高級搜索”,進入搜索設置頁面,檢查下拉菜單和單選框的屬性;然後在搜索框輸入搜索詞,在 搜索頁面得到搜索數目。

1. Page Object模式測試用例設計

PageObject是一種程序設計模式,將面向過程轉變爲面向對象(頁面對象),將測試對象及單個的測試步驟封裝在每個Page對象中,以page爲單位進行管理。可以使代碼複用,降低維護成本,提高程序可讀性和編寫效率。
PageObject可以將頁面定位和業務操作分開,分離測試對象(元素對象)和測試腳本(用例腳本),提高用例的可維護性。

我理解的就是將Page和test分開,這樣在一項改變時不會影響整體,變動減少。

Pages

首先看pages的設計,先有一個BasePage,這個BasePage包含所有待測page都能用到的公用方法。
這裏寫圖片描述
驗證頁面的方法_validate_page()使用了@abstractmethod進行裝飾,基類不能被實例化,只有當子類繼承並且實現了改方法後子類纔可以實例化,這樣可以對不同的頁面進行不同的驗證。並定義了Search和Setting兩種方法,用於轉向不同頁面,使用@property將方法轉爲屬性,方便實例化對象後使用。
對於首頁的設計,如下:
這裏寫圖片描述
在首頁中,完成了對頁面驗證_validate_page() 的重寫,並對含有’百度’的鏈接數和‘新聞’鏈接狀態進行了返回。
對於搜索設置頁面,如下:
這裏寫圖片描述
在SettingRegion()類實現點擊‘設置’進入設置頁面,在SettingPage類裏完成對該頁面一些元素的檢查,包括搜索時間範圍的下來菜單,檢查其包含的下來選項數量,選擇其中一項,查找範圍的單選按鈕,選中一項。
對於搜索結果頁面,如下:
這裏寫圖片描述

主要完成輸入搜索詞點擊搜索,SearchRegion()類,然後在搜索結果頁面定位到結果語句,並將語句中的數值返回(即搜索到的條目數)。

Test

我使用的是unittest來組織測試,pip install unittest 安裝後,先在test的基類中完成測試前/後的方法,即setUp()和tearDown(),這會在每次test方法前後調用,若是想應用於整個測試類,可以使用類方法setUpClass()和tearDownClass(),並使用@classmethod 修飾。基類如下:

import unittest
from selenium import webdriver

class BaseTestCase(unittest.TestCase):
    """docstring for BaseTestCase"""
    def setUp(self):
        # create a new Firefox session
        profile_dir = r'C:\Users\czhou012\AppData\Roaming\Mozilla\Firefox\Profiles\iewanxoz.default'
        profile = webdriver.FirefoxProfile(profile_dir)
        self.driver = webdriver.Firefox(profile)
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()

        # navigate to the application home page
        self.driver.get('https://www.baidu.com/')

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

最後寫測試類,繼承於BaseTestCase():

import unittest
from pages.homepage import HomePage
from pages.settingpage import SettingRegion
from base.basetestcase import BaseTestCase
from base.data import GetData
from ddt import ddt, data, unpack

@ddt
class PageTest(BaseTestCase):
    """docstring for PageTest"""
    #@unittest.skip('not run')
    def test_home_page(self):
        hp = HomePage(self.driver)
        self.assertEqual(4,hp.links_count)
        self.assertTrue(hp.news_able)
    #@unittest.skip('not run')
    def test_set_page(self):
        set_page = HomePage(self.driver).Setting.set_to()
        self.assertEqual(5,set_page.num_show_time)
        self.assertEqual('最近一天',set_page.select_one_day)
        self.assertTrue(set_page.radio_select)
    #@unittest.skip('no run ')
    @data(*GetData().data)
    @unpack
    def test_search_result(self,term,expect_num):
        sp = HomePage(self.driver).Search.searchFor(term)
        self.assertGreater(sp.result_num,expect_num)

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

分別完成首頁的測試,設置頁面的測試,和搜索結果頁面的測試。

數據驅動

在搜索結果的測試中我使用了數據驅動,即將數據參數化,適用於大量數據重複操作中,在這裏我新建了一個csv數據文檔,隨意編寫了搜索詞條和必須大於的返回結果數目。
這裏寫圖片描述
對應編寫用於讀取數據的模塊:

#coding:utf-8
import csv

class GetData(object):
    """docstring for GetDat"""
    def __init__(self, file_name=None):

        if file_name != None:
            self.file_name = file_name
        else:
            self.file_name = r'D:\TEST\selenium\my\testdata.csv'
        # create an empty list to store rows
    @property
    def data(self):
        rows = []
        # open the CSV file
        with open(self.file_name,'r',encoding='utf-8') as data_file:
            # 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)
            num_list = list(map(int,list(zip(*rows))[1]))
            term_list = list(zip(*rows))[0]
            return list(zip(term_list,num_list))

這樣調用該對象的data即可返回數據[('phones', 3), ('music', 5), ('iphone 5s', 10)]
使用ddt模塊pip install ddt, 在測試類前加修飾@ddt ,在使用數據驅動的測試方法前使用@data(數據集),獲取數據,使用@unpack 會自動將數據對應到多個參數上。單獨運行可以看出結果:
這裏寫圖片描述
去掉註釋整體運行可得結果:
這裏寫圖片描述

填坑

坑一:直接使用腳本啓動Firefox瀏覽器,會發現沒有瀏覽器插件,打開相同的網址,網頁展示也不一樣,這會給定位元素造成很大困擾。原因:用腳本去打開瀏覽器時候,其實是重新打開了一個進程,跟手動打開瀏覽器不是一個進程。解決方法:在啓動時webdriver.Firefox(profile)傳入參數profile,具體可參考此博文
坑二:對於需要懸停操作顯示元素的定位:
這裏寫圖片描述
百度首頁的搜索設置選項需要在‘設置’懸停顯示,需要加入鼠標移動到指定元素中央的操作。
坑三:選擇下拉菜單選項時可能會有報錯:‘Element could not be scrolled into view’,加入等待時間即可。
坑四:逐行讀取csv文件後獲得的二維列表中,Number列是str類型,這樣不能直接比較,我這裏採用的方法是將該列取出轉爲int,再和前一列合併。
坑五:我定位到的是百度搜索結果的一句話。需要在這句話中找出用逗號分隔表示的數值,這裏沒用正則表達式,而是使用isdigit() 來判斷,需要注意返回的是類似於[‘1’,’2’,’3’,’4’]這樣的列表,還需要拼接後再轉爲int類型。


新手學習,歡迎指教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章