pytest简介——深入分析

一.pytest单元测试框架

1.什么是单元测试框架

单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查测试。

2.单元测试框架

java:junit和esting

python:unitest和pytest

3.单元测试框架主要做什么?

(1). 测试发现:从多个文件里面去找到我们的测试用例

(2). 测试执行:按照一定的顺序和规则去执行,并生成结果

(3). 测试判断:通过断言判断预期结果和实际结果的差异

(4). 测试报告:统计测试进度,耗时,通过率,生成测试报告

二.单元测试框架和自动化测试框架有什么关系?

1.什么是自动化测试框架

2.作用

(1). 提高测试效率,降低维护成本

(2). 减少人工干预,提高测试的准确性,增加代码的重用性

(3). 核心思想是让不懂代码的人也能够通过这个框架去实现自动化测试

3.pytest单元测试框架和自动化测试框架的关系

单元测试框架:只是自动化测试框架中的组成部分之一。

pom设计模式:只是自动化测试框架中的组成部分之一。

数据驱动:只是自动化测试框架中的组成部分之一。

关键字驱动:只是自动化测试框架中的组成部分之一。

全局配置文件的封装:只是自动化测试框架中的组成部分之一。

日志监控:只是自动化测试框架中的组成部分之一。

selenium,request二次封装:只是自动化测试框架中的组成部分之一。

断言:只是自动化测试框架中的组成部分之一。

报告邮件:只是自动化测试框架中的组成部分之一。

更多....................。

三.pytest简介

1.pytest是一个非常成熟的python的单元框架。比unittest更灵活,容易上手

2.pytest可以和selenium,requests,appium结合实现web自动化,接口自动化,app自动化

3.pytest 可以实现测试用例的跳过以及reruns失败用例重试

4.pytest可以和allure生成非常美观的测试报告

5.pytest可以和jenkins持续集成

6.pytest有很多非常强大的插件,并且这些插件能够实现很多实用的操作

插件:

(1). pytest-html   生成html格式的自动化测试报告

(2). pytest-xdist  测试用例分布式执行,多cpu分发

(3). pytest-ordering 用于改变测试用例的执行顺序

(4). pytest-rerunfailures  用例失败后重跑

(5). allure-pytest  用于生成美观的测试报告

安装:

在项目目录中新建一个文件,一般叫做requirements.txt ,将插件名称放到txt中,

在terminal中输入pip install -r requirements.txt

requirements.txt中的内容如下:

pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
allure-pytest

注意:这个安装是局部的,仅仅是我们的项目中,如果想要安装全局的,需要在dos中进行执行。

四.pytest使用,默认的测试用例的规则以及基础应用

1.模块名必须以test_ 开头或者_test 结尾

2.测试类必须以Test开头,并且不能有init方法

3.测试方法必须以test开头

例如:

五.pytest测试用例的运行方式

1.主函数模式

上面的方式是打印不出来print中的内容的

我们需要在main中加参数,例如:

(1). 运行所有

if __name__ == '__main__':
    pytest.main(['-s'])

这样就能打印出来了。

2.命令行模式

在这个终端中输入pytest,即可执行用例。

(1). 运行所有 pytest

(2). 指定模块 pytest -vs test_login.py

(3). 指定目录  pytest -vs ./interface_testcase

(4). 指定目录 pytest -vs ./interface_testcase/test_interface.py::TestInterface::test_03_zhiliao

 

参数详解:

-s:表示输出调试信息,包括print打印的信息

-v:打印更详细的信息

-vs:这两个参数可以一起用

-n:支持多线程或者分布式运行测试用例

  例如:

import pytest
if __name__ == '__main__':
    pytest.main(['-vs','./testcase','-n=2'])

--reruns NUM:失败用例重跑

import pytest
if __name__ == '__main__':
    pytest.main(['-vs','./testcase','--reruns=2'])

-x :表示有一个用例报错,那么测试停止 

--maxfail=2:出现两个用例失败就停止

-k: 根据测试用例的部分字符串指定用例

--html ./report/report.html:生成html的测试报告

(2). 指定模块

如果想在all.py中指定模块

import pytest
if __name__ == '__main__':
    pytest.main(['-sv','test_login.py'])

这样指定即可 

(3). 指定目录

将all.py放在最外面,又创建了一个interface_testcase这个包,包里面是一个test_interface.py模块,模块下,创建了类和方法。

那么执行在all文件下指定包名也可以执行里面的用例。

(4).通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组成。

if __name__ == '__main__':
    pytest.main(['-vs','./interface_testcase/test_interface.py::test_04_func'])

注意:模块和函数之间使用::这个符号隔开,然后如果想执行“测试知了”,需要带上类名。

if __name__ == '__main__':
    pytest.main(['-vs','./interface_testcase/test_interface.py::TestInterface::test_03_zhiliao'])

 

3.通过读取pytest.ini全局配置文件运行

pytest.ini这个文件是pytest单元测试的配置文件。

1.位置:一般放在项目的根目录

2.编码:必须是ANSI,可以使用notpad++修改编码格式。

3.作用:改变pytest默认的行为

4.运行的规则:不管是主函数的模式运行,命令行模式运行,都会去读这个配置文件。

[pytest]
addopts= -vs    #命令行的参数,用空格分隔
testpaths = ./testcase   #测试用例的路径
python_files=test*.py   #模块名的规则
python_classes = Test*  #类名的规则
python_functions = test  #方法名的规则

六.pytest执行用例的顺序是怎么样的?

unittest:ascll的大小来绝对的执行的顺序

pytest:默认从上到下

@pytest.mark.run(order=),这个可以改变用例的执行顺序。

七.如何分组执行(冒烟,分模块执行,分接口和web执行)

smoke:冒烟用例,分布在各个模块里面

命令行执行:pytest  -m "smoke or usermanage"

[pytest]
addopts= -vs --html ./report/report.html
testpaths = ./testcase
python_files=test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟用例
    usermanage:用户管理模块
    productmange:商品管理模块

八.pytest跳过测试用例

(1).无条件跳过

@pytest.mark.skip(reason="百里不老实")

(2).有条件跳过

@pytest.mark.skipif(age>=18,reason="已成年")

九.pytest框架实现一些前后置(固件,夹具)的处理,常用三种

1. setup/teardown,setup_class/teardown_class

为什么需要这些功能?

比如:web自动化执行用例之前,请问需要打开浏览器 

import time

import pytest

class TestLogin:

    def setup_class(self):
        print("在每个类执行前的初始化的工作:比如:创建日志对象,创建数据库链接,创建接口的请求对象")
    def setup(self):
        print('\n在执行测试用例之前初始化的代码:打开浏览器,加载网页')

    @pytest.mark.run(order=5)

    def test_01_baili(self):
        print("测试百里")
    @pytest.mark.run(order=4)

    def test_02_xiaohai(self):
        print("测试小海")
    @pytest.mark.run(order=3)
    def test_03_xiaoze(self):
        print("测试小泽")
    @pytest.mark.run(order=2)
    def test_05_xiaohao(self):
        print("测试小号")
    @pytest.mark.run(order=1)
    def test_04_xiaotao(self):
        print("\n测试小涛")
    def teardown(self):
        print('\n在执行测试用例之后的扫尾的代码:关闭浏览器')
    def teardown_class(self):
        print("在每个类执行后的扫尾工作:比如:销毁日志对象,销毁数据库连接,销毁接口的请求对象")

注意:和Unitest不一样,全是小写

2.使用@pytest.fixture()装饰器来实现部分用例的前后置

@pytest.fixture(scope="",params="",autouse="",ids="",name="")

结构如此:

scope表示的是被@pytest.fixture标记的方法的作用域。function(默认),class,module,package/session.

params:参数化(支持,列表,元组,字典列表,字典元组)

autouse=True:自动执行,默认False

ids:当使用params参数化时,给每个值设置一个变量名。意义不大。

name:表示的是被@pytest.fixture标记的方法取一个别名。

@pytest.fixture(scope='function',params=['成龙','甄子丹'])
def my_fixture(request):
    "这个位置可以加个前置,例如放一个print('这是前置的方法')"
    "yield是用来加后置的,一般在yield下面放输出的内容即可"
    return request.param
class TestLogin:
    def test_01_baili(self):
        print("测试百里")
    def test_02_xiaohai(self):
        print("测试小海")
    def test_03_xiaoze(self):
        print("测试小泽")
    def test_05_xiaohao(self):
        print("测试小号")

    def test_04_xiaotao(self,my_fixture):
        print("\n测试小涛")
        print('.............'+str(my_fixture))

 注:return和yield都表示返回的意思,但是return的后面不能有代码,,yield返回后,后面可以加代码。

@pytest.fixture(scope='function',params=['成龙','甄子丹'])
def my_fixture(request):
   # "这个位置可以加个前置,例如放一个print('这是前置的方法')"
    #"yield是用来加后置的,一般在yield下面放输出的内容即可"
    #return request.param
    print('前置')
    yield request.param
    print('后置')
class TestLogin:
    def test_01_baili(self):
        print("测试百里")
    def test_02_xiaohai(self):
        print("测试小海")
    def test_03_xiaoze(self):
        print("测试小泽")
    def test_05_xiaohao(self):
        print("测试小号")

    def test_04_xiaotao(self,my_fixture):
        print("\n测试小涛")
        print('.............'+str(my_fixture))

注:上面的代码实现了前后置和参数化一起用。

import time

import pytest


@pytest.fixture(scope='function',params=['成龙','甄子丹'],ids=('cl','zzd'))
def my_fixture(request):
   # "这个位置可以加个前置,例如放一个print('这是前置的方法')"
    #"yield是用来加后置的,一般在yield下面放输出的内容即可"
    #return request.param
    print('前置')
    yield request.param
    print('后置')
class TestLogin:
    def test_01_baili(self):
        print("测试百里")
    def test_02_xiaohai(self):
        print("测试小海")
    def test_03_xiaoze(self):
        print("测试小泽")
    def test_05_xiaohao(self):
        print("测试小号")

    def test_04_xiaotao(self,my_fixture):
        print("\n测试小涛")
        print('.............'+str(my_fixture))

注:上面代码演示了ids的使用。下面展示变化内容。给每一个值设置了一个变量名

给这个unicode这个值改成自己想要的。

import time

import pytest


@pytest.fixture(scope='function',params=['成龙','甄子丹'],ids=('cl','zzd'),name='aaa')
def my_fixture(request):
   # "这个位置可以加个前置,例如放一个print('这是前置的方法')"
    #"yield是用来加后置的,一般在yield下面放输出的内容即可"
    #return request.param
    print('前置')
    yield request.param
    print('后置')
class TestLogin:
    def test_01_baili(self):
        print("测试百里")
    def test_02_xiaohai(self):
        print("测试小海")
    def test_03_xiaoze(self):
        print("测试小泽")
    def test_05_xiaohao(self):
        print("测试小号")

    def test_04_xiaotao(self,aaa):
        print("\n测试小涛")
        print('.............'+str(aaa))

注:上面的内容展示的是通过name给标记起了一个别名。

3.通过conftest.py和@pytest.fixture()结合使用实现全局前置应用(比如:项目的全局登录,模块的全局处理)

(1). conftest.py文件是单独存放的一个夹具配置文件,名称不能更改。

(2). 用处可以在不同的py文件中使用同一个fixture函数。

(3). 原则上conftest.py需要和运行的用例放到同一层,并且不需要做任何的import导入的操作

总结:setup/teardown,setup_class/teardown_class,他是作用于所有用例或者所有的类

@pytest.fixture(),他的作用是既可以部分也可以全部前后置

conftest.py和@pytest.fixture()结合使用,作用于全局的前后置

4.断言

assert

5.pytest结合allure-pytest插件生成allure测试报告

(1).下载,解压,配置path路径

(2). 加入命令生成json格式临时报告 

[pytest]
addopts= -vs --alluredir ./temp
testpaths = ./testcase
python_files=test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟用例
    usermanage:用户管理模块
    productmange:商品管理模块

(3).生成allure报告

os.system('allure generate ./temp -o ./report --clean')

allure generate  命令,固定的

./trmp                临时的json格式报告的路径

-o                       输出output

/report               生成的allure报告的路径

-clean                清空./report 路径原来的报告

 

posted @ 2023-03-16 20:44  小泽的窝  阅读(318)  评论(0编辑  收藏  举报