提升之路--从0开始学web自动化(8)--深入分层&数据驱动&断言

po封装的原则

遵循原则的话会达到更好的效果

-页面封装里不应该包含断言或者测试操作,不然就做不到页面操作和测试操作分离

-唯一可以操作页面中的测试是判断一个元素是否能找到

-不需要封装所有页面操作,用到什么就封装什么

-页面封装也可以使用组建方式.比如导航栏,侧边栏等在多个页面重复出现的,也可以封装成一个组件类,页面使用的时候只需要继承这个组件的类

-当一个操作引发不同的效果,应该使用多个自动化测试用例函数,比如login_failed,login_success

如登录页面操作:

当登录失败时候,会有错误信息返回,这一逻辑都是相同的,所以我们可以把登录失败的数据都存储到测试数据.py文件里,用列表嵌套字典的方式,相当于读取excel返回的结果

登录成功的时候,页面会跳转,不能再用上面登录失败的逻辑,所以要重新使用一个新的测试用例函数,专门用来测试登录成功,会把登录成功的数据存储到py文件,用另外一个变量存储.由于页面已经跳转,断言时候而需要用到的po页面,是home_page,不是login_page

ui自动化测试数据驱动

数据驱动应用的场景是,测试步骤一样,但是数据不一样

在ui自动化测试中,因为页面操作的逻辑不像接口,有很多不同的变化,逻辑不一样,断言不一样,所以不能只用一个测试用例函数进行自动化测试.也就代表测试数据不能只放在一个excel的表单中,如果使用多个表单,读取起来不方便

数据驱动使用分组的方式,把不同的列表数据,驱动到逻辑不同的测试用例函数

fail_data = login_fail
success_data = login_success

class TestLogin:

    @pytest.mark.parametrize("case_info",fail_data)
    def test_login(self,case_info,login_page):

        #获得测试数据
        usename = case_info["username"]
        password = case_info["password"]
        expected = case_info["expected"]

        #使用类里的实例方法
        login_page.get_url()
        #使用登录方法
        login_page.login(usename,password)
        #获取错误信息
        actual = login_page.get_error_tips()
        #断言
        assert actual == expected

 

    @pytest.mark.parametrize("case_info",success_data)
    def test_login_success(self,case_info,login_page,home_page):

        #获得测试数据
        usename = case_info["username"]
        password = case_info["password"]
        expected = case_info["expected"]
        #使用类里的实例方法
        login_page.get_url()
        login_page.login(usename,password)

        #断言当前页面url是否跳转到预期的页面
        assert home_page.is_loaded()

        #断言元素的值是否与预期相符
        #定位class - avatar,断言title属性的值
        assert  home_page.get_username() == expected

ui自动化测试断言

ui自动化测试中,因为逻辑不一样,所以断言也有不同,我们常用的断言方式有:

-获取当前页面的错误信息,与预期比较

-获取某个元素的属性值,判断是否与预期相同

 

-判断页面是否已经加载完成,判断页面是否已经跳转到预期url 

 因为加载页面由于网络原因不一定马上就能跳转,有可能还停留在之前的页面,所以需要加入显性等待

 显性等到后如果url包含跳转后的字符串,即为true

 

basepage

作用:对selenium 封装浏览器操作进行二次封装,让整个浏览器的操作变得更加容易使用

po只能用在当前的项目,每个项目开始进行ui自动化之前都需要封装各种页面po,而basepage类能用在不同的项目

把浏览器和页面最通用的操作,都封装到basepage类里,这样可以被其他页面对象(po)使用,使其他po里的代码变得简洁

其他页面对象(po)直接继承basepage,后期重点维护basepage 操作

当po页面的方法的参数出现locator时,就代表传入的参数是一个元组,里面是元素定位表达式

在basepage中初始化对象,就不用在po页面上初始化了,每次在测试用例函数里的参数传入夹具之后,夹具的返回值是该po类的实例,而po类继承BasePage类,所以创建实例时候也要传入浏览器对象作为参数

class BasePage:

    def __init__(self,browser:Chrome):
        self.browser = browser

页面操作封装

-获取当前url

   def is_loaded(self,url,timeout=10):
        '''判断某个url是否被加载'''
        return WebDriverWait(self.browser, timeout).until(when.url_contains(url))

在po页面调用这个方法的时候要用超继承,因为父类有同名的方法

    def is_loaded(self):
        '''页面已经被加载'''
        #超继承,因为父类有同名方法,不然就是自己调用自己
        return super().is_loaded(self.url)

-输入框操作

locator代表定位元素的表达式(元组),words代表输入的内容

    def send(self,locator,words):
        '''输入框操作'''
        wait = WebDriverWait(self.browser, timeout=10)
        condiction = when.visibility_of_element_located(locator)
        input_el = wait.until(condiction)
        input_el.send_keys(words)

-清空输入框操作

当出现查找元素的时候,locator需要加*,表示拆分元组,当出现显性等待条件时就不用

    def clear(self,locator):
        '''清空输入框'''
        el = self.browser.find_element(*locator)
        el.clear()

在po页面调用

    def login(self,username,password):
        locator =("name", "account")
        # 清空输入框
        self.clear(locator)
        #输入用户名
        self.send(locator,username)

-加载页面

    def goto(self,url):
        '''加载页面'''
        if url.find("https://") != -1:
            return self.browser.get(url)
        else:
            return self.browser.get(host + url)

-文件上传

    def upload(self,filename):
        # 文件上传
        btn = self.browser.find_element(By.XPATH, '//input[@type="file"]')
        btn.send_keys(filename)

-获取某个元素的属性值

    def get_element_attribute(self,locator,name):
        '''获取某个元素的属性'''
        #name是属性名
        el = self.browser.find_element(*locator)
        return el.get_attribute(name)

-设置/修改元素属性

    def set_element_attribute(self,locator,value):
        '''设置元素属性'''
        el = self.browser.find_element(*locator)
        #value是想要在传入的值
        js = f"arguments[0].value='{value}'"
        self.browser.execute_script(js,el)

-获取错误信息

    def get_error_tips(self,locator):
        '''获取错误信息'''
        wait = WebDriverWait(self.browser, timeout=10)
        condiction = when.visibility_of_element_located(locator)
        el = wait.until(condiction)
        return el.text

-切换到iframe

    def iframe(self,locator):
        '''切换到iframe'''
        wait = WebDriverWait(self.browser,timeout=10)
        addiction = when.frame_to_be_available_and_switch_to_it(locator)
        wait.until(addiction)

-从iframe切换回主页

    def switch_to_default(self):
        '''从iframe切换回主页面'''
        self.browser.switch_to.default_content()

-页面滚动

    def scroll_to_bottom(self):
        '''页面滚动到底部'''
        js = "window.scrollTo(0,document.body.scrollHeight)"
        self.browser.execute_script(js)

-元素滚动至可见

    def scroll_view(self,locator):
        '''滚动到元素可见'''
        el = self.browser.find_element(*locator)
        js = "arguments[0].scrollIntoView()"
        self.browser.execute_script(js,el)

鼠标操作封装

-点击(显性等待)

    def click(self,locator):
        '''显性等待点击操作,用于按钮'''
        wait = WebDriverWait(self.browser, timeout=10)
        condition = when.element_to_be_clickable(locator)
        el = wait.until(condition)
        #点击操作最好用ActionChains
        ActionChains(self.browser).click(el).perform()

-点击(普通)

    def nomal_click(self,locator):
        '''没有显性等待点击,用于点击图标等'''
        el = self.browser.find_element(*locator)
        ActionChains(self.browser).click(el).perform()

-双击

    def double_click(self,locator):
        '''双击'''
        wait = WebDriverWait(self.browser, timeout=10)
        condition = when.element_to_be_clickable(locator)
        el = wait.until(condition)
        # 点击操作最好用ActionChains
        ActionChains(self.browser).double_click(el).perform()

-右击

   def right_click(self,locator):
        '''右击'''
        wait = WebDriverWait(self.browser, timeout=10)
        condition = when.element_to_be_clickable(locator)
        el = wait.until(condition)
        # 点击操作最好用ActionChains
        ActionChains(self.browser).context_click(el).perform()

-拖动

    def drag_and_drop(self,locator1,locator2):
        '''拖拽'''
        wait = WebDriverWait(self.browser, timeout=10)
        condition = when.element_to_be_clickable(locator1)
        el1 = wait.until(condition)

        wait = WebDriverWait(self.browser, timeout=10)
        condition = when.element_to_be_clickable(locator2)
        el2 = wait.until(condition)

        ActionChains(self.browser).drag_and_drop(el1,el2).perform()

-悬停

    def hover(self,locator):
        '''鼠标悬停'''
        el = self.browser.find_element(*locator)
        ActionChains(self.browser).move_to_element(el).perform()

键盘操作封装

-回车

    def enter(self):
        '''回车'''
        ActionChains(self.browser).send_keys(Keys.ENTER).perform()

-全选

    def select_all(self):
        '''全选'''
        ac = ActionChains(self.browser)
        ac.key_down(Keys.CONTROL).send_keys("a").key_up(Keys.CONTROL).perform()

-复制

    def copy(self):
        '''复制'''
        ac = ActionChains(self.browser)
        ac.key_down(Keys.CONTROL).send_keys("c").key_up(Keys.CONTROL).perform()

-粘贴

    def paste(self):
        '''粘贴'''
        ac = ActionChains(self.browser)
        ac.key_down(Keys.CONTROL).send_keys("v").key_up(Keys.CONTROL).perform()

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值