python测试框架unittest和pytest的区别
·
一、用例设计规则
| unittest | pytest |
|---|---|
| 测试文件必须先import unittest | 测试文件的文件名必须以"test_“开头,或者以”_test"结尾 |
| 测试类必须继承unittest.TestCase | 测试类命名必须以"Test"开头 |
| 测试函数必须以"test_"开头 | 测试函数名必须以"test"开头 |
| 测试类必须有unittest.main()方法 | 测试类里面不能使用" init "方法 |
总结:pytest是基于unittest衍生出来的新的测试框架,使用起来相对于unittest来说更简单、效率来说更高,pytest兼容unittest测试用例,但是反过来unittest不兼容pytest,所以说pytest的容错性更好一些!在使用交互逻辑上面pytest比unittest更全一些!
二、断言对比
| unittest | pytest | 断言描述 |
|---|---|---|
| unittest断言需要记很多断言格式 | pytest只需要用assert 来断言,assert 后面加需要断言的条件 | |
| assertEqual(a, b) | assert a==b | 判断a和b是否相等 |
| assertNotEqual(a, b) | assert a!=b | 判断a不等于b |
| assertTrue(a) | 判断a是否为Ture | |
| assertFalse(a) | 判断a是否为False | |
| assertIn(a, b) | assert ‘h’ in ‘hello’ | a 包含在b里面 |
| asserNotIn(a, b) | assert ‘h not’ in ‘hello’ | a 不包含在b里面 |
| assert f() ==4 | 判断f()方法返回值是否=4 | |
| assert 5>6 | 判断5>6为真 | |
| assert not xx | 判断xx不为真 |
三、前置后置
| unittest | pytest | 级别 |
|---|---|---|
| setup、teardown | @pytest.fixture(scope=‘function’) | 函数级别(每个用例执行前后执行) |
| setupclass、teardownclass | @pytest.fixture(scope=‘class’) | 类级别 (类里面所有用例开始前执行一次,所有用例执行完执行一次) |
| @pytest.fixture(scope=‘module’) | 模块级别(整个.py全部用例开始前执行/全部用例执行完后执行) | |
| @pytest.fixture(scope=‘package’) | 包级别 | |
| @pytest.fixture(scope=‘session’) | 会话级别 |
一般常用的是function和class
unittest:
class TestLogin(unittest.TestCase):
def setUp(self):
# 前置:访问登录页面
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get(CD.web_login_url)
self.lg = LoginPage(self.driver)
def tearDown(self):
#后置,关闭浏览器
self.driver.quit()
pytest:
conftest中定义多个fixture,一个fixture可以是另一个fixture的前后置,期间还是用field隔开前后置
@pytest.fixture(scope='class')
def access_web():
# 前置条件
global driver #声明driver为全局变量
print("========所有测试用例之前的,整个测试用例只执行一次=========")
driver=webdriver.Chrome()
driver.maximize_window()
driver.get(CD.web_login_url)
# 实例化LoginPage类
lg=LoginPage(driver)
# yield 同时可以返回值(driver,lg),相当于return,在使用返回值的时候直接用函数名
yield (driver,lg) #分割线:前面是前置条件、后面是后置条件
# 后置条件
print("========所有测试用例之后的,整个测试用例只执行一次=========")
driver.quit()
@pytest.fixture()
# @pytest.fixture()表示函数默认作用域access_web的作用域在函数上,执行测试用例时,每个函数都执行一次
def refresh_page():
global driver
# 前置操作
yield
# 后置操作
driver.refresh()
四、参数化
| unittest | pytest |
|---|---|
| 依赖ddt库 | 使用@pytest.mark.parametrize装饰器 |
unittest:
@ddt
# @pytest.mark.usefixtures("refresh_page")
class TestLogin:
#异常测试用例
@@data(*LD.phone_data)
def test_login_0_user_wrongFormat(self,data):
#前置:访问登录页面
#步骤:输入用户名、密码、点击
# 调用login方法
self.lg.login(data['user'],data['pwd'])
# 断言:首页当中能否找到“退出”按钮
#等待10秒
#找元素 //div[@class="navbar-account"]
self.assertEqual(self.lg.get_errorMsg_form_loginArea(),data['check'])
pytest:
class TestLogin:
#异常测试用例
@pytest.mark.parametrize("data",LD.phone_data)
def test_login_0_user_wrongFormat(self,data,access_web):
#前置:访问登录页面
#步骤:输入用户名、密码、点击
# 调用login方法
access_web[1].login(data['user'],data['passwd'])
# 断言:首页当中能否找到“退出”按钮
#等待10秒
#找元素 //div[@class="navbar-account"]
assert access_web[1].get_errorMsg_form_loginArea(),data['check']
五、测试用例分类执行、顺序执行
| unittest | pytest |
|---|---|
| 默认执行全部用例,也可以通过加载testsuit,执行部分用例 | 可以通过@pytest.mark来标记类和方法,pytest.main加入参数("-m")可以只运行标记的类和方法 |
| 用例名称可用1,2等标记,例:test_case1,test_case2 | 安装:pip install pytest-ordering,在测试方法上加下面装饰器 @pytest.mark.last—最后一个执行 @pytest.mark.run(order=1)—第几个执行 |
六、测试报告
| unittest | pytest |
|---|---|
| 使用HTMLTestRunnerNew库 | 通过pytest-html生成html格式报告,通过allure生成方案(很详细) |
七、失败重跑
| unittest | pytest |
|---|---|
| 无此功能 | pytest支持用例执行失败重跑,pytest-rerunfailures插件 |
总结
总体来说,unittest用例格式复杂,兼容性无,插件少,二次开发方便。pytest更加方便快捷,用例格式简单,可以执行unittest风格的测试用例,无须修改unittest用例的任何代码,有较好的兼容性。pytest插件丰富,可用于用例出错重跑,测试报告详细,用力分类执行,断言方便,可用于设备并行执行,效率更高。
更多推荐
所有评论(0)