1、pytest介绍
pytest是一个成熟的全功能的Python测试框架
特点:
(1)简单灵活易上手,参数化、测试用例skip和xfail以及自动失败重试
(2)支持简单单元测试及复杂的功能测试,也可以结合selenium和appnium做自动化测试,结合requests模块做接口自动化测试
(3)具有较多的第三方插件,可自定义扩展,比如pytest-allure、pytest-xdist多CPU分发
(4)Jenkins集成
2、测试用例的识别与运行
测试文件:必须以test_开头或以_test结尾
test_*.py
*_test.py
用例识别
Test*类包含的所有test_*方法(测试类不能带有__init__方法)
不在class中的所有的test_*方法
pytest也可以执行unittest框架写的用例和方法
3、安装pytest
安装命令:pip install pytest
升级命令:pip install -U pytest
查看版本:pytest --version
4、测试文件的执行方式
方式一:配置pytest解释器,直接run
方式二:命令行执行,pytest 文件名 -v,参数-v显示出详细日志
方式三:文件里包含入口函数main,命令行执行 python 文件名
(1)在setting中指定pytest解释器
(2)命令行执行的命令
-v 表示详细展示
-k 选中测试用例执行
pytest -k test_b -v
pytest -k 'test_a or test_b' -v
(3)main入口执行
if __name__ == '__main__': pytest.main(['test_a.py'])
5、pytest运行测试文件示例
配置Python运行环境
运行代码示范
# content of test_sample.py
import pytest
def inc(x):
return x + 1
def test_answer1():
assert inc(3) == 5
def test_answer2():
assert inc(4) == 5
class TestDemo:
def test_1(self):
print("测试1")
def test_2(self):
print("测试2")
if __name__ == '__main__':
pytest.main(["test_a.py::TestDemo","-v"])
6、pytest的参数化
@pytest.mark.parametrize(argnames,argvalues)
argnames要参数化的变量 string ,list tuple
argvalues参数化的值 list,list[tuple]
代码示例1
import pytest
def func(x):
return x + 1
@pytest.mark.parametrize(('a', 'b'), [(1, 2), (2, 4)])
def test_answer(a, b):
assert func(a) == b
if __name__ == '__main__':
pytest.main(['test_a.py'])
代码示例2
argnames要参数化的变量 string ,list tuple
argvalues参数化的值 list,list[tuple]
import pytest
class TestData:
# @pytest.mark.parametrize('a,b',[(10,20),(15,13),(3,9)])
# @pytest.mark.parametrize(('a,b'),[(10,20),(15,13),(3,9)])
@pytest.mark.parametrize(['a','b'],[(10,20),(15,13),(3,9)])
def test_data(self,a,b):
print(a+b)
7、 测试用例的前置条件
(1)创建前置条件的方法,例如:登录
(2)加上装饰器@pytest.fixture()
代码示例
@pytest.fixture()
def login():
username = "dema"
print("登录成功")
return username
class TestDemo:
def test_1(self, login):
print(f"测试1 用户是{login}")
def test_2(self):
print("测试2")
def test_3(self,login):
print(f"测试3 用户是{login}")
if __name__ == '__main__':
pytest.main(["test_a.py::TestDemo", "-v"])
8、使用yaml传参
yaml语法
(1)等价['10','20','30']
- 10
- 20
- 30(2)等价{‘by’:'id','locator':'name','action':'click'}
by:id
locator:name
action:click#嵌套
(3)等价[{'by’:'id'},{'locator':'name'},{'action':'click'}]
-
- by:id
- locator:name
- action:click
代码示例
import pytest
import yaml
class TestData:
@pytest.mark.parametrize(("a", "b"), yaml.safe_load(open("./data.yaml")))
def test_addnum(self, a, b):
print(a + b)
# assert 30 == a + b
if __name__ == '__main__':
pytest.main("test_data.py::TestData", "-v")
yaml传参方式
yaml.safe_load(open("文件名"))
代码示例二:
import pytest
import yaml
class TestDemo:
@pytest.mark.parametrize(("env"), yaml.safe_load(open("data2.yaml")))
def test_demo(self, env):
if "test" in env:
print("这是测试环境")
elif "dev" in env:
print("这是开发环境")
print(env["test"])
return env
if __name__ == '__main__':
pytest.main("test_demo.py::TestDemo", "-v")
-
test: 127.0.0.1
10、数据驱动
概念:数据改变从而驱动自动化测试的执行,最终引起测试结果的改变,简单来说就是参数化的应用
应用方式:数据量较大时,可以使用结构化文件来进行数据存储与读取
应用场景:web、APP、接口自动化测试
测试步骤、测试数据、配置项 等方面的数据驱动
11、allure介绍
轻量级灵活的支持多语言的测试报告工具
多平台的report框架
可提供详细的测试报告、测试步骤、log
为管理层提供high level的统计报告
Java语言开发,支持pytest、JS、PHP等
可集成到Jenkins
12、allure安装及使用
注意:更新环境变量要重启pycharm
windows(带有java环境)
https://github.com/allure-framework/allure2/releases
下载allure2.7.zip
解压后进入bin目录,运行allure.bat
把bin目录加入到PATH环境变量
使用allure
安装allure-pytest插件
pip install allure-pytest
13、命令行运行
在测试执行收集结果
pytest 【测试文件】 -s -q --alluredir=./result/1 生成文件夹1,其下是json文件
14、查看测试报告
方法一:测试完成在线查看报告,会直接打开默认浏览器显示当前测试报告
allure serve ./result/1
方法二:先生成报告,再打开报告,需要启动Tomcat服务
生成报告
allure generate ./result/ -o ./report/ --clean (覆盖路径需要加--clean)
打开报告
allure open -h 127.0.0.1 -p 8883 ./report/
15、allure常用场景
在测试报告中看到测试功能、测试子功能、测试步骤、测试附加信息
import allure
@Feature 测试功能
@story 测试子功能
@step 测试步骤细节
@attach 测试文本信息
代码示例
import pytest
import allure
@allure.feature("登录")
class TestLogin:
@allure.story("登录成功")
def test_login_success(self):
print("测试用例登录成功")
@allure.story("登录失败")
def test_login_fail(self):
print("测试用例登录失败")
@allure.story("用户名缺失")
def test_login_username_lose(self):
print("测试用例用户名缺失")
@allure.story("密码缺失")
def test_login_password_lose(self):
with allure.step("点击用户名"):
print("输入用户名")
with allure.step("点击密码"):
print("输入密码")
print("点击登录")
with allure.step("点击登录之后登录失败"):
assert "1" == 1
print("登录失败")
16、allure指定某个模块运行
指定登录模块运行
pytest test_a.py --allure-features "登录模块"
指定子功能运行
pytest -v test_a.py --allure-story "登录成功"
-v是打印详细信息 可以不加
17、allure中feature与story的关系
@allure.fearture和@allure.story 类似于父子关系
前者相当于一个功能模块,类似于testsuite
后者相当于这个功能或者模块下的一个分支功能,类似于testcase
18、allure中step
应用场景:测试过程中的每个步骤,放在具体的逻辑方法中,也可放在关键步骤
例如:在app/web的自动化测试中,建议每次切换到一个新的页面就当成一个step
@allure.step 只能以装饰器的形式放在类或者方法上面
with allure.step() 可以放在测试用例方法里面,测试步骤的代码要被此语句包含
19、allure关联测试用例和bug
关联测试用例 :直接给出测试用例的地址链接
关联bug,在执行时需要加参数
--allure-link-pattern=issue:http://www.mytesttracker.com/issue/{}
执行命令
pytest test_alluredemo_link_issue_case.py
--alluredir=./result/5
--allure-linkpattern=issue:http://www.mytesttracker.com/issue/{}
查看测试报告
allure serve ./result/5
在测试报告的behavior查看详细的测试结果,点击链接可以跳转到链接网址
网址:http://www.mytesttracker.com/issue/140
即{}里面的值是@allure.issue('140') 里面的140
代码示例
import allure
@allure.link("https://www.baidu.com/", name="百度链接")
def test_with_link():
print("链接百度地址")
test_case_link = "https://github.com/ceshiren/HogwartsSDET12"
@allure.testcase(test_case_link, "登录用例")
def test_with_testcese_link():
print("测试用例链接")
# --allure-link-pattern=issue:http://www.mytesttracker.com/issue/{}
@allure.issue("140", "这是一个issue") #140是传给上一行的大括号的值
def test_with_issue():
pass
20、按重要性级别进行范围测试
应用场景:测试存在不同级别,可能是冒烟、sit、p0等重要级别
解决方案3种:
(1)通过附加的pytest.mark标记
(2)通过allure.feature,allure.story
(3)allure.severity标记
allure.severity标记级别分类,上下对应
- 不重要、不太重要、正常、严重、阻塞
- Trivial、Minor、Normal、Critical、Blocker
操作步骤
(1)在方法、函数、类上加装饰器
@allure.severity(allure.severity_level.TRIVIAL)
(2)执行时命令
pytest -s -v 文件名 --allure-severity normal,critical
例子
import allure
def test_with_no_severity_label():
print("不加标记")
@allure.severity(allure.severity_level.TRIVIAL)
def test_with_trivial_severity():
print("标记为不重要")
@allure.severity(allure.severity_level.MINOR)
def test_with_minor_severity():
print("标记为不太重要")
@allure.severity(allure.severity_level.NORMAL)
def test_with_trivial_severity():
print("标记为正常")
@allure.severity(allure.severity_level.NORMAL)
class TestClassWithNormalSeverity(object):
def test_inside_the_normal_severity_test_class(self):
pass
@allure.severity(allure.severity_level.CRITICAL)
def test_inside_normal_severity_test_class_with_overrding_critical_severity(self):
pass
执行命令:pytest -s -v 文件名 --allure-severities normal,critical
例子:pytest test_severity.py --alluredir=./result/7 --allure-severities normal,critical
allure serve ./result/7
配置IDE执行
(1)被选中的执行文件
(2)执行时的参数
21、前端自动化测试-截图功能
应用场景:前端自动化测试需要附加图片
解决方案:
@allure.attach显示许多不同类型的附件,可以补充测试、步骤、测试结果
操作步骤:
(1)在测试报告里附加网页
- allure.attach(body(内容),name,attachment_type,extension):
参数左至右分别是网页内容、名字、attach的类型
例子:allure.attach('<head></head><body>首页</body>',‘错误页的结果信息’,allure.attachment_type.HTML)
(2)在测试报告里附加图片
- allure.attach.file(source,name,attachment_type,extension):
- allure.attach.file("./result/b.png",attachment_type=allure.attachment_type.PNG)
例子
import allure
import pytest
def test_attach_text():
allure.attach("纯文本", attachment_type=allure.attachment_type.TEXT)
def test_attach_html():
allure.attach("<head></head><body>首页</body>", "错误网页", attachment_type=allure.attachment_type.HTML)
def test_attach_photo():
allure.attach.file("./1.jpg", "附加图片", attachment_type=allure.attachment_type.JPG)
22、百度搜索综合练习举例
import allure
import pytest
from selenium import webdriver
import time
@allure.testcase("https://github.com/Peggy6") # 测试用例链接
@allure.feature("百度搜索") # 功能模块
@pytest.mark.parametrize("test_data1", ["allure", "pytest", "unittest"]) # pytest参数化
def test_steps_demo(test_data1):
with allure.step("打开百度网页"):
driver = webdriver.Chrome() # 创建webdriver对象
driver.get("https://www.baidu.com/") # 测试网址
driver.maximize_window() # 最大化浏览器窗口
with allure.step(f"输入搜索词:{test_data1}"): # 传参
driver.find_element_by_id("kw").send_keys(test_data1) # 输入参数
time.sleep(3)
driver.find_element_by_id("su").click() # 点击搜索按钮
time.sleep(3)
with allure.step("保存图片"):
driver.save_screenshot("./2.png") # 截图操作
allure.attach.file("./2.png", attachment_type=allure.attachment_type.PNG) # 附加测试图片
allure.attach("<head></head><body>首页</body>", "Attach with HTML type",
attachment_type=allure.attachment_type.HTML) # 附加HTML代码
with allure.step("关闭浏览器"):
driver.quit() # driver对象退出
执行
pytest test_baidudemo.py --alluredir=./result/11
allure serve ./result/11