zoukankan      html  css  js  c++  java
  • 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"
    
  • 相关阅读:
    linux 经常使用网络命令
    ExtJS学习--------Ext.Element中其它操作方法学习
    对“使用MyEclipse,写的jsp代码因有汉字而无法保存”问题的解决
    SQL之case when then用法
    SQL之CASE WHEN用法详解[1]
    [SQL case when的两种用法]
    在delphi中生成GUID
    在delphi中生成GUID/自动获取临时表名......
    Delphi中Owner和Parent的区别
    Delphi处理数据网格DBGrid的编辑框 获取还没有提交到数据集的字段文本
  • 原文地址:https://www.cnblogs.com/xiehuangzhijia/p/15168975.html
Copyright © 2011-2022 走看看