pytest的使用
pytest
pytest是python的一种测试框架,也是python当中比较流行的测试框架,与python自带的unittest测试框架类似,它也可以组织多个用例去执行,但是比unittest框架使用起来更简洁,效率更高。
优点
1、容易上手,入门简单,文档丰富。
2、能够支持简单的单元测试和复杂的功能测试,经常结合selenium/appnium/requests等做自动化测试。
3、支持参数化
4、执行测试过程中可以将某些测试跳过(skip)
5、支持重复执行(rerun)失败的 case
6、pytest具有很多第三方插件,并且可以自定义扩展,pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)等;
安装
# 打开终端输入
pip install pytest # 从国外网站下载比较慢,容易出错
pip install pytest -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com # 从豆瓣网下载
查看pytest的版本
pytest --version
pytest使用规则
用Pytest写用例时候,一定要按照下面的规则去写,否则不符合规则的测试用例是不会执行的
文件名以 test_*.py
文件和*_test.py
以 test_ 开头的函数
以 Test 开头的类,不能包含__init__
方法
以 test_ 开头的类里面的方法
pytest示例代码
# 测试类
class TestScript:
def test_login_success(self):
print("测试登录成功")
# 断言
assert True
def test_login_error(self):
print("测试登录失败")
# 断言
assert False
执行:
打开 Terminal输入
pytest -vs TestScript
更换默认的用例运行测试库
python 有多个测试库可以用来编写测试用例,比如 unittest、pytest 等
默认的用例运行库为 unittest,如果想使用 pytest 或其它的库来运行测试用例,可以通过设置来更换。
PyCharm更换运行测试库步骤 :
Windows:Settings --> Tools --> Python Integrated Tools
Mac:Preferences --> Tools --> Python Integrated Tools
提示:pytest是可以兼容 unittest脚本的,使用 unittest编写的用例也能用 pytest 框架去运行
常用命令行参数
pytest -h 或 pytest --help 查看pytest命令行参数(帮助文档)
-s 输出打印信息
-v 显示详细的执行信息
-k 匹配用例名称
-x 失败停止执行
:: 按节点运行
# 执行具体的某一测试文件
pytest 脚本名称.py
# 执行所有的测试文件
pytest -sv
# 执行指定包或者文件夹下面的所有文件
pytest -sv 包名或文件夹名
# 执行测试用例名称包含phone的所有用例
pytest -k phone test_demo.py
# 执行测试用例名称 不包含phone的所有用例
pytest -s -k "not phone" test_demo.py
# 执行测试用例名称包含 phone 或 login 的所有用例
pytest -s -k "phone or login" test_demo.py
# 运行.py模块里面,测试类里面的某个方法
pytest test_demo.py::TestClass::test_one
用例执行状态
用例执行完成后,每条用例都有自己的状态,常见的状态有:
passed:测试通过,一般使用 . 来表示
failed:断言失败,一般使用 F 来表示
error:代码错误,一般使用 E 来表示
Fixture
pytest常用的Fixture方法:
setup():每个测试方法执行之前会执行
teardown():每个测试方法执行之后会执行
setup_class():在每个类执行之前会执行
teardown_class():在每个类执行后会执行
示例:
class TestFixture:
@staticmethod
def setup_class():
print("整个测试类开始前只执行一次setup_class")
@staticmethod
def teardown_class():
print("整个测试类结束后只执行一次teardown_class")
@staticmethod
def setup():
print("类里面的每个用例执行前都会执行setup")
@staticmethod
def teardown():
print("类里面的每个用例执行后都会执行teardown")
def test_login_success(self):
print("登录成功")
assert True
def test_login_error(self):
print("登录失败")
assert False
跳过测试用例
-
@pytest.mark.skip
无条件跳过执行测试用例,有可选参数reason可以指定,reason表示跳过的原因,会在执行结果中打印
-
@pytest.mark.skipif(condition, reason="")
希望有条件地跳过某些测试用例, condition为True时才会跳过用例
import random
import pytest
class TestSkip:
def test_one(self):
print("第一个测试用例!")
@pytest.mark.skip(reason="无条件跳过")
def test_two(self):
print("第二个测试用例!")
@pytest.mark.skipif(1 == random.randint(0, 1), reason="当随机数等于1时跳过")
def test_three(self):
print("第三个测试用例!")
def test_four(self):
print("第四个测试用例!")
参数化的场景
编写测试用例时,多个测试用例操作步骤一样,只有测试数据和期望结果不一样时,此时可以使用参数化。减少冗余代码。
参数化
语法:
@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
参数说明
1、argnames
含义:参数名字
格式:字符串"arg1,arg2,arg3"【需要用逗号分隔】
2、argvalues
含义:参数值列表
格式:一般数据类型为列表,如:[ val1,val2,val3 ]
如果只有 一个参数,里面则是值的列表如:
@pytest.mark.parametrize("username", ["yy", "yy2", "yy3", ...])
如果有 多个参数例,则需要用元组来存放值,一个元组对应一组参数的值,如:
@pytest.mark.parametrize("name, pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123"), ...])
其实也可以用字典保存,如:
@pytest.mark.parametrize("person", [{'name':'yy1','pwd':'123'},{'name':'yy2','pwd':'123'}, ...])
3、indirect
是否把参数当成函数去执行,当indirect=True 把参数当成一个函数去执行,默认值是False
4、ids
含义:用例的标题
格式:传一个列表,如:["", "", ""]
作用:可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性
强调:ids的长度需要与测试数据列表的长度一致
5、scope
如果指定,则表示参数的范围。
取值范围:session、package、module、class、function、None
import pytest
class TestParameters:
data = [
{"username": "张三", "password": "123", "expect_code": 200},
{"username": "李四", "password": "321", "expect_code": 400},
{"username": "王五", "password": "123456", "expect_code": 400}
]
@pytest.mark.parametrize("account", data)
def test_login(self, account):
print(account)
assert 200 == account["expect_code"]
示例:
验证两数结果是否与实际结果一致
import pytest
class TestData:
data = {(3, 5, 9), (2, 4, 6), (6, 9, 15)}
# 建议使用
@pytest.mark.parametrize("data", data)
def test_data(self, data):
print(data)
num1, num2, result = data
assert num1 + num2 == result
# 或
@pytest.mark.parametrize("num1, num2, result", data)
def test_data(self, num1, num2, result):
print(num1, num2, result)
assert num1 + num2 == result
参数化之笛卡尔积
多个集合的乘积。多组数据之间进行组合测试,总次数 = 每一组数据相乘
import itertools
import pytest
class TestCartesianProduct:
# 用户名列表
user_name_list = [
"张三",
"李四"
]
# 密码列表
password_list = [
"123456",
"654321"
]
# 验证码列表
captcha_list = [
"6666",
"8888"
]
@pytest.mark.parametrize("user_name", user_name_list)
@pytest.mark.parametrize("password", password_list)
@pytest.mark.parametrize("captcha", captcha_list)
def test_cartesian_product(self, user_name, password, captcha):
print(user_name, password, captcha)
# 或
# itertools:迭代器,对数据进行迭代
@pytest.mark.parametrize("user_name, password, captcha",
itertools.product(user_name_list, password_list, captcha_list))
def test_cartesian_product2(self, user_name, password, captcha):
print(user_name, password, captcha)
常用插件
以下插件需要通过 pip install 进行下载
失败重试
pip install pytest-rerunfailures
命令行参数后加 【--reruns n】或 【--reruns=n】 (n代表的是次数)
示例:
# reruns=2:失败重试2次
pytest -sv test_plugins.py --reruns=2
多断言插件
Pytest中可用assert断言, 但一个失败后面的断言将不再执行;pytest-assume可以实现对多个断言多重校验的
pip install pytest-assume
示例:
def test_assume(self):
pytest.assume(4 < 5)
pytest.assume(5 > 7)
pytest.assume(3 == 3)
print("测试完成")
执行顺序插件
unittest默认按字母顺序去执行的(小写英文 --> 大写英文 --> 0-9数字)用例之间的顺序是文件之间按照ASCLL码排序,文件内的用例按照从上往下执行。pytest框架默认执行方法的顺序是从上往下执行。如想自定义用例的执行顺序,可以通过安装第三方插件pytest-ordering
实现
pip install pytest-ordering
在测试方法上,使用该语句进行修改 【@pytest.mark.run(order=x)】,x 是一个数字,表示执行的顺序
html报告
pip install pytest-html
命令行参数后加 【--html=report/report.html】
示例:
pytest -sv test_plugins.py --html=reports/report.html
用例重复执行
测试过程中会出现一些偶现的bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来;pytest-repeat插件就能起到这个作用:重复执行测试用例。无论是否出错都执行指定的次数。
pip install pytest-repeat
命令行参数可以加 【--count=n】(n代表的是次数)
示例:
# 用例重复执行2次
pytest -sv test_plugins.py --count=2
注:将pytest的 -x 选项与 pytest-repeat 结合使用,以强制测试运行程序在第一次失败时停止。
pytest -sv test_plugins.py --count=2 -x
allure报告插件
pip install allure-pytest
生成allure测试报告的数据
pytest -s --alluredir [xml_report_path] --clean-alluredir
--clean-alluredir
:清除之前生成的数据
示例:
pytest test_plugins.py --alluredir=allure_data --clean-alluredir
生成allure测试报告
allure generate [xml_report_path] -o [html_report_path] --clean
--clean
:删除上次生成的报告
示例:
# -o:设置生成报告的目录名称,不指定默认为 allure-report
allure generate allure_data -o allure_reports --clean
Allure工具的安装及配置
下载地址: https://github.com/allure-framework/allure2/releases
解压后配置环境变量,如:D:\Test Program\allure-2.14.0\bin
生成测试报告,详见allure报告插件模块!
Git
Git安装
安装
Mac 自带git工具
Windows 需要下载,地址: https://git-scm.com/download/win
git 配置
Git安装之后需要进行一些基本信息设置
设置用户名:git config -- global user.name '你在码云上注册的用户名'
设置用户邮箱:git config -- global user.email '注册时候的邮箱'
注意:该配置会在码云主页上显示谁提交了该文件
配置ok之后,我们使用【git config --list】命令来查看是否配置成功
git 基础命令
git init # 初始化Git
git add . # 添加到缓存区
git rm . -r --cached # 从缓存区删除提交的文件,-r表示递归的删除,比如:文件夹撤销提交
git commit -m '' # 提交到本地仓库
git push -u origin master # 把本地仓库代码提交到远程仓库的master分支
把项目提交到码云
步骤:
1、cd 工程目录
2、git init
3、创建忽略文件
touch .gitignore
4、输入忽略内容(需要忽略的文件或文件夹):
.idea
.pytest_cache
allure_data
allure_report
__pycache__
5、git add .gitignore
6、git commit -m '添加忽略文件'
7、添加远程仓库
git remote add origin https://gitee.com/hbinBoy/test.git
8、推送到码云(注意:第一次执行需添加 -u origin master)
git push -u origin master
9、添加本地所有文件
git add .
10、提交本地文件
git commit -m '初始化工程'
11、再次推送到码云
git push