8.webUI入门及单例模式

webUI入门及单例模式

回归测试

版本迭代,进行优化,重新部署了新环境,只是前端页面发生了改变,api没有变化,只需要把host更换成新地址就可以
重新执行用例,用例通过

自动化类型分配

  • 什么情况下使用api,什么情况下使用ui?
    • 前后端分离项目,API是针对后端的,可能前端开发速度没有那么快,后端已经开发完成,就可以使用API进行逻辑验证
    • 只有后端,比如数据交互中心,必须使用API进行测试
    • 一般来说,通过ui实现的都可以使用api来完成,一般前端都是需要调用后端来完成的,但是通过api测试,就绕过了前端了,前端的问题就无法发现了,比如页面的布局,文字提示之类的
    • ui既可以验证前端,也可以验证后端,因为通过操作前端,前端调用后端,可以对后端的逻辑进行测试
    • 如果前端测试发现了问题,再去分析是前端的还是后端的问题
    • 通过抓包来判断,如果发现数据发送没有问题,后端返回有异常,就是后端的问题,那后端没有问题,前端有异常,那就是前端的问题了(排除网络其他因素影响),一般优先判断后端的问题
    • UI比较适合测试流程,比如订单类的业务,经过好几个页面,很复杂,一系列的操作,如果使用api来测试,那我们就需要写几十个api,各种调用,写得很复杂,那如果我们通过ui来实现,通过页面上的点点点,填写表单,选择一下,就可以实现了;如果使用api,那就要先查询,再操作,先查询,再操作,要写很多api,很麻烦,如果通过ui来实现,那就简单了,因为UI就是模拟人的操作,点击一下,选择一下,输入一下就可以完成了
    • API的侧重点是对数据的校验,而UI的侧重点是针对流程

了解业务场景

  • 新增日程:填写日程信息,新增成功,分派日程给其他用户
  • 其他用户登录系统,首页查看日程

webUI设计模式

PO模式一般适用于大型系统,我们只需要把页面的元素封装好放到对应的配置文件里面就可以了,页面比较多,页面元素频繁变动
PO库的实现

  • 以面向对象形式封装常用UI操作
  • 合理规划层级结构
  • 抽取元素定位到配置文件

在pylib的webUI目录下,新建一个文件common.py,里面定义通用类BasePage,页面通用操作方法

class BasePage:
    def click(self):
        pass

    def input_text(self):
        pass

在pylib的webUI目录下,新建一个文件business.py,里面定义业类

#定义业务操作类
class LoginPage(BasePage):
    pass

点击和输入,都需要对页面元素进行操作,对页面操作就需要知道元素的定位方法,使用什么定位方法呢,id,name,css,xpath
我们不能给别人规定死,那怎么办呢,就需要写一个通用的定位方法
同时对元素进行操作,需要通过driver进行,需要先实例化一个driver

def __init__(self):
    self.driver=webdriver.Chrome()

但是这样会打开多个浏览器,每次实例化就打开一个浏览器,一个对象就是一个浏览器,多次实例化就打开多个浏览器

解决打开多个浏览器的方法

方法一:
外面实例化好driver,然后通过传参进来

class BasePage:
    def __init__(self,driver):
        self._driver=driver

    def click(self,locator):
        self._driver.find_element(*locator).click()

    def input_text(self,locator,text):
        self._driver.find_element(*locator).send_keys(text)


#定义业务操作类
class LoginPage(BasePage):
    pass

class MainPage(BasePage):
    pass

if __name__ == '__main__':
    from selenium import webdriver
    driver=webdriver.Chrome()
    LoginPage(driver)
    MainPage(driver)

方法二:
单例模式

单例模式

非单例模式
图 6

日常见到的init方法是否产生对象?初始化方法并不产生对象
实例化就像新生儿一样,初始化就像给新生儿穿衣服一样,并不会产生新的
init方法必须先有对象才能使用,那什么方法可以产生对象呢?
new 方法来产生对象,同时init方法不能有返回值,new必须有返回值
如果我们需要实现单例模式,就必须从new这个地方下手
首先判断当前类是否有实例存在,存在就返回当前实例
hasattr()#相当于python的反射,如果当前对象存在某个属性(方法或者字段)就返回true,反之就是false
cls也是一个对象,由元类来产生,类控制对象,元类控制类
object类是所有类继承的祖先类

class Single:
    def __new__(cls, *args, **kwargs):#new产生对象,并且需要定义返回值
        #首先判断当前类是否有实例存在,如果存在就直接返回,否则就创建一个新的实例再返回
        if hasattr(cls,'_isinstace'):#hasattr相当于python的反射,如果当前类存在某个属性就返回true,否则返回false
            return cls._isinstace
        else:
            cls._isinstace=object.__new__(cls)
            return cls._isinstace
    def __init__(self):#初始化是否产生对象?不产生对象,init方法不可以有返回值
        pass

if __name__ == '__main__':
    assert Single()==Single()

看看子类是不是也具有相同特性?子类也具有父类的特性

class Child(Single):
    pass

if __name__ == '__main__':
    assert Child()==Child()

如果else里面没有其他语句,else可以省略,因为我们用了return,后面的语句就不会执行了

class Single:
    def __new__(cls, *args, **kwargs):#new产生对象,并且需要定义返回值
        #首先判断当前类是否有实例存在,如果存在就直接返回,否则就创建一个新的实例再返回
        if hasattr(cls,'_isinstace'):#hasattr相当于python的反射,如果当前类存在某个属性就返回true,否则返回false
            return cls._isinstace
        cls._isinstace=object.__new__(cls)
        return cls._isinstace
    def __init__(self):#初始化是否产生对象?不产生对象,init方法不可以有返回值
        pass
class Child(Single):
    pass

if __name__ == '__main__':
    assert Child()==Child()

至此单例模式已经调试完成,我们可以把当前代码放到pulgins模块下面
接着在common模块下面创建一个生成webdriver类,继承Single类来实现创建浏览器

class BasePage:
    def __init__(self):
        self._driver=WebdriverCreater().get_browser()

    def click(self,locator):
        self._driver.find_element(*locator).click()

    def input_text(self,locator,text):
        self._driver.find_element(*locator).send_keys(text)

class WebdriverCreater(Single):
    def get_browser(self):
        self._driver=webdriver.Chrome()
        self._driver.implicitly_wait(10)
        return self._driver

到business中测试
if name == 'main':
LoginPage()
MainPage()

发现还是打开多个浏览器
分析发现,类已经是单例模式,但是get_browser(),不是单例模式,调用一次就生成一个浏览器
解决:使用单例模式的思想继续改造

class WebdriverCreater(Single):
    def get_browser(self):
        #如果存在就直接返回,没有就创建一个再返回
        if hasattr(self,'_driver'):
            return self._driver
        self._driver=webdriver.Chrome()
        self._driver.implicitly_wait(10)
        return self._driver

查看BY方法

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"
原文地址:https://www.cnblogs.com/xiehuangzhijia/p/15168975.html