zoukankan      html  css  js  c++  java
  • 40 web自动化 (复杂的测试用例编写方法 basepage)

    目录

    1.复杂用例的前置条件 、测试步骤

    2.basepage

    正文  83 28min

     1.复杂用例的前置条件 、测试步骤---------以  投资用例 为例子来详细说明

     根据测试步骤来进行编写

    ①编写投资的测试用例 test_invest.py  ------之前的test_login.py测试用例编写的是TestLogin类,在投资测试用例中换个方式,直接写成函数

    """投资用例"""
    
    def test_invest_fail_not_10_times():
        """投资失败:输入金额不是10的整数倍 的测试用例
        测试步骤:
        1.前置条件:先登录 conftest
             ---账户有余额
             ---有标
        2.首页:点击 【抢投标】
        3.投标详情页:输入投标金额
        4.详情页:获取结果
        """

    根据test_invest_fail_not_10_times()函数的docstring,投标之前的前置条件,除了登录,还需要:账户必须有余额(充值),系统有标可以投(建标、审核),那么这些条件是否都需要通过web自动化去实现???

    ---------不需要!!!

    可以实现前置条件的方式比如:接口实现、修改数据库、手工添加、web自动化等

    web自动化实现:可以每次执行之前,都自动化充值、或者加标或者,一次性充值足够的钱。但是,用web自动化实现这些前置条件,比较麻烦又比较困难,

    所以,可以通过手工的方式实现前置条件。

    总之一句话,这些前置条件能够满足,就OK了。------------(只要能够实现这个前置条件,就可以)

    ①-1前置条件--登录

    在conftest中,封装登录的前置条件--------在login测试用例中,实现了test_login_success()的方法,在前置封装的登录方法中直接调用即可

    """固定文件名conftest.py,存储所有的测试夹具fixture"""
    import pytest
    from middware import handler
    from middware.pages.login import LoginPage
    from data.login_data import data_success
    
    @pytest.fixture()
    def driver():
        from selenium import webdriver
    
        ##前置条件
        #打开浏览器
        driver = webdriver.Chrome()
    
        # 设置隐性等待 等待的时间就可以放在config中,直接参数调用
        wait_time = handler.HandlerMiddle.yaml_data["selenium"]["wait_time"]
        driver.implicitly_wait(wait_time)
    
        yield driver
    
        #后置清理
        driver.quit()
    
    @pytest.fixture()
    def login(driver):
        """登录"""
    
        #前置条件:登录成功
        user_info = data_success[0] #登录成功数据的第一条,实现登录即可
        #登录成功后进入首页
        index_page = LoginPage(driver).get().login_success(username=user_info["username"],
                                              password=user_info["password"])
        #返回首页
        yield index_page
    
        #无后置清理工作

    继续按测试步骤执行第二步:抢投标

    但是并没有封装抢投标的方法,则返回到index页面进行抢投标方法的封装

    ②首页 点击:抢投标

    定位【抢投标】按钮,来确定元素定位方式:

     index.py文件中封装抢投标的方法:

    """登录成功页面"""
    from selenium.webdriver.common.by import By
    from middware.handler import HandlerMiddle
    
    
    class IndexPage:
        """登录成功"""
    
        #首页的URL
        URL  =HandlerMiddle.yaml_data["host"] + "/Index.html"
    
        #用户账号locator
        user_accout_locator = (By.XPATH,'//a[@href="/Member/index.html"]')
    
        #抢投标按钮locator
        invest_btn_locator = (By.CLASS_NAME,'btn-special')
    
        #初始化driver
        def __init__(self,driver):
            self.driver = driver
    
        #打开首页
        def get(self):
            self.driver.get(self.URL)
            return self
    
        #获取登录成功的用户名
        def get_account_name(self):
            web_element=self.driver.find_element(*self.user_accout_locator)
            return web_element.text
    
        #点击抢投标
        def click_invest_btn(self):
            self.driver.find_element(*self.user_accout_locator).click()
            # 返回投标详情页
            return InvestPage(self.driver)

    点击抢投标进入的是投标详情页----》所以抢投标的方法,返回的是投标详情页

    投标详情页 没有封装,下面进行投标详情页的封装:----invest.py

    ③页面详情页-输入用户金额、点击投标

     invest.py中 封装的类InvestPage中:

    不需要URL -----因为每个详情页是不一样的,详情页是动态变化的(URL是变化的)

    不需要get()方法----因为无法直接访问该详情页

    下面进行投标金额输入框的元素定位:输入用户金额 ----->定位【投标】按钮并点击

    定位投标按钮(不是10的整数倍)进行断言

    invest.py封装好如下:

    """登录成功页面"""
    from selenium.webdriver.common.by import By
    from middware.handler import HandlerMiddle
    
    
    class InvestPage:
        """投资详情页"""
        #输入用户金额
        user_invest_input_locator = (By.CLASS_NAME,'form-control')
    
        #投标 按钮
        invest_btn_locator = (By.CLASS_NAME,'btn-special')
    
        #初始化driver
        def __init__(self,driver):
            self.driver = driver
    
        def enter_user_money(self,money):
            self.driver.find_element(*self.user_invest_input_locator).send_keys(money)
            return self
    
        def get_error_info(self):
            """错误信息:输入金额不是10的整数倍"""
            ele = self.driver.find_element(*self.invest_btn_locator)
            return ele.text

     再次回到test_invest.py完善测试用例:

    """投资用例"""
    
    from middware.pages.index import IndexPage
    from middware.handler import HandlerMiddle
    
    def test_invest_fail_not_10_times(login):
        """投资失败:输入金额不是10的整数倍 的测试用例
        测试步骤:
        1.前置条件:先登录 conftest
             ---账户有余额
             ---有标
        2.首页:点击 【抢投标】
        3.投标详情页:输入投标金额
        4.详情页:获取结果
        """
        # driver = login
        # actual_result = IndexPage(driver).click_invest_btn().enter_user_money(8).get_error_info()
    
        actual_result = IndexPage(login).click_invest_btn().enter_user_money(8).get_error_info()
    
        #断言
        try:
            assert  actual_result == "请输入10的整数倍"
        except AssertionError as e:
            HandlerMiddle.logger.error("测试用例不通过!")
            raise e

    84 节 

    运行上面的代码,出现【抢投标】按钮元素定位成功,但是点击【抢投标】按钮,并没有生效。

    原因:是前后2个页面,定位class属性的value值是一样的,value=‘btn-special’

    总结:

    如何避免出现上下2个页面,同样的元素定位方式重合的问题?

    ①等待  即等待下一个页面加载完成(在下一个页面进行操作时,在初始化中加入加入等待)

        ----time.sleep()

        ----get(),调用get(),但是不是每个页面都有get()方法,比如投资详情页是变化的,每页get()方法,就无法用

        ----显性等待

             已经加载这个页面,在初始化中完成这个页面

    ②检查相邻页面的元素定位方式是不是一样的。 ------需要重复查询元素,比较麻烦,不建议使用

    在login 、index、invest的页面初始化中,添加显性等待:

    比如:indexpage中:

    title_contains:表示页面标题包含的内容

    """登录成功页面"""
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    from middware.handler import HandlerMiddle
    from middware.pages.invest import InvestPage
    
    
    class IndexPage:
        """登录成功"""
        title = "项目详情"
    
        #首页的URL
        URL  =HandlerMiddle.yaml_data["host"] + "/Index.html"
    
        #用户账号locator
        user_accout_locator = (By.XPATH,'//a[@href="/Member/index.html"]')
    
        #抢投标按钮locator
        invest_btn_locator = (By.CLASS_NAME,'btn-special')
    
        #初始化driver
        def __init__(self,driver):
            self.driver = driver
            try:
                WebDriverWait(self.driver,timeout=20).until(
                    expected_conditions.title_contains(self.title)
                )
            except:
                HandlerMiddle.logger.error("您的操作可能没有进入对应的页面:{},可能会有异常!".format(self.title))

    2.BasePage     ---  每个页面的通用方法放在一个公共页面类当中

    1)页面行为的分类:

        ---某个页面的特定的行为    定位登录元素   

        ----每个页面的通用行为     定位某个元素可见

    比如等待某个元素可见,就属于通用行为:

        def wait_element_visible(self,locator,timeout = 20,poll = 0.5):
            """显式等待元素可见
            :return elem
            """
            ele = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until(
                expected_conditions.visibility_of_element_located(locator)
            )
            return ele

    单独放在某个页面里面,就不合理。应该放在通用类basepage中更为合理

    2)搭建basepage框架

     在pages中新建basepage.py文件,将属于的通用方法移至basepage.py中。

    如下:如果别的页面要调用wait_element_visible方法,只要调用该页面的方法即可。

    """通用的方法"""
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    
    class BasePage:
    
        def __init__(self,driver):
            self.driver = driver
    
        def wait_element_visible(self,locator,timeout = 20,poll = 0.5):
            """显式等待元素可见
            :return elem
            """
            ele = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until(
                expected_conditions.visibility_of_element_located(locator)
            )
            return ele

    那么,别的页面调用的时候,之前写的是页面自己的方法,用的是self.wait_element_visible(),-----如何继续实现这样的调用?======继承

    在需要调用wait_element_visible()方法的页面中,直接继承basepage类即可。

    其次,将login、index、invest页面中初始化----->等待页面加载,也可以移至basepage,

    但是要注意,basepage里面只是一个公共类,不能进行初始化页面,那么这个title怎么获取?

    将title设置为basepage类中的类属性即可。

    公共的方法basepage就是所谓的selenium_handler.py中的SeleniumHandler,既然是公共方法,不以项目为转移的,那么就可以放在common中了。

    这里的BasePage类就是SeleniumHandler啦

     common中的selenium_handler.py:如下

    """通用的方法"""
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    from middware.handler import HandlerMiddle
    
    
    class BasePage:
        title = None
    
        def __init__(self,driver):
            self.driver = driver
    
            try:
                WebDriverWait(self.driver,timeout=20).until(
                    expected_conditions.title_contains(self.title)
                )
            except:
                HandlerMiddle.logger.error("您的操作可能没有进入对应的页面:{},可能会有异常!".format(self.title))
    
        def wait_element_visible(self,locator,timeout = 20,poll = 0.5):
            """显式等待元素可见
            :return elem
            """
            ele = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until(
                expected_conditions.visibility_of_element_located(locator)
            )
            return ele

    85节

    总结basePage:----思想:类的继承

    ①不以项目为转移,每个页面都能直接调用,的页面的封装;放在一个类中,这个类就是basepage

    ②basepage是每个页面的父类(可以直接通过self直接调用basepage类中的方法)

    下面在basepage中继续封装一些通用的方法:等待元素可以被点击、鼠标操作、窗口滚动等

    """通用的方法"""
    from selenium.webdriver import ActionChains
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    
    from middware.handler import HandlerMiddle
    
    
    class BasePage:
        title = None
    
        def __init__(self,driver):
            self.driver = driver
    
            try:
                WebDriverWait(self.driver,timeout=20).until(
                    expected_conditions.title_contains(self.title)
                )
            except:
                HandlerMiddle.logger.error("您的操作可能没有进入对应的页面:{},可能会有异常!".format(self.title))
    
        def wait_element_visible(self,locator,timeout = 20,poll = 0.5):
            """显式等待元素可见
            :return elem
            """
            ele = WebDriverWait(self.driver,timeout=timeout,poll_frequency=poll).until(
                expected_conditions.visibility_of_element_located(locator)
            )
            return ele
    
        def wait_element_clickable(self,locator,timeout = 20,poll = 0.5):
            """等待某个元素被点击"""
            ele = WebDriverWait(self.driver,timeout=timeout).until(expected_conditions.element_to_be_clickable(locator))
            return self
    
        def wait_element_presence(self,locator,timeout = 20,poll = 0.5):
            """等待某个元素可见"""
            ele = WebDriverWait(self.driver,timeout=timeout).until(expected_conditions.presence_of_all_elements_located(locator))
            return self
    
        def click(self,locator):
            """点击某个元素"""
            ele=self.wait_element_visible(locator).click()
            return self
    
        def enter_info(self,locator,value=None):
            """输入信息"""
            ele = self.wait_element_presence(locator).send_keys(value)
            return self
    
    
        def window_scroll(self,width=None,height=None):
            """窗口滚动"""
            if width==None:
                width="0"
            if height == None:
                height="0"
    
            js_code = "window.scrollTo({},{})".format(width,height)
            self.driver.execute_script(js_code)
            return self
    
        def mouse_moveto(self,locator):
            """鼠标操作 移动到某个元素"""
            ele= self.driver.find_element(*locator)
            ActionChains(self.driver).move_to_element(ele).perform()
            return self
    
        def switch_iframe(self,locator,timeout=20):
            """切换到iframe"""
            WebDriverWait(self.driver,timeout=timeout).until(expected_conditions.frame_to_be_available_and_switch_to_it(locator))
            return self
  • 相关阅读:
    Android应用程序请求SurfaceFlinger服务创建Surface的过程分析
    和菜鸟一起学linux总线驱动之初识i2c驱动主要结构
    和菜鸟一起学linux之container_of实例
    和菜鸟一起学linux总线驱动之初识spi驱动主要结构
    和菜鸟一起学android4.0.3源码之按键驱动短长按功能
    和菜鸟一起学linux总线驱动之初识i2c总线协议
    程序溢出的基础和原理
    Network Information Detection程序作品+源代码
    Network Information Detection程序作品+源代码
    渗透asp后门源代码
  • 原文地址:https://www.cnblogs.com/ananmy/p/13594471.html
Copyright © 2011-2022 走看看