selenium- PO模式

一、思想:

PO模式:
  PageObject,从最初自动化是基于QTP来实现的,通过录制的形式,自动生成脚本,通过定义对象库来实现对页面的元素的收集,升级到关键字驱动的形式来实现自动化(通过封装对元素的操作,来实现关键字驱动),再升级到PageObject,将系统以页面来进行区分,针对不同的页面,基于页面的元素及当前页面所实现的业务,将其定义为一个完整的页面对象。然后对这个页面对象进行操作。在PO中,通过分层的形式,来定义出不同页面的操作内容:

  1、BasePage:基础层,用于提供最为底层的功能,让其他页面对象可以直接进行继承
  2、Page:页面层,用于提供元素的获取,各个元素的操作方法的封装
  3、业务层:通过这一层的调用,传入参数,进行自动化的运行

优点:
1、针对于指定的被测业务系统的流程,执行自动化时非常简便
缺点:
1、对于多个系统的复用性相对较差

二、PO实现实例

下面,以安居客登录为例

2.1 定义公用功能部分 basepage.py

# -*- coding:utf-8 -*-
 
from public.common.log import Logger
from config import globalparam
from selenium.common.exceptions import NoSuchElementException
import os
import time
 
logger = Logger(logger='BasePage').getlog()
class BasePage:
    """测试基类"""
 
    def __init__(self, driver):
        self.driver = driver
 
    @staticmethod
    def isdisplayed(element):
        """元素是否存在"""
        value = element.is_displayed()
        return value
 
    @staticmethod
    def sleep(secondes):
        """强制等待"""
        time.sleep(secondes)
        logger.info('Sleep for %d seconds' % secondes)
 
    def open_url(self,url):
        self.driver.get(url)
 
    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.info("Faile to quit the browser with %s" %e)
 
    def get_img(self):
        """截图"""
        rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
        screen_name = os.path.join(globalparam.test_img_path,'%s.png' % rq)
        # noinspection PyBroadException
 
        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_img()
 
    def find_element(self, selector):
        """定位元素"""
        by = selector[0]
        value = selector[1]
        element = None
        if by in ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']:
            # noinspection PyBroadException
            try:
                if by == 'id':
                    element = self.driver.find_element_by_id(value)
                elif by == 'name':
                    element = self.driver.find_element_by_name(value)
                elif by == 'class':
                    element = self.driver.find_element_by_class_name(value)
                elif by == 'tag':
                    element = self.driver.find_element_by_tag_name(value)
                elif by == 'link':
                    element = self.driver.find_element_by_link_text(value)
                elif by == 'plink':
                    element = self.driver.find_element_by_partial_link_text(value)
                elif by == 'css':
                    element = self.driver.find_element_by_css_selector(value)
                elif by == 'xpath':
                    element = self.driver.find_element_by_xpath(value)
                else:
                    logger.error('Not find the element')
                logger.info("Had  find the element! ,by %s via value :%s " %(by,value))
                # logger.info('元素定位成功。定位方式:%s,使用的值%s:' % (by, value))
 
                return element
            except NoSuchElementException as e:
                logger.error("NoSuchElementException %s " %e)
                self.get_img()  # 调用截图
        else:
            logger.error('Please enter a valid type of targeting elements')
 
    def type(self, selector, value):
        """输入内容"""
        element = self.find_element(selector)
        # element.clear()
        logger.info('clear input_box')
        # noinspection PyBroadException
        try:
            element.send_keys(value)
            logger.info('input is:%s' % value)
        except BaseException:
            logger.error('Failed to type in input box', exc_info=1)
            self.get_img()
 
    #输入并确认
    def type_enter(self,selector,value):
        try:
            element = self.find_element(selector)
            element.send_keys(value)
            time.sleep(1)
            element.send_keys(Keys.ENTER)
        except Exception as e:
            logger.info("Failed to type_and_enter with %s" % e)
            self.get_img()
            raise
 
    def click(self, selector):
        """点击元素"""
        element = self.find_element(selector)
        # noinspection PyBroadException
        try:
            element.click()
            logger.info('"The element \' %s \' was clicked." % element.text')
        except BaseException:
            display = self.isdisplayed(element)
            if display is True:
                self.sleep(3)
                element.click()
                logger.info('The element was clicked')
            else:
                self.get_img()
                logger.error('Failed to click the element', exc_info=1)
 
    def right_click(self,selector):
        """右击元素"""
        element = self.find_element(selector)
        try:
            ActionChains(self.driver).context_click(element).perform()
            logger.info("The element \' %s \' was clicked." % element.text)
        except NameError as e:
            logger.error("Failed to right_click the element with %s" % e)
            self.get_img()
 
    def double_click(self,selector):
        """双击"""
        element = self.find_element(selector)
        try:
            ActionChains(self.driver).double_click(element).perform()
        except Exception as e:
            logger.info("Failed to double_click the element with %s" % e)
            self.get_img()
            raise
 
    def move_to_element(self,selector):
        """鼠标移到元素上"""
        try:
            element = self.find_element(selector)
            ActionChains(self.driver).move_to_element(element).perform()
        except Exception as e:
            logger.info("Failed to move_to_element the element with %s" % e)
            self.get_img()
            raise
 
    def drag_and_drop(self, element_selector,ta_selector):
        """拖拽"""
        try:
            element_drag = self.find_element(element_selector)
            taget_drop = self.find_element(ta_selector)
            ActionChains(self.driver).drag_and_drop(element_drag,taget_drop).perform()
        except Exception as e:
            logger.info("Failed to drag_and_drop the element with %s" % e)
            self.get_img()
            raise
 
    def refresh(self):
        """刷新"""
        self.driver.refresh()
 
    def submit(self,selector):
        """submit"""
        try:
            element = self.find_element(selector)
            element.submit()
        except Exception as e:
            logger.info("Failed to submit the element with %s" % e)
            self.get_img()
 
    def get_attribute(self,selector,attribute):
        """获取元素属性"""
        try:
            element = self.find_element(selector)
            return element.get_attribute(attribute)
        except Exception as e:
            logger.info("Failed to get_attribute  with %s" % e)
            self.get_img()
            raise
 
    def get_text(self,selector):
        """获取元素的文本信息"""
        try:
            return self.find_element(selector).text
        except Exception as e:
            logger.info("Failed to get_text  with %s" % e)
            self.get_img()
 
    def dismiss_alert(self):
        """弹窗 alert——取消"""
        self.driver.switch_to.alert.dismiss()
 
 
    def clear(self,selector):
        """清除文本框"""
        element = self.find_element(selector)
        try:
            element.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_img()
 
    def use_js(self, js):
        """调用js"""
        # noinspection PyBroadException
        try:
            self.driver.execute_script(js)
            logger.info('successful,js contents is:%s' % js)
        except BaseException:
            logger.error('js error', exc_info=1)
 
    def switch_menue(self, parentelement, secelement, targetelement):
        """三级菜单切换"""
        self.sleep(3)
        # noinspection PyBroadException
        try:
            self.driver.switch_to_default_content()
            self.click(parentelement)
            logger.info('成功点击一级菜单:%s' % parentelement)
            self.click(secelement)
            logger.info('成功点击二级菜单:%s' % secelement)
            self.click(targetelement)
            logger.info('成功点击三级菜单:%s' % targetelement)
        except BaseException:
            logger.error('切换菜单报错', exc_info=1)
 
 
    def switch_ifarme(self, selector):
        """切换ifarme"""
        element = self.find_element(selector)
        # noinspection PyBroadException
        try:
            self.driver.switch_to.frame(element)
            logger.info('Successful to switch_to_frame! ')
        except BaseException:
            logger.error('Failed to  switch_to_frame', exc_info=1)
 
    def quit_iframe(self):
        """退出当前iframe"""
        self.driver.switch_to_default_content()
 
    def get_title(self):
        """获取title"""
        title = self.driver.title
        logger.info('Current page title is:%s' % title)
        return title
 
    def quit(self):
        """关闭浏览器"""
        self.driver.quit()
        logger.info('quit the browser')

2.2 页面封装 login.py

每个操作封装成一个个小组件.

这里需要注意的是

self.findElement(*self.pwtab_loc).click()
参数中,带*号,为什么要带星号,因为我们参数是一个元组.中间有By.ID这样的对像,如果不加会有问题.
#coding:utf-8
from selenium.webdriver.common.by import By
from selenium import webdriver
class LoginPage(BasePage):
    #定位元素
    username_loc = (By.ID,"pwdUserNameIpt")
    password_loc = (By.ID,"pwdIpt")
    pwtab_loc = (By.ID,"pwdTab")
    btn_loc = (By.ID,"pwdSubmitBtn")
    switchFrame = 0
    #打开页面
    def open_url(self):
        self.page_open(self.base_url,self.page_title)

    #切换frame
    def switch_to_f(self):
        self.switch_to_frame(self.switchFrame)

    #切换登录方式
    def switch_login(self):
        self.findElement(*self.pwtab_loc).click()

    #输入用户名
    def inputUserName(self,username):
        self.findElement(*self.username_loc).send_keys(username)
    #输入pndc
    def inputPassWord(self,password):
        self.findElement(*self.password_loc).send_keys(password)

    #单击登录按钮
    def clickLogin(self):
        self.findElement(*self.btn_loc).click()

if __name__=="__main__":
        driver = webdriver.Firefox()
        driver.implicitly_wait(30)
        url = 'https://login.anjuke.com/login/form?history=aHR0cHM6Ly9zaGFuZ2hhaS5hbmp1a2UuY29tLw=='
        username ='123'
        password=''
        Login_page = LoginPage(url,driver,u'登录')
        Login_page.open_url()
        Login_page.switch_to_f()
        Login_page.switch_login()
        Login_page.inputUserName(username)
        Login_page.inputPassWord(password)
        Login_page.clickLogin()

2.3 pytest 用例封装

posted @ 2021-02-25 16:07  dongye95  阅读(340)  评论(0编辑  收藏  举报