web自动化之基础内容六(全网最详细,po模式)-第六天

1.简单的po模式

po模式,简单来说,就是page object(页面对象)
我们做ui自动化的时候,会遇到很多的页面
为了维护方面,我们可以将每一个页面封装成一个class

po模式,其实没有任何新的知识点融入,只不过是将面向对象的思想融入进来了

基本代码示例(简单的po模式)

from selenium import webdriver
class loginPage:
    def __init__(self, url):
        # 创建浏览器驱动对象,这里是打开浏览器
        self.driver = webdriver.Chrome("E:\愤怒吧小鸟\chromedriver-win64\chromedriver.exe")
        # 访问网址
        self.driver.get(url)
        #用户名输入框
        self.user_name_input=self.driver.find_element_by_name("username")
        #密码输入框
        self.password_input=self.driver.find_element_by_name("password")
        #登录按钮
        self.login_button=self.driver.find_element_by_css_selector("button")
    def logn(self):
        self.user_name_input.send_keys("libai")
        self.password_input.send_keys("opmsopms123")
        self.login_button.click()
LP = loginPage("http://127.0.0.1:8088/")
LP.logn()

注意:上段代码如果加上一个界面刷新的操作,就会报错(陈旧的元素引用异常),selenium关于StaleElementReferenceException异常的出现以及解决方案可参考以下链接:

web自动化异常,selenium.common.exceptions.StaleElementReferenceException(陈旧的元素引用异常)-CSDN博客

即为了避免“StaleElementReferenceException异常”,代码改为如下模式:

更改的思路可参考上面的链接

from selenium import webdriver
class loginPage:
    def __init__(self, url):
        # 创建浏览器驱动对象,这里是打开浏览器
        self.driver = webdriver.Chrome("E:\愤怒吧小鸟\chromedriver-win64\chromedriver.exe")
        # 访问网址
        self.driver.get(url)

    # 用户名输入框
    def user_name_input_box(self):
        return self.driver.find_element_by_name("username")
    # 密码输入框
    def password_input_box(self):
        return self.driver.find_element_by_name("password")

    # 登录按钮
    def login_button_box(self):
        return self.driver.find_element_by_css_selector("button")

    def logn(self):
        self.driver.refresh()
        self.user_name_input_box().send_keys("libai")  #封装成方法,元素赋值和操作元素中间就不会有界面刷新了
        self.password_input_box().send_keys("opmsopms123")
        self.login_button_box().click()
LP = loginPage("http://127.0.0.1:8088/")
LP.logn()

2.优化po模式的代码-初级版本

第一步骤的代码的优化(是避免了taleElementReferenceException异常之后的代码优化

思路:(1)driver路径,url等抽离出来,形成一个配置文件-setting.py

           (2)把driver抽离出来(公用的)-myDriver.py

            (3)页面模块-loginPage.py

项目构造:

day06-初级版本-setting.py

                        -myDriver.py

                        -loginPage.py

setting.py代码

# 域名
url = "http://127.0.0.1:8088/"

# driver 路径
drverPath = {
    "Chrome": "E:\愤怒吧小鸟\chromedriver-win64\chromedriver.exe",
    "Firefox": ""
}

user_name = "libai"
password = "opmsopms123"

myDriver.py代码:

from selenium import webdriver
driver = webdriver.Chrome("E:\愤怒吧小鸟\chromedriver-win64\chromedriver.exe")

思考:如何保证driver唯一;

解决方法:定义一个工具类

思考:如何再类中让变量保持唯一呢(可用类方法的变量

myDriver.py优化后的代码

from day06.初级版本.setting import drverPath, url
from selenium import webdriver
class Driver:
    """
    任何地方需要用到浏览器驱动对象,直接调用此类下的 get_driver函数,获取返回值即可
    且 get_driver 函数保证了我们的 driver 唯一
    类成员存放在类中,是唯一的,普通成员存放在对象中,不是唯一的;
    所以把driver成员创建为类成员(加了一个注解@classmethod)
    """
    # 初始化为空
    driver = None

    @classmethod
    def get_driver(cls, browser_name):
        # 如果 cls.driver 为 None,则证明不存在,进入if代码块去创建
        # 如果 cls.driver 不为 None,则证明存在,不需要进入if代码块创建,可直接返回
        if cls.driver is None:  #cls.driver是唯一的
            if browser_name == "Chrome":
                cls.driver = webdriver.Chrome(drverPath["Chrome"])
            elif browser_name == "Firefox":
                cls.driver = webdriver.Firefox(drverPath["Firefox"])

            # 最大化窗口,
            cls.driver.maximize_window()
            # 访问默认的网页
            cls.driver.get(url)

        return cls.driver

if __name__ == '__main__':
    #调用两次get_driver,只会打开一次浏览器,说明代码逻辑正确(因为把driver成唯一的)
    Driver.get_driver("Chrome")
    Driver.get_driver("Chrome")

运行结果:

只会打开一次浏览器

loginPage.py代码:

from day06.初级版本.myDriver import Driver
from day06.初级版本.setting import user_name, password


class LoginPage:
    def __init__(self):
        # 创建浏览器驱动对象,这里是打开浏览器
        self.driver = Driver.get_driver("Chrome")

    # 用户名输入框
    def user_name_input_box(self):
        return self.driver.find_element_by_name("username")

    # 密码输入框
    def password_input_box(self):
        return self.driver.find_element_by_name("password")

    # 登录按钮
    def login_button_box(self):
        return self.driver.find_element_by_css_selector("button")


class LoginPageAction(LoginPage):
    """
    我们一般会将页面当中一些常用的动作,会重复使用的动作
    抽离出来,写成一个个的函数,封装在一个页面动作类当中
    页面动作类,继承对应的页面类
    """

    def logn(self):
        self.driver.refresh()
        self.user_name_input_box().send_keys(user_name)
        self.password_input_box().send_keys(password)
        self.login_button_box().click()

"""
将页面分为 页面元素类,与页面动作类
若以后,只是逻辑修改了,只需要改动动作类即可,而不必关系元素定位
若是元素定位发生了变化,只需要修改页面元素类即可,执行动作、逻辑,都不必关心
"""

if __name__ == '__main__':
    LPA = LoginPageAction()
    LPA.logn()

运行结果:

界面可登录成功

3.优化po模式的代码-抽离出basepage版本

思考:界面肯定不止一个,所以新增一个basePage.py模块,该模块是将页面通用的方法,抽离出来封装起来

结构如下图

setting.py和myDriver跟初级版本一样,代码没变

basePage.py代码

from day06.抽离出basepage的版本.myDriver import Driver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from day06.抽离出basepage的版本.setting import time_out, poll_time


class BasePage:
    """
    basepage 是将一些页面通用的方法,抽离出来封装起来
    """
    def __init__(self):
        # 获取浏览器驱动对象
        self.driver = Driver.get_driver("Chrome")

    def get_element(self, locator):
        """
        显示等待,查找元素
        :param locator: 要求传入的参数是一个元组,表示元素定位方法和表达式
        :return: 单个的元素对象
        """
        WebDriverWait(
            # 传入浏览器对象
            driver=self.driver,
            # 传入超时时间
            timeout=time_out,
            # 设置轮询时间
            poll_frequency=poll_time).until(
            EC.visibility_of_element_located(locator)
        )

        return self.driver.find_element(*locator)  # *locator是解包
    def get_elements(self, locator):
        """
        显示等待,查找元素
        :param locator: 要求传入的参数是一个元组,表示元素定位方法和表达式
        :return: 元素列表
        """
        WebDriverWait(
            # 传入浏览器对象
            driver=self.driver,
            # 传入超时时间
            timeout=time_out,
            # 设置轮询时间
            poll_frequency=poll_time).until(
            EC.visibility_of_element_located(locator)
        )

        return self.driver.find_elements(*locator)

解包的概念,参考以下链接

python之打包、解包_python中打包和解包的区别-CSDN博客

loginPage.py代码

from day06.抽离出basepage的版本.basePage import BasePage
from day06.初级版本.setting import user_name, password
from selenium.webdriver.common.by import By

class LoginPage(BasePage):

    # 用户名输入框
    def user_name_input_box(self):
        return self.driver.find_element_by_name("username")

    # 密码输入框
    def password_input_box(self):
        #假设密码输入框按钮需要用到显示等待,将代码改成如下所示即可
        return self.get_element((By.NAME, "password"))

    # 登录按钮
    def login_button_box(self):
        return self.driver.find_element_by_css_selector("button")


class LoginPageAction(LoginPage):
    """
    我们一般会将页面当中一些常用的动作,会重复使用的动作
    抽离出来,写成一个个的函数,封装在一个页面动作类当中
    页面动作类,继承对应的页面类
    """

    def logn(self):
        self.driver.refresh()
        self.user_name_input_box().send_keys(user_name)
        self.password_input_box().send_keys(password)
        self.login_button_box().click()


"""
将页面分为 页面元素类,与页面动作类
若以后,只是逻辑修改了,只需要改动动作类即可,而不必关系元素定位
若是元素定位发生了变化,只需要修改页面元素类即可,执行动作、逻辑,都不必关心
"""

if __name__ == '__main__':
    LPA = LoginPageAction()
    LPA.logn()

结果:

界面登录成功 

注意:如需要代码,可在资源绑定中自行下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布凡哦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值