博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python+Selenium框架设计篇之5-框架内封装基类和实现POM
阅读量:4301 次
发布时间:2019-05-27

本文共 7327 字,大约阅读时间需要 24 分钟。

      前面文章,我们实现了框架的一部分功能,包括日志类和浏览器引擎类的封装,今天我们继续封装一个基类和介绍如何实现POM。关于基类,是这样定义的:把一些常见的页面操作的selenium封装到base_page.py这个类文件,以后每个POM中的页面类,都继承这个基类,这样每个页面类都有基类的方法,这个我们会在这篇文章实现。

1. 在实现封装基类里,我们实现了元素八大方式的定位和截图类封装。具体项目层级结构如下图。

2. 基类base_page.py的具体实现代码,这里就封装了几个常用方法,其他方法,你自己去练习封装下。

# coding=utf-8import timefrom selenium.common.exceptions import NoSuchElementExceptionimport os.pathfrom framework.logger import Logger# create a logger instancelogger = Logger(logger="BasePage").getlog()class BasePage(object):    """    定义一个页面基类,让所有页面都继承这个类,封装一些常用的页面操作方法到这个类    """    def __init__(self, driver):        self.driver = driver    # quit browser and end testing    def quit_browser(self):        self.driver.quit()    # 浏览器前进操作    def forward(self):        self.driver.forward()        logger.info("Click forward on current page.")    # 浏览器后退操作    def back(self):        self.driver.back()        logger.info("Click back on current page.")    # 隐式等待    def wait(self, seconds):        self.driver.implicitly_wait(seconds)        logger.info("wait for %d seconds." % seconds)    # 点击关闭当前窗口    def close(self):        try:            self.driver.close()            logger.info("Closing and quit the browser.")        except NameError as e:            logger.error("Failed to quit the browser with %s" % e)    # 保存图片    def get_windows_img(self):        """        在这里我们把file_path这个参数写死,直接保存到我们项目根目录的一个文件夹.\Screenshots下        """        file_path = os.path.dirname(os.path.abspath('.')) + '/screenshots/'        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))        screen_name = file_path + rq + '.png'        try:            self.driver.get_screenshot_as_file(screen_name)            logger.info("Had take screenshot and save to folder : /screenshots")        except NameError as e:            logger.error("Failed to take screenshot! %s" % e)            self.get_windows_img()    # 定位元素方法    def find_element(self, selector):        """         这个地方为什么是根据=>来切割字符串,请看页面里定位元素的方法         submit_btn = "id=>su"         login_lnk = "xpath => //*[@id='u1']/a[7]"  # 百度首页登录链接定位         如果采用等号,结果很多xpath表达式中包含一个=,这样会造成切割不准确,影响元素定位        :param selector:        :return: element        """        element = ''        if '=>' not in selector:            return self.driver.find_element_by_id(selector)        selector_by = selector.split('=>')[0]        selector_value = selector.split('=>')[1]        if selector_by == "i" or selector_by == 'id':            try:                element = self.driver.find_element_by_id(selector_value)                logger.info("Had find the element \' %s \' successful "                            "by %s via value: %s " % (element.text, selector_by, selector_value))            except NoSuchElementException as e:                logger.error("NoSuchElementException: %s" % e)                self.get_windows_img()   # take screenshot        elif selector_by == "n" or selector_by == 'name':            element = self.driver.find_element_by_name(selector_value)        elif selector_by == "c" or selector_by == 'class_name':            element = self.driver.find_element_by_class_name(selector_value)        elif selector_by == "l" or selector_by == 'link_text':            element = self.driver.find_element_by_link_text(selector_value)        elif selector_by == "p" or selector_by == 'partial_link_text':            element = self.driver.find_element_by_partial_link_text(selector_value)        elif selector_by == "t" or selector_by == 'tag_name':            element = self.driver.find_element_by_tag_name(selector_value)        elif selector_by == "x" or selector_by == 'xpath':            try:                element = self.driver.find_element_by_xpath(selector_value)                logger.info("Had find the element \' %s \' successful "                                "by %s via value: %s " % (element.text, selector_by, selector_value))            except NoSuchElementException as e:                logger.error("NoSuchElementException: %s" % e)                self.get_windows_img()        elif selector_by == "s" or selector_by == 'selector_selector':            element = self.driver.find_element_by_css_selector(selector_value)        else:            raise NameError("Please enter a valid type of targeting elements.")        return element    # 输入    def type(self, selector, text):        el = self.find_element(selector)        el.clear()        try:            el.send_keys(text)            logger.info("Had type \' %s \' in inputBox" % text)        except NameError as e:            logger.error("Failed to type in input box with %s" % e)            self.get_windows_img()    # 清除文本框    def clear(self, selector):        el = self.find_element(selector)        try:            el.clear()            logger.info("Clear text in input box before typing.")        except NameError as e:            logger.error("Failed to clear in input box with %s" % e)            self.get_windows_img()    # 点击元素    def click(self, selector):        el = self.find_element(selector)        try:            el.click()            logger.info("The element \' %s \' was clicked." % el.text)        except NameError as e:            logger.error("Failed to click the element with %s" % e)    # 或者网页标题    def get_page_title(self):        logger.info("Current page title is %s" % self.driver.title)        return self.driver.title    @staticmethod    def sleep(seconds):        time.sleep(seconds)        logger.info("Sleep for %d seconds" % seconds)
3. 页面对象中,百度主页的元素定位和简单的操作函数,页面类主要是元素定位和页面操作写成函数,供测试类调用。

baidu_homepage.py

# coding=utf-8from framework.base_page import BasePageclass HomePage(BasePage):    input_box = "id=>kw"    search_submit_btn = "xpath=>//*[@id='su']"     def type_search(self, text):        self.type(self.input_box, text)    def send_submit_btn(self):        self.click(self.search_submit_btn)
这里注意下元素定位写法,=>和base_page.py中find_element()方法元素定位切割有关系,网上有些人写根据逗号切割或者等号切割,在实际使用xpath定位,发现单独逗号或者单独等号切割都不精确,造成元素定位失败。

4. 测试类的写法举例

# coding=utf-8import timeimport unittestfrom framework.browser_engine import BrowserEnginefrom pageobjects.baidu_homepage import HomePageclass BaiduSearch(unittest.TestCase):    def setUp(self):        """        测试固件的setUp()的代码,主要是测试的前提准备工作        :return:        """        browse = BrowserEngine(self)        self.driver = browse.open_browser(self)    def tearDown(self):        """        测试结束后的操作,这里基本上都是关闭浏览器        :return:        """        self.driver.quit()    def test_baidu_search(self):        """        这里一定要test开头,把测试逻辑代码封装到一个test开头的方法里。        :return:        """        homepage = HomePage(self.driver)        homepage.type_search('selenium')  # 调用页面对象中的方法        homepage.send_submit_btn()     #调用页面对象类中的点击搜索按钮方法        time.sleep(2)        homepage.get_windows_img()  # 调用基类截图方法        try:            assert 'selenium' in homepage.get_page_title()  # 调用页面对象继承基类中的获取页面标题方法            print ('Test Pass.')        except Exception as e:            print ('Test Fail.', format(e))if __name__ == '__main__':    unittest.main()
homepage = HomePage(self.driver)
      上面这行代码要注意,意思是,到一个页面,第一件事情是初始化这个页面的一个页面对象实例。注意,一定要带self.driver,不然会报错,这个self.driver,可以这样理解:在当前测试类里面,self.driver是来自浏览器引擎类中方法得到的,在初始化一个页面对象的时候,也把这个来自浏览器引擎类的driver给赋值给当前的页面对象,这样,才能执行页面对象或者基类里面的相关driver方法。写多了selenium的自动化脚本,你会明白,最重要的是保持前后driver的唯一性。

测试结果:会在logs文件夹生成一个日志文件,也会在screenshots文件夹生成一个png图片。

你可能感兴趣的文章
vue中 不更新视图 四种解决方法
查看>>
MySQL 查看执行计划
查看>>
OpenGL ES 3.0(四)图元、VBO、VAO
查看>>
OpenGL ES 3.0(五)纹理
查看>>
OpenGL ES 3.0(八)实现带水印的相机预览功能
查看>>
OpenGL ES 3.0(九)实现美颜相机功能
查看>>
FFmpeg 的介绍与使用
查看>>
Android 虚拟机简单介绍——ART、Dalvik、启动流程分析
查看>>
原理性地理解 Java 泛型中的 extends、super 及 Kotlin 的协变、逆变
查看>>
FFmpeg 是如何实现多态的?
查看>>
FFmpeg 源码分析 - avcodec_send_packet 和 avcodec_receive_frame
查看>>
FFmpeg 新旧版本编码 API 的区别
查看>>
RecyclerView 源码深入解析——绘制流程、缓存机制、动画等
查看>>
Android 面试题整理总结(一)Java 基础
查看>>
Android 面试题整理总结(二)Java 集合
查看>>
学习笔记_vnpy实战培训day02
查看>>
学习笔记_vnpy实战培训day03
查看>>
VNPY- VnTrader基本使用
查看>>
VNPY - CTA策略模块策略开发
查看>>
VNPY - 事件引擎
查看>>