pytest01-》:
一 测试框架测试框架简介pvtest是一个成熟的全功能 Python测试工具,可以帮助您编写更好的程序,它与 python自带的 unittest测试框架类似,但 pytest使用起来更简洁和高效,并容uet根架四能够支持简单的单元测试和复杂的功能测试,D本科单元测两requests实现接口测试,结合 selenium、 apium实现自动化功能测试,使用 pytestalre集成到 Jenkins中可以实现持续集成。工作中一般会使用持续集成来完成代码集成到主干分支之后的回归测试,通过自动化测试的手段来实现产品的快速选代,同时还能保证产品的高质量。 pytest支持315种以上的插件,可以访问网址:http://plugincompat.herokuapp.com/,可以访问网址:htts://docs.pytestorg/查看帮助文档安装
pip install pytest
用例编写规范测试文件以 test开头(或者以 _test结尾),创建测试方法以 test_ 开头,测试类需要以Test开头并且不能 带有 init 方法 测试环境以test开头 断言使用 assert 即可,创建文件名为 test_add.py 文件
所有的包pakege必须要有__init__.py文件
用例设计原则
- 文件名以test_*.py文件和*_test.py
- 以test_开头的函数
- 以Test开头的类
- 以test_开头的方法
- 所有的包pakege必须要有__init__.py文件
1.新建一个test_sample.py文件, 文件名为 test_ 开头 写以下代码
# content of test_sample.py
def func(x):
return x +1
def test_answer():
assert func(3)==5
pip show pytest查看安装版本
pip show pytest
pytest --version
1 pytest运行规则:查找当前目录及其子目录下以test_*.py或*_test.py文件,找到文件后,在文件中找到以test开头函数并执行
2.pytest会找到符合规则(test_.py和_test.py)所有测试,因此它发现两个test_前缀功能。 如果只想运行其中一个,可以指定传递文件名test_class.py来运行模块:
备注: -q, --quiet decrease verbosity( 显示简单结果)
pytest用例规则
- 测试文件以test_开头(以_test结尾也可以)
- 测试类以Test开头,并且不能带有
__init__
方法 - 测试函数以test_开头
- 断言使用assert
用例运行
python -m
cmd执行pytest用例有三种方法,以下三种方法都可以,一般推荐第一个
-
pytest
-
py.test
-
python -m pytest
如果不带参数,在某个文件夹下执行时,它会查找该文件夹下所有的符合条件的用例(查看用例设计原则)
执行用例规则
1.执行某个目录下所有的用例
pytest 文件名/
2.执行某一个py文件下用例
pytest 脚本名称.py
3.-k 按关键字匹配; 用例中包含 MyClass 才会被执行
pytest -k "MyClass and not method"
4.按节点运行
每个收集的测试都分配了一个唯一的nodeid,它由模块文件名和后跟说明符组成
来自参数化的类名,函数名和参数,由:: characters分隔。
运行.py模块里面的某个函数
pytest test_mod.py::test_func
运行.py模块里面,测试类里面的某个方法
pytest test_mod.py::TestClass::test_method
5.标记表达式;即方法中用了 @ pytest.mark.slow slow 和方法中的slow一致就会被执行
pytest -m slow
将运行用@ pytest.mark.slow装饰器修饰的所有测试。
6.从包里面运行;怎么用
pytest --pyargs pkg.testing
这将导入pkg.testing并使用其文件系统位置来查找和运行测试。
7 pytest -x test_class.py -x 遇到错误时停止测试
8
--maxfail=num
pytest --maxfail=1
当用例错误个数达到指定数量时,停止测试
pytest文档3-pycharm运行pytest
以pytest方式运行,需要改该工程设置默认的运行器:file->Setting->Tools->Python Integrated Tools->项目名称->Default test runner->选择py.test
2.运行结果“.F. ” 点是代表测试通过,F是Fail的意思,1 warnings是用于pytest.main('-q test_class.py')里面参数需要传list,多个参数放list就不会有警告了
这样执行
pytest.main('-q','test_class.py')
04
setup和teardown
用例运行级别
-
模块级(setup_module/teardown_module)开始于模块始末,全局的 setup_module是所有用例开始前只执行一次,teardown_module是所有用例结束后只执行一次
-
函数级(setup_function/teardown_function)只对函数用例生效(不在类中) 每个用例开始和结束调用一次
-
类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
-
方法级(setup_method/teardown_method)开始于方法始末(在类中)
-
类里面的(setup/teardown)运行在调用方法的前后
- 运行的优先级:setup_class》setup_method》setup 》用例》teardown》teardown_method》teardown_class
备注:这里setup_method和teardown_method的功能和setup/teardown功能是一样的,一般二者用其中一个即可
- 运行的优先级:setup_class》setup_method》setup 》用例》teardown》teardown_method》teardown_class
- https://www.cnblogs.com/yoyoketang/p/9374957.html
1.pytest框架支持函数和类两种用例方式
05 公共参数,感觉哟的不多
pytest文档5-fixture之conftest.py
fixture优势
1.firture相对于setup和teardown来说应该有以下几点优势
- 命名方式灵活,不局限于setup和teardown这几个命名
- conftest.py 配置里可以实现数据共享,不需要import就能自动找到一些配置
- scope="module" 可以实现多个.py跨文件共享前置, 每一个.py文件调用一次 (module,session参数),test 文件中必须调用才可以触发并使用 公共参数,不是module 和session了就默认调用了
- scope="session" 以实现多个.py跨文件使用一个session来完成多个用例
2.如果@pytest.fixture()里面没有参数,那么默认scope="function",也就是此时的级别的function,针对函数有效
fixture(scope="function", params=None, autouse=False, ids=None, name=None):
"""使用装饰器标记fixture的功能 ** 作者:上海-悠悠 QQ交流群:588402570** 可以使用此装饰器(带或不带参数)来定义fixture功能。 fixture功能的名称可以在以后使用 引用它会在运行测试之前调用它:test模块或类可以使用pytest.mark.usefixtures(fixturename标记。 测试功能可以直接使用fixture名称作为输入参数,在这种情况下,夹具实例从fixture返回功能将被注入。 :arg scope: scope 有四个级别参数 "function" (默认), "class", "module" or "session".:argparams: 一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它 :argautouse: 如果为True,则为所有测试激活fixture func 可以看到它。 如果为False(默认值)则显式需要参考来激活fixture :argids: 每个字符串id的列表,每个字符串对应于params 这样他们就是测试ID的一部分。 如果没有提供ID它们将从params自动生成 :argname: fixture的名称。 这默认为装饰函数的名称。 如果fixture在定义它的同一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽; 解决这个问题的一种方法是将装饰函数命名 “fixture_ <fixturename>”然后使用”@ pytest.fixture(name ='<fixturename>')“”。
如果加了 scope="module" ,就是模块层级了(模块执行一次,login()被执行一次),但是代码都是方法层级调用,用例1和用例3都要调用login()。
为方便理解我总结如下:
scope="function", 方法层级,方法每调用login()一次,login()被执行一次;
scope="class", 类层级,类执行一次,login()被执行一次;即使类里面多处调用login(),也只执行一次;
scope="module" 模块层级,模块执行一次,login()被执行一次;即使模块里面多处调用login(),也只执行一次;
scope="session" package层级,package执行一次,login()被执行一次;即使package里面多处调用login(),也只执行一次;
conftest 放在最顶层目录即可
使用方法
conftest.py # coding:utf-8 import pytest @pytest.fixture() def login(): print("输入账号,密码先登录") test_fix1.py # coding:utf-8 import pytest def test_s1(login): #多个py文 件都可以调用 conftest.py里的方法,若是写在非conftest文件只能在自己的文件中调用, print("用例1:登录之后其它动作111") def test_s2(): # 不传login print("用例2:不需要登录,操作222") def test_s3(login): print("用例3:登录之后其它动作333") if __name__ == "__main__": pytest.main(["-s", "test_fix1.py"])
Fixtures可以选择使用yield
语句为测试函数提供它们的值,而不是return
。 在这种情况下,yield
语句之后的代码块作为拆卸代码执行,而不管测试结果如何。fixture功能必须只产生一次
import pytest
# 不带参数时默认scope="function"
class Test_sk(object):
@pytest.fixture()
def login(self): #谁用这个参数就传给谁,相当于就是这个方法的前置方法了
print("输入账号,密码先登录;我使用了fixture()999999999")
def test_s1(self,login):
print("用例1:登录之后其它动作111")
conftest.py配置
1.上面一个案例是在同一个.py文件中,多个用例调用一个登陆功能,如果有多个.py的文件都需要调用这个登陆功能的话,那就不能把登陆写到用例里面去了。
此时应该要有一个配置文件,单独管理一些预置的操作场景,pytest里面默认读取conftest.py里面的配置
conftest.py配置需要注意以下点:
- conftest.py配置脚本名称是固定的,不能改名称
- conftest.py与运行的用例要在同一个pakage下,并且有__init__.py文件
- 不需要import导入 conftest.py,pytest用例会自动查找
-
一个测试工程下是可以有多个conftest.py文件的,一般在工程根目录放一个conftest.py起到全局作用。
在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效
- conftest.py 中的文件是函数,不是类,是类的时候,其它文件无法默认调用这个conftest.py 中的参数
pytest文档6-fixture之yield实现teardown
fixture通过scope参数控制setup级别,既然有setup作为用例之前前的操作,用例执行完之后那肯定也有teardown操作。
这里用到fixture的teardown操作并不是独立的函数,用yield关键字呼唤teardown操作 (conftest.py 中使用)
它只会在第一个用例前执行一次
1.fixture参数scope="module",module作用是整个.py文件都会生效,用例调用时,参数写上函数名称就行 (只有在被调用的时候才会执行)
# 新建一个文件test_f1.py
# coding:utf-8
import pytest
'''
** 作者:上海-悠悠 QQ交流群:588402570**
'''
@pytest.fixture(scope="module")
def open():
print("打开浏览器,并且打开百度首页")
def test_s1(open):
print("用例1:搜索python-1")
def test_s2(open):
print("用例1:搜索python-1")
yield执行teardown
1.前面讲的是在用例前加前置条件,相当于setup,既然有setup那就有teardown,fixture里面的teardown用yield来唤醒teardown的执行
yield遇到异常
1.如果其中一个用例出现异常,不影响yield后面的teardown执行,运行结果互不影响,并且全部用例执行完之后,yield呼唤teardown操作
import pytest @pytest.fixture(scope="module") def open(): print("打开浏览器,并且打开百度首页") yield #yield操作如果是module的话就是类似于 setupClass 和teardownClass的操作,如果是function的话,就是类似于setup和teardown的操作 print("执行teardown!") print("最后关闭浏览器") def test_s1(open): print("用例1:搜索python-1") def test_s2(open): print("用例2:搜索python-2") def test_s3(open): print("用例3:搜索python-3") if __name__ == "__main__": pytest.main(["-s", "test_f1.py"])
2.如果在setup就异常了,那么是不会去执行yield后面的teardown内容了