一、pytest框架的使用
安装 Pytest
#安装
pip install pytest
#验证安装
pytest --version #展示当前安装的版本
pip install pytest-html #安装原生态报告模板(自带的,不好用)
pip install pytest-html #用于生成美观的测试报告
pytest用例编写规则
(1)模块名必须以test_开头或者_test结尾(如: test_ab.py)
(2)测试类必须以Test开头,并且不能有init方法。
(3)测试方法必须以test开头
pytest用例执行
关于 pytest 执行测试,有两种方式,一种是命令行通过 pytest 这个命令执行,另外在代码中可以通过 pytest.main() 这个方法来执行测试。
命令行模式
在测试用例文件所在的目录中,运行以下命令来执行 pytest 测试用例
#运行所有
pytest
#指定模块
pytest test_login.py
#指定目录:pytest 目录路径
pytets ./testcase/test_web.py::TestLogin::test_001
主函数模式
#运行所有
pytest.main()
#指定模块
pytest.main(["test_login.py"]) #"test_login.py"为文件的路径
#指定目录
pytest.main(["目录路径"])
#通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组成
pytest.main(["./testcase/test_web.py::TestLogin::test_001"])
运行 pytest 测试用例时,可以使用一些参数来控制测试的行为
-v 参数可以显示详细的测试结果;
-s 参数可以打印测试用例中的 print 语句输出;
-k <expression> 参数可以只运行符合表达式 <expression> 的测试用例;
--html=<file> 参数可以将测试结果输出到 HTML 报告中;
具体的参数列表可以使用 pytest --help 命令查看。
pytest用例分类执行
可以通过@pytest.mark来标记类和方法,pytest.main加入参数("-m”可以只运行标记的类和
方法)
import pytest
@pytest.mark.smoke
def test_login():
# 测试登录功能
pass
@pytest.mark.regression
def test_search():
# 测试搜索功能
pass
@pytest.mark.regression
def test_checkout():
# 测试结账功能
pass
如上,我们使用 @pytest.mark.xxx 的方式来为测试用例打标记,其中 xxx 是自定义的标记名称。例如,test_login 用 @pytest.mark.smoke 标记,test_search 和 test_checkout 用 @pytest.mark.regression 标记。
然后,我们可以使用 -m 参数来指定要执行的标记。例如,执行所有 smoke 标记的测试用例,可以使用以下命令:
pytest -m smoke
执行所有 regression 标记的测试用例,可以使用以下命令:
pytest -m regression
如果要执行多个标记的测试用例,可以使用逗号分隔。例如,执行同时具有 smoke 和 regression 标记的测试用例,可以使用以下命令:
pytest -m "smoke,regression"
测试用例的执行顺序
pytest:从上到下依次运行
pytest可以通过给用例添加修饰器来改变默认的顺序
@pytest.mark.run(order=<num>)
装饰器来指定测试用例的执行顺序,其中 <num> 为一个整数,表示测试用例的执行顺序,数字越小,越先执行。
import pytest
@pytest.mark.run(order=2)
def test_case1():
assert 1 + 1 == 2
@pytest.mark.run(order=1)
def test_case2():
assert 2 * 3 == 6
在上面的代码中,test_case2 的执行顺序为 1,test_case1 的执行顺序为 2。因此,当运行这两个测试用例时,先执行 test_case2,再执行 test_case1。
二、pytest用例前置和后置setup/teardown
在pytest中,我们可以通过fixture来实现用例的前置和后置操作。fixture是pytest提供的一种装饰器,用于在测试用例执行前后执行一些操作。
具体来说,我们可以定义一个fixture函数,然后在测试用例中通过装饰器的方式来调用这个fixture函数。这个fixture函数可以返回一些数据,也可以执行一些操作,例如连接数据库、打开文件等。
夹具的作用域
在 pytest 中,夹具(fixture)可以具有不同的作用域(scope),控制它们的生命周期和作用范围。
在 pytest 中,fixture 的作用域有四种,分别是 function(模块级)、class(类级)、module(方法级) 和 session(函数级)。
使用 @pytest.fixture() 装饰器,并通过 scope 参数指定了作用域为 function。
function
fixture 的作用域为 function,表示 fixture 每个测试函数都会调用一次。这是默认的作用域。
import pytest
@pytest.fixture
def my_fixture():
return 'fixture'
def test_my_test(my_fixture):
assert my_fixture == 'fixture'
class
fixture 的作用域为 class,表示 fixture 在一个测试类中所有测试函数执行前都会调用一次。
import pytest
@pytest.fixture(scope='class')
def my_fixture():
return 'fixture'
class TestClass:
@classmethod
def setup_class(cls):
cls.my_fixture = my_fixture
def test_my_test(self):
assert self.my_fixture == 'fixture'
def test_another_test(self):
assert self.my_fixture == 'fixture'
module
fixture 的作用域为 module,表示 fixture 在一个测试模块中所有测试函数执行前都会调用一次。
import pytest
@pytest.fixture(scope='module')
def my_fixture():
return 'fixture'
def setup_module(module):
# 运行模块级别夹具
module.my_fixture = my_fixture
def test_my_test():
assert my_fixture == 'fixture'
def test_another_test():
assert my_fixture == 'fixture'
session
fixture 的作用域为 session,表示 fixture 在整个测试会话中只会被调用一次,即所有测试模块执行前只会被调用一次。
# conftest.py
import pytest
@pytest.fixture(scope='session')
def my_fixture():
return 'fixture'
def session_start():
# 运行 session 级别夹具
my_fixture = my_fixture()
fixture操作的实例
例如,我们需要在每个测试用例执行前都连接数据库,并在测试用例执行后关闭数据库连接,我们可以这样定义fixture:
import pytest
import pymysql
@pytest.fixture(scope="module")
def db():
# 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='123456', database='testdb')
yield conn
# 关闭数据库连接
conn.close()
如上,我们定义了一个名为db的fixture函数,它的作用是连接数据库。这个fixture函数的作用域是module,也就是整个测试模块中只会执行一次。
然后我们可以在测试用例中通过装饰器的方式来调用这个fixture函数:
def test_query(db):
cursor = db.cursor()
cursor.execute('select * from users')
result = cursor.fetchall()
assert len(result) == 3
这里我们定义了一个名为test_query的测试用例,它的参数是db,也就是我们刚刚定义的db fixture函数。在这个测试用例执行前,pytest会自动调用db fixture函数,连接数据库。在测试用例执行完毕后,pytest会自动调用db fixture函数,关闭数据库连接。