Python3学习笔记_web自动化基础十_20200725
pytest 和 unittest 共用
组合使用:
unittest: 数据驱动,前置后置条件
ddt
setUp tearDown
self.assertTrue()
pytest :运行用例
pytest.main()
自动收集
用例筛选
测试报告
测试插件
分开使用:
全用unittest
ddt数据驱动
setUp等前后置条件
unittest.main()运行用例
全用pytest:
paramatrize()数据驱动
fixture()前后置条件
assert 断言
pytest.main()运行用例
面试题:
pytest 有哪些好处?你为什么用pytest ,不用unittest?
好处:
自动收集
用例筛选
测试报告 【allure只支持pytest】
测试插件
断言也更加方便,fixture()比较灵活,以函数的形式自行导入
unittest过时了,pytest才是王道—这是不对的
pytest确实是功能比较强大,但是:
pytest是第三方库,而unittest是标准库
标准库:
不需要安装
不存在和Python版本不兼容的问题
一般来说,能用标准库,也不要用第三方库
第三方库:
需要安装
如果库未升级,存在和Python版本不兼容的问题
PageObject
PageObject 页面对象,我们会把某个网页(App页面)页面封装成对象
对象
-属性 ---元素定位器,URL,标题(DOM)
-方法 ---元素定位,点击,(做了某个动作,执行了某步操作)
只要是名词就是属性,动词就是方法
PageObject 原则
是不是所有的动作都需要单独封装成页面对象的方法?
-你可以封装
-但是不必要这么做
-遵循的原则:你用到了什么行为,就封装什么行为
封装的页面操作的返回值是:
1、self【如果执行完操作后,还停留在自己的页面,那就返回self】;
其他的页面对象【如果执行完操作后,跳转到其他页面,那就返回其他页面的对象】
2、如果你需要获取某个元素或者属性,就直接返回元素本身或者属性
3、如果一个操作可能会有多个结果,比如进行页面跳转或者本页面
根据结果封装成多个方法【这样搞的定义就复杂了,可以定义复杂,没关系,要的是调用简单】
注意:这种封装原则只是一个建议,不一定非要这样
链式调用
在这个测试用例里面,login_page调用了两个方法login 和 get_error_message,如果需要调用
login_page中的多个方法的时候,可以这样写:
login_page.login().get_error_message()
这样写的话,需要将代码改成链式的
找到login,将返回值改成 return self
面试题:
PageObject 的好处
可读性
如果不用,看代码,每一行都要看
如果使用的话,看到类名或者函数名,就知道是什么意思【本身就有注释功能】
如果是在使用PO模式时,还是不清楚到底是啥意思,可以
① 在调用的时候写一行注释,
② 具体的函数里面开头,写文档字符串
详细介绍这个函数是做什么用的,怎么使用,传什么参数,每个参数的意思
最后的返回值是什么,返回值代表什么意思
③ 如果还不明白,就把如果调用该函数也写清楚:
LoginPage(driver).login('lemon','123')
注意:一般注释都在文档字符串中,即定义的时候,调用的时候不会写很多注释,一般写到函数定义里
可维护性
如果一个页面,前端工程师改了,比如定位方式,直接找到对应的页面修改即可,其他代码不需要修改
如果不用 PO 的话,用的地方越多改的越多【前端页面框架的更换不影响我们的代码,只是渲染不同】
扩展性
随意的添加新的功能【当有新功能,新需求需要实现,更加方便】
可复用性
重复使用
页面逻辑和测试逻辑分离【面试官比较喜欢听的话】
测试用例的编写:【每一个测试用例函数的内容包括】
1、先初始化页面,测试用到的页面
2、测试步骤:页面的行为,PO当中的方法【调用页面逻辑
3、实际结果和预期结果比对
数据分组
如果是按照之前的直接读取Excel数据,出现的结果就是不管你有多少条用例,都会在第一个方法中执行
解决办法:数据分组
对Excel进行分组,
第一种:切片,
第二种:通过title,
第三种:通过多个表单的形式 login_success,login_error
data_error=HandlerAll.excel.read_sheet('login_error')
data_success=HandlerAll.excel.read_sheet('login_success')
比如:
@pytest.mark.parametrize('test_info',data_success)
@pytest.mark.success
def test_login_success_py(self,test_info,driver):
### 1、先初始化页面,测试用到的页面
login_page = LoginPage(driver)
# index_page=IndexPage(driver)
actual = login_page.login_success(
eval(test_info['data'])['username'],
eval(test_info['data'])['password']
).get_account_name()
assert actual == test_info['expected']
一个模块建一个Excel
分组的依据:
测试步骤不一样
保存用例,建议不要通过Excel去管理了
py文件
login_data.py 文件中的内容:
login_success=[
{"username":"18684720553","password":"python","expected":"我的帐户[python]"}
]
比如:测试用例
@pytest.mark.parametrize('test_info', login_success)
@pytest.mark.success
def test_login_success_01_py(self,test_info,driver):
### 1、先初始化页面,测试用到的页面
login_page = LoginPage(driver)
# index_page=IndexPage(driver)
actual = login_page.login_success(
login_success[0]['username'],
login_success[0]['password']
).get_account_name() # 链式调用
assert actual ==login_success[0] ['expected']
yaml文件
也支持字典的格式,不需要解析
locator 分层
login_btn_locator=('name','btn-special')
调用:加* 是为了拆包
self.driver.find_element(*self.login_btn_locator).click()
字典的形式:
login_btn_locator1 = {"by":"name", "value":"btn-special"}
调用:加 ** 是为了拆包,因为是字典的形式,要拆两次包,所以用两个*
self.driver.find_element(**self.login_btn_locator1).click()