pytest学习总结
1、介绍
单元测试框架——软件开发过程中针对软件的最小单位(函数、方法)进行正确性的检查测试
Java测试框架:junit和testng
python测试框架:unittest和pytest
单元测试框架的主要实现:
1、测试发现
2、测试执行
3、测试判断
4、测试报告:测试进度、耗时、通过率、生成测试报告
2、pytest执行测试需要遵循的规则
1、模块名必须以test_开头或者以_test结尾
2、测试类必须以Test开头,并且不能有int方法
3、测试方法必须以test开头、pytest执行测试需要遵循的规则
4、断言必须要使用assert
3、pytest 测试用例运行方式
1、主函数模式
运行所有:pytest.main()
指定模块pytest.main([’-vs’,test_login.py])
指定目录pytest.main([’-vs’,’./interface_testcase’])
通过nodeid指定用例运行 nodeid由模块名、分隔符、类名、方法名、函数名组成
2、命令行模式
参数详解
-s:表示输出调试信息,包括print打印信息
-q 只显示整体测试结果
-v 用于显示每个测试函数的执行结果
-n:支持多线程或者分布式运行测试用例
-x, --exitfirst, exit instantly on first error or failed test
-h 帮助
1、pytest 执行当前文件夹以及子文件夹中所有以test_开头的测试文件
2、pytest xxx.py 执行某个指定文件
3、pytest -v -s
-v 详细信息 -s 打印信息
4、pytest -q 静默执行
5、pytest xxx.py::类名::函数名 执行指定某一个测试用例
6、pytest -x 失败即停止
pytest --maxfail=5 失败达到5 停止
7、pytest -k 类名 只执行某个类里面的测试用例
8、失败后重试
安装pytest -rerunfailures 库文件 或者是pip install pytest-rerunfailures
pytest -v -s --reruns=3-delay=5
–reruns=3 重试三次–reruns -delay=5延时五秒
9、多线程运行 pytest -s -v -n 2 (2个线程运行
安装 pytest -xdist库文件
mark标记
1)冒烟用例
通过自定义mark的形式完成
@pytest.mark.maoyan
pytest -m maoyan xx.py
2)跳过用例
@pytest.mark.skip("原因)
mark中自带的函数
3)参数化
@pytest.mark.parametrize('x,y,r’list )
parametrlze传递的是list列表 多个数据使用元组传递
assert 断言可以叠加使用 但是第一个不通过的时候,下面的不会再继续执行
可以借助assume来完成 安装assume库文件
assume(a ==b)
4、pytest环境搭建
首先使用pip安装 pytest
pip install pytest
检测是否安装成功
C:\Users\xinping.kuang>pytest --version
pytest 6.2.1
安装pytest-html(原生态报告模板):
pip install pytest html
运行模式:
pytest --html=report.html
5、测试框架的整体目录
目录/文件 | 说明 | 是否为python包 |
---|---|---|
common/libs | 这个包中存放的是常见的通用的类 | 是 |
config | 配置文件目录 | 是 |
logs | 日志目录 | |
page | 对selenium的方法进行深度的封装 | 是 |
page_element | 页面元素存放目录 | |
page_object | 页面对象POM设计模式 | 是 |
TestCase | 所有的测试用例集 | 是 |
tools | 工具类 | 是 |
script | 脚本文件 | |
conftest.py | pytest胶水文件 | |
pytest.ini | pytest配置文件 |
注意:python包为是的,都需要添加一个__init__.py文件以标识此目录为一个python包。
pytest可以和selenium、request、appium结合实现web自动化、接口自动化、app自动化
6、用例运行级别
模块级(setup_module/teardown_module)开始于模块始末,全局的
函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
类级 (setup_class/teardown_class)只在类中前后运行一次(在类中)
方法级(setup_method/teardown_method)开始于方法始末)(在类中)
方法细化级:(setup/teardown)每个用例执行前都会执行(在类中)
import pytest
def setup_module():
print("=====整个.py模块开始前只执行一次:打开浏览器=====")
def teardown_module():
print("=====整个.py模块结束后只执行一次:关闭浏览器=====")
def setup_function():
print("===每个函数级别用例开始前都执行setup_function===")
def teardown_function():
print("===每个函数级别用例结束后都执行teardown_function====")
def test_one():
print("one")
def test_two():
print("two")
class TestCase():
def setup_class(self):
print("====整个测试类开始前只执行一次setup_class====")
def teardown_class(self):
print("====整个测试类结束后只执行一次teardown_class====")
def setup_method(self):
print("==类里面每个用例执行前都会执行setup_method==")
def teardown_method(self):
print("==类里面每个用例结束后都会执行teardown_method==")
def setup(self):
print("=类里面每个用例执行前都会执行setup=")
def teardown(self):
print("=类里面每个用例结束后都会执行teardown=")
def test_three(self):
print("three")
def test_four(self):
print("four")
if __name__ == '__main__':
pytest.main(["-q", "-s", "-ra", "test_login.py"])
运行结果
E:\kuang\venv\Scripts\python.exe E:/kuang/test_login.py
=====整个.py模块开始前只执行一次:打开浏览器=====
===每个函数级别用例开始前都执行setup_function===
one
.===每个函数级别用例结束后都执行teardown_function====
===每个函数级别用例开始前都执行setup_function===
two
.===每个函数级别用例结束后都执行teardown_function====
====整个测试类开始前只执行一次setup_class====
==类里面每个用例执行前都会执行setup_method==
=类里面每个用例执行前都会执行setup=
three
.=类里面每个用例结束后都会执行teardown=
==类里面每个用例结束后都会执行teardown_method==
==类里面每个用例执行前都会执行setup_method==
=类里面每个用例执行前都会执行setup=
four
.=类里面每个用例结束后都会执行teardown=
==类里面每个用例结束后都会执行teardown_method==
====整个测试类结束后只执行一次teardown_class====
=====整个.py模块结束后只执行一次:关闭浏览器=====
4 passed in 0.21s
Process finished with exit code 0
类里面的(setup/teardown)运行在调用方法的前后
setup_module/teardown_module的优先级是最大的,然后函数里面用到的setup_function/teardown_function与类里面的setup_class/teardown_class互不干涉
import pytest
from selenium import webdriver
import time
class Test_错误登录:
def test_C001(self):
print('用例 C001: 不输入账号登录')
# 实例化浏览器 如果为空就是是用的项目根目录的Chrome驱动
borwser = webdriver.Chrome()
# 请求网址
borwser.get('http://api.sindraxservices.com/#/login')
# 隐式等待 每隔半秒请求
borwser.implicitly_wait(10)
# 窗口放大
borwser.maximize_window()
# 点击密码框
borwser.find_element_by_name('password').click()
borwser.find_element_by_name('password').send_keys('zzc222736')
time.sleep(2)
# 点击登陆
borwser.find_element_by_class_name('el-button--primary').click()
time.sleep(2)
tes = borwser.find_element_by_class_name('el-form-item__error') .text
print(tes)
assert tes == '请输入正确的用户名'
def test_C002(self):
print('\n用例 C002: 不输入账号登录')
# 实例化浏览器 如果为空就是是用的项目根目录的Chrome驱动
borwser = webdriver.Chrome()
# 请求网址
borwser.get('http://api.sindraxservices.com/#/login')
# 隐式等待 每隔半秒请求
borwser.implicitly_wait(10)
# 窗口放大
borwser.maximize_window()
# 点击密码框
borwser.find_element_by_name('username').click()
borwser.find_element_by_name('username').send_keys('zzc222736')
time.sleep(2)
# 点击登陆
borwser.find_element_by_class_name('el-button--primary').click()
time.sleep(2)
tes = borwser.find_element_by_class_name('el-form-item__error') .text
print(tes)
assert tes == '密码不能小于3位'
if __name__ == "__main__":
pytest.main(['-q', 'test_sample.py'])
7、插件allure使用
allure-2.13.8安装包地址
配置环境变量
将解压的安装包路径E:\allure-2.13.8\bin添加到 系统变量-path
检查allurea是否安装成功
allure --version
@allure.feature # 用于定义被测试的功能,被测产品的需求点
@allure.story # 用于定义被测功能的用户场景,即子功能点
with allure.step # 用于将一个测试用例,分成几个步骤在报告中输出
allure.attach # 用于向测试报告中输入一些附加的信息,通常是一些测试数据信息
@pytest.allure.step # 用于将一些通用的函数作为测试步骤输出到报告,调用此函数的地方会向报告中输出步骤
测试allure脚本
import pytest
import allure
@allure.step("步骤1:点xxx")
def step_1():
print("111")
@allure.step("步骤2:点xxx")
def step_2():
print("222")
@allure.feature("编辑页面")
class TestEditPage():
'''编辑页面'''
@allure.story("这是一个xxx的用例")
def test_1(self):
'''用例描述:先登录,再去执行xxx'''
step_1()
step_2()
print("xxx")
@allure.story("打开a页面")
def test_2(self):
'''用例描述:先登录,再去执行yyy'''
print("yyy")
生成测试报告
1、测试脚本中添加了Allure特性之后,可以通过两步,就可以展示出测试报告了。
第一步,生成测试报告数据
在py.test执行测试的时候,指定–alluredir选项及结果数据保存的目录:
pytest --alluredir ./report/allure_raw
第二步,生成测试报告页面
allure serve report/allure_raw
安装pytest-html 库文件 或者 pip install pytest-html
–html=,/report/result.html
fixture 标签
场景:测试之前的准备工作:准备测试数据 读取数据库给测试用例函数传递数据,使用更加灵活
普通函数加注解 @ pytest.fixture()
fixture是可以有返回值的,如果没有return默认返回none
scope作用域:测试用例函数 类 py文件
params参数 list
autouse 自动使用fixture 默认false
autouse自动使用
默认False 添加这个属性 在测试用例函数中不调用fixture函数 也能自动使用
参数化 返回值
pytest配置文件
pytest.ini必须是这个名字 出席创建这种
作用域
函数:function
类:class
py文件:module
问题解决
1、pycharm运行报错
ModuleNotFoundError: No module named ‘pytest’
这类没没有找到但已经安装导入过的模块
pycharm --File–settings–project:pytest–project interpreter 选择正确的确认就行
2、