python pytest测试框架


pytest介绍

pytest是一个非常成熟的全功能的Python测试框架。简单灵活,容易上手;支持参数化;
测试用例的skip和xfail,自动失败重试等处理:
。能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);
pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-allure(完美html测试报告生成),pytest- xdist(多CPU分发)等;
。可以很好的和jenkins集成
文档:https://docs.pytest.org/en/latest/contents.html#toc第三方库:https://pypiorg/search/?q=pytest

pytest测试用例的识别和运行

测试文件

  • test_*py
  • *_test.py
    用例识别
  • Test类包含的所有test的方法(测试类不能带有_init方法)
  • 不在class中的所有的test_*方法
  • pytest也可以执行unittest框架写的用例和方法

常用的终端执行命令:

pytest/py.test
pytest-v(最高级别信息-verbose)打印详细运行日志信息
pytest-s -v 文件名.py(s是带控制台输出结果,也是输出详细)
pytest文件名.py执行单独一个pytest模块
pytest 文件名.py::类名 运行某个模块里面某个类
pytest文件名.py:类名:方法名运行某个模块里面某个类里面的方法
pytest文件名.py-v -k"类名 and not 方法名”跳过运行某个用例
pytest文件名.py-m[标记名] @pytestmark.[标记名]将运行有这个标记的测试用例
pytest文件名.py -x 一旦运行到报错就停止运行
pytest文件名.py -maxfail-[num] 当运行错误达到num的时候就停止运行

创建test_01.py,并输入以下代码

def test_demo01():
    print("执行测试demo01")
    x = 'zhangshuai'
    assert 'h' in x

def test_demo02():
    print("执行测试demo02")
    a = 'hello'
    b = 'hello pytest'
    assert a in b

分别执行一下三种pytest的执行语句
pytest test_01.py 只能看到失败的信息(成功的时候显示test_01py..)
pytest -v test_01.py 会显示每个测试方法的执行情况
pytest -s test_01.py 会打印方法的输出语句
结果如下

pytest执行失败重新运行

场景:测试失败后要重新运行n次,要在重新运行之间添加延迟时间,间隔n秒再运行。
安装:pip install pytest-rerunfailures
执行:
pytest --reruns 3 -v -s test_01.py(加入方法demo01出错会重复执行这个方法3次)
pytest -v --reruns 5 --reruns-delay 1 test_01.py(reruns-delay 1表示每次再执行失败的方后法间隔1秒再重复执行下一次)

pytest执行多条断言遇到有失败的断言也能继续执行所有

场景:一个方法中写多条断言,通常第一条过不去,下面就不执行了。我们想报错也执行
安装:pip install pytest-assume
执行:
pytest.assume(14)
pytest.assume(2
4)
代码:

class TestDemo:

    def test_demo01(self):
        print("执行测试demo01")
        x = 'Changsha'
        assert 'a' in x

    def test_demo02(self):
        print("执行测试demo02")
        a = 'helloa'
        b = 'hello pytest'
        assert a in b
        assert 'q' in b
       # pytest.assume(1==1)
       # pytest.assume(a in b)
       # pytest.assume(1==2)

不使用assume的断言

使用assume的断言

文章主要介绍下在pycharm中怎么使用pytest框架进行测试

pycharm配置与执行pytest测试框架

运行方式:pytest.main(['-v',TestClass])(所有参数和pytest命令行方式一样的)
下载pytest第三方包

将运行方式选择pytest

详细可参考这个文章:https://www.cnblogs.com/hpzyang/p/13948048.html

有时候在创建的项目是虚拟环境virtualenv的时候 会发现正常配置pytest的运行方式但是右键运行还是没有出现 pytest for *** 运行,这时候需要在配置中选中项目


避免这种复杂的方式,(这种情况可以能虚拟环境使用的是本地的python的依赖 两者没法互通)我们在创建项目的时候可以创建为conda的项目

参数解析

pytest框架结构

import pytest类似的setupteardown同样更灵活,
模块级(setup_module/teardown_module)模块始末,全局的(优先最高)
函数级(setup_function/teardown_function)只对函数用例生效(不在类中犯法)
类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
方法级(setup_method/teardown_methond)开始于方法始末(在类中的方法)
类里面的(setup/teardown)运行在调用方法的前后(和method方法作用相同,在方法前进行执行但是执行的优先级别低于method)

import pytest


def setup_module():
    print('setup_module')


def teardown_module():
    print('teardown_module')


def setup_function():
    print('setup_function')


def teardown_function():
    print('teardown_function')


def test_login():
    print('这是个登陆方法')


class TestDemo:
    def setup_class(self):
        print('setup_class')
        print('用户a已经开始登录成功')

    def teardown_class(self):
        print('teardown_class')

    def setup_method(self):
        print('setup_method')

    def setup(self):
        print('setup')

    def test_demo01(self):
        print("执行测试demo01,需要登陆")
        x = 'Changsha'
        assert 'a' in x
        pass
    def test_demo02(self):
        print("执行测试demo02,不需要登陆")
        a = 'hello'
        b = 'hello pytest'
        assert a in b
        # assert 'q' in b
        # pytest.assume(1 == 1)
        # pytest.assume(a in b)
        # pytest.assume(1 == 2)
        pass
    def test_demo03(self):
        print("执行测试demo03,需要登陆")
        x = 'Changsha'
        assert 'a' in x
        pass

# class TestDemo1:
#
#     def test_demo03(self):
#         print("执行测试demo03")
#         x = 'shanghaied'
#         assert 'q' in x
#
#     def test_demo04(self):
#         print("执行测试demo04")
#         a = 'hello'
#         b = 'hello pytest'
#         assert a in b
if __name__ == '__main__':
    pytest.main("-v -x TestDemo")

结果如下

在方法前面加@pytest.fixture()

例子1:前端自动化中应用

用例1需要先登录
用例2不需要登录
用例3需要登录

场景:测试用例执行时,有的用例需要登陆才能执行,有些用例不需要至 setup和teardown无法满足。
fixture可以。默认scope(范围)function
步骤:
导入pytest
在登陆的函数上面加@pytest.fixture()
在要使用的测试方法中传入(登陆函数名称),就先登陆
不传入的就不登陆直接执行测试方法

import pytest
@pytest.fixture()
def test_login():
    print('这是个登陆方法')


def  test_demo01(test_login):
    print('需要登陆')
    pass

def  test_demo02():
    print('需要登陆')
    pass

def  test_demo03(test_login):
    print('需要登陆')
    pass

if __name__ == '__main__':
    pytest.main()

运行结果如下

例子2场景:
不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也都不需要返回值时可以选择自动应用
解决:使用fixture中参数autouse=True实现
步骤:
在方法上面加@pytest.fixture(autouse=True)
在测试方法上加@pytest.markusefixtures("start")

conftest

场景:
你与其他测试工程师合作一起开发时公共模块要在不同文件中,要在大家都访问到的地方。
解决:
conftest.py这个文件进行数据共享,并且他可以放在不同位置起着不同的范围共享作用。执行:
系统执行到参数login时先从本文件中查找是否有这个名字的变量,之后在conftestpy中找是否有
步骤:
将登陆模块带@pytest.fixture写在conftestpy

  • conftestpy配置需要注意:
  • conftest文件名是不能换的
  • conftest.py与运行的用例要在同一个package下,并且有_init_.py文件
  • 不需要import导入conftset.py,pytest用例会自动查找
  • 全局的配置和前期工作都可以写在这里,放在某个包下,就是这个包数据共享的地方。

yield

场景:你已经可以将测试方法前要执行的或依赖的解决了,测试方法后销毁清除数据的要如何进行呢?范围是模块级别的。类似setupClass

解决:通过在同一模块中加入yield关键字,yield是调用第一次返 回结果,第二次执行它下面的语句返回。

步骤: 在@pytest.fixture(scope=module)

在登陆的方法中加yield,之后加销毁清除的步骤注意,这种方式没有返回值,如果希望返回使用addfinalizer


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM