selenium+Python Page Object自动化测试

本文是我在学习了selenium+Python进行自动化测试后的总结,方便以后回顾和填坑吧(确实遇到了不少坑~~),也希望各位大神能多多指教!
本文主要包含Page Object模式设计测试用例,selenium元素定位和常用操作,同时包含自己在实践中遇到的各种坑。
我设计的场景是用火狐浏览器登录百度首页,在首页上测试输入框,以及含有‘百度’的链接数量;然后点击“设置”–>”高级搜索”,进入搜索设置页面,检查下拉菜单和单选框的属性;然后在搜索框输入搜索词,在 搜索页面得到搜索数目。

1. Page Object模式测试用例设计

PageObject是一种程序设计模式,将面向过程转变为面向对象(页面对象),将测试对象及单个的测试步骤封装在每个Page对象中,以page为单位进行管理。可以使代码复用,降低维护成本,提高程序可读性和编写效率。
PageObject可以将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),提高用例的可维护性。

我理解的就是将Page和test分开,这样在一项改变时不会影响整体,变动减少。

Pages

首先看pages的设计,先有一个BasePage,这个BasePage包含所有待测page都能用到的公用方法。
selenium+Python Page Object自动化测试_第1张图片
验证页面的方法_validate_page()使用了@abstractmethod进行装饰,基类不能被实例化,只有当子类继承并且实现了改方法后子类才可以实例化,这样可以对不同的页面进行不同的验证。并定义了Search和Setting两种方法,用于转向不同页面,使用@property将方法转为属性,方便实例化对象后使用。
对于首页的设计,如下:
selenium+Python Page Object自动化测试_第2张图片
在首页中,完成了对页面验证_validate_page() 的重写,并对含有’百度’的链接数和‘新闻’链接状态进行了返回。
对于搜索设置页面,如下:
selenium+Python Page Object自动化测试_第3张图片
在SettingRegion()类实现点击‘设置’进入设置页面,在SettingPage类里完成对该页面一些元素的检查,包括搜索时间范围的下来菜单,检查其包含的下来选项数量,选择其中一项,查找范围的单选按钮,选中一项。
对于搜索结果页面,如下:
selenium+Python Page Object自动化测试_第4张图片

主要完成输入搜索词点击搜索,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 会自动将数据对应到多个参数上。单独运行可以看出结果:
selenium+Python Page Object自动化测试_第5张图片
去掉注释整体运行可得结果:
selenium+Python Page Object自动化测试_第6张图片

填坑

坑一:直接使用脚本启动Firefox浏览器,会发现没有浏览器插件,打开相同的网址,网页展示也不一样,这会给定位元素造成很大困扰。原因:用脚本去打开浏览器时候,其实是重新打开了一个进程,跟手动打开浏览器不是一个进程。解决方法:在启动时webdriver.Firefox(profile)传入参数profile,具体可参考此博文
坑二:对于需要悬停操作显示元素的定位:
这里写图片描述
百度首页的搜索设置选项需要在‘设置’悬停显示,需要加入鼠标移动到指定元素中央的操作。
坑三:选择下拉菜单选项时可能会有报错:‘Element could not be scrolled into view’,加入等待时间即可。
坑四:逐行读取csv文件后获得的二维列表中,Number列是str类型,这样不能直接比较,我这里采用的方法是将该列取出转为int,再和前一列合并。
坑五:我定位到的是百度搜索结果的一句话。需要在这句话中找出用逗号分隔表示的数值,这里没用正则表达式,而是使用isdigit() 来判断,需要注意返回的是类似于[‘1’,’2’,’3’,’4’]这样的列表,还需要拼接后再转为int类型。


新手学习,欢迎指教!

你可能感兴趣的:(selenium+Python Page Object自动化测试)