0
点赞
收藏
分享

微信扫一扫

Pytest框架学习笔记

驚鴻飛雪 2022-04-30 阅读 146
python

·后期需要用pytest来开发自动化框架,开始重新整理pytest相关知识

PyTest

一、Pytest overview

概览,包含编写规范、执行顺序、前后置方法函数、参数化、断言、测试报告的输出、失败重跑。

用例编写规范

  1. 测试文件名必须以"test_“开头或”_test"结尾
  2. 测试方法名必须以"test_开头"
  3. 测试类命名以"Test"开头

用例的分类执行

可以通过@pytest.mark来标记类和方法,pytest.main加入参数 -m 可以只运行标记的类和方法
pytest -v会执行所有
pytest -s test_name.py;执行特定的pytest文件

用例前置和后置方法函数

pytest中的fixture可以任意自定义方法函数,只要加上@pytest.fixture()这个装饰器,那么被修饰的方法就可以被使用

参数化

使用@pytest.mark,parametrize装饰器

断言

assert

生成报告

pytest-HTML、allure插件

失败重跑

pytest支持用例执行失败截图,使用pytest-reunfailures插件(支持失败自动重新执行)

持续集成

和Jenkin持续集成

二、Pytest的安装和规则约束

  • 安装: pip install pytest
  • 查看安装版本:pytest --version
  • pytest文档:https://docs.pytest.org/en/latest/contents.html
  • pytest的运行规则:
    1、pytest将再当前目录及其子目录中运行所有格式为test_.py或者_test.py的文件
    2、类必须以Test开头

三、跑一个demo pytest脚本

import pytest

def func(x):
    return x+1

def test_01():
    print("---test_01---")
    assert func(3) == 5 #assert fail

def test_02():
    print("---test_02---")
    assert func(3) == 4

if __name__ == '__main__':
    pytest.main(["-s","test_sample.py"])

四、用例前置和后置执行

pytest的前置和后置

函数级别:setup/teardown

可以放在类之内也可以写在类之外,对于函数级别的setup/teardown来说效果都是一样的,在执行某个测试用例(一个函数)时都会执行一遍setup/teardown。
1、运行测试方法的始末;
2、运行一次测试用例会运行一此setup和teardown

import pytest
#类之外的函数方法

def test_a():
    print("test a")

def test_b():
    print("test b")

def setup():
    print("setup")

def teardown():
    print("teardown")

if __name__ == '__main__':
    pytest.main("-s","test_method.py")
import pytest
#类之内
class TestMethod():
    def test_a(self):
        print("test a")

    def test_b(self):
        print("test b")

    def setup(self):
        print("setup")

    def teardown(self):
        print("teardown")
if __name__ == '__main__':
    pytest.main("-s","test_method.py")

放在类之内和类之外的运行效果是一样的:
test_method.py setup
.test a
teardown
setup
.test b
teardown

类级别:setup_class/teardown_class

1、运行于测试类的始末
2、一个测试内只运行一次setup_class和teardown_class

setup_class和teardown_class必须放在类里面,不然的话是不生效的。

import pytest

class TestMethod():
    def test_a(self):
        print("test a")

    def test_b(self):
        print("test b")

    def setup(self):
        print("---setup----")

    def teardown(self):
        print("---teardown---")

    def setup_class(self):
        print("***setup class***")

    def teardown_class(self):
        print("***teardown class***")

if __name__ == '__main__':
    pytest.main(["-s","test_class.py"])

运行结果:

test_class.py ***setup class***
---setup----
.test a
---teardown---
---setup----
.test b
---teardown---
***teardown class***

五、pytest的自定义运行规则

pytest里面定义一个文件pytest.ini来自定义用例的运行:

#有该标识则认为为pytest.ini文件
 [pytest] 
 addopt = -s 
#表示当前目录下的script文件夹,-可自定义
testpaths = testcase 
#表示当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件,可自定义
python_files = test_*.py
#表示当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件中,以Test_开头的类,可自定义
pytest_classes  = Test_*.py
#当前目录下的scripts文件夹下,以test_开头,以.py结尾,以Test_开头的类,以test_开头的方法,可自定义
pytest_functions = test_*

默认规则:

[pytest]

addopts = -v

testpaths = testcase

pytest_files = test_*.py

pytest_class = Test_*

pytest_functions = test_*

pytest -v运行:

testcase/test_class.py::TestMethod::test_a PASSED                                                                                 [ 50%]
testcase/test_class.py::TestMethod::test_b PASSED                                                                                                          [100%]

六、pytest断言的使用

判断为真,assert xx

判断xx不为真,assert not xx

判断b包含a,assert a in b

判断a=b,assert a == b

判断a不等于b,assert a != b

import pytest

def test_true():
    assert True

def test_false():
    assert not False

def test_a_in_b():
    res = "{'username':'python','user_id':1}"
    assert 'python' in res

def test_code():
    code = 200
    assert 200 == code

pytest -v运行结果:

testcase/test_assert.py::test_true PASSED                                                                                                                  [ 16%]
testcase/test_assert.py::test_false PASSED                                                                                                                 [ 33%]
testcase/test_assert.py::test_a_in_b PASSED                                                                                                                [ 50%]
testcase/test_assert.py::test_code PASSED                                                                                                                  [ 66%]
testcase/test_class.py::TestMethod::test_a PASSED                                                                                                          [ 83%]
testcase/test_class.py::TestMethod::test_b PASSED                                                                                                          [100%]

七、标记mark的使用

@pytest.mark.test01

pytest提供了标记机制,允许使用mark对测试函数做标记
1.一个测试函数可以多个标记
2.一个mark也可以标记多个测试函数
3.运行参数pytest -m test01
4.运行多个参数pytest -m “test01 or test02”

@pytest.mark.test01
@pytest.mark.test02
def test_b(self):
	pass
import pytest

class TestMethod:
    @pytest.mark.apitest
    @pytest.mark.httptest
    def test_a(self):
        print("---test a---")
    @pytest.mark.apitest
    def test_b(self):
        print("---test b---")
    @pytest.mark.testc
    def test_c(self):
        print("---test c---")

运行方法:

pytest -m "apitest"	#只运行mark标记为apitest的方法
pytest -m "apitest or httptest" #运行mark标记为apitest或者为httptest的方法
pytest -m "not apitest" #运行mark标记为非apitest的其他所有方法

@pytest.mark.skip(reason=none)

1.直接加在方法函数的上面(跳过该函数)
2.直接加在类上面(跳过该类)

import pytest

class TestMethod():
    @pytest.mark.skip(reson = "not needed")
    def test_a(self):
        print("test a")

    def test_b(self):
        print("test b")

if __name__ == '__main__':
    pytest.main(["-s","Test_skip.py"])

运行结果:

Test_skip.py::TestMethod::test_b PASSED                                  [100%]test b
============================== 1 passed in 0.02s ==============================
import pytest


@pytest.mark.skip(reason="not needed")
class TestMethod():

    def test_a(self):
        print("test a")

    def test_b(self):
        print("test b")

if __name__ == '__main__':
    pytest.main(["-s","Test_skip.py"])
Test_skip.py::TestMethod::test_a SKIPPED                                 [ 50%]
Skipped: not needed

Test_skip.py::TestMethod::test_b SKIPPED                                 [100%]
Skipped: not needed
============================= 2 skipped in 0.02s ==============================

@pytest.mark.skipif(2>1,reason=“我是正确的”)

八、pytest数据参数化

1.传入单个参数,pytest.mark.parametrize(argnames,argvalues)

argnames:参数名
argvalues:参数对应值,类型必须为可迭代类型,一般为list

import pytest

class TestMethod:
    @pytest.mark.parametrize("name",["xiaoA","xiaoB"])
    def test_a(self,name):
        print("--------test a")
        print(name)

    def test_b(self):
        print("--------test b")

if __name__ == '__main__':
    pytest.main(["-s","test_params.py"])

运行结果:


test_params.py::TestMethod::test_a[xiaoA] PASSED                         [ 33%]--------test a
xiaoA

test_params.py::TestMethod::test_a[xiaoB] PASSED                         [ 66%]--------test a
xiaoB

test_params.py::TestMethod::test_b PASSED                                [100%]--------test b


============================== 3 passed in 0.03s ==============================

2.传入多个参数

@pytest.mark.parametrize((“username”,“password”),[(“xiaoA”,“123456”),(“xiaoB”,“45678”)])
list每一个元素都是一个元组,元组里的每一个元素和按参数顺序一一对应

import pytest

class TestMethod:
    @pytest.mark.parametrize("name",["xiaoA","xiaoB"])
    def test_a(self,name):
        print("--------test a")
        print(name)

    @pytest.mark.parametrize(("name","passwd"),[("xiaoA","123456"),("xiaoB","456789")])
    def test_b(self,name,passwd):
        print("--------test b")
        print(name,passwd)

if __name__ == '__main__':
    pytest.main(["-s","test_params.py"])

运行结果:

test_params.py::TestMethod::test_a[xiaoA] PASSED                         [ 25%]--------test a
xiaoA

test_params.py::TestMethod::test_a[xiaoB] PASSED                         [ 50%]--------test a
xiaoB

test_params.py::TestMethod::test_b[xiaoA-123456] PASSED                  [ 75%]--------test b
xiaoA 123456

test_params.py::TestMethod::test_b[xiaoB-456789] PASSED                  [100%]--------test b
xiaoB 456789

九、pytest常用插件(测试报告、失败重跑)

测试报告插件pytest-html

应用场景:自动化测试脚本最终执行是通过还是不通过,需要通过测试报告进行体现

安装:pip3 install pytest-html

使用方式:在pytest里面加–html参数指定生成报告

[pytest]

addopts = -s --html=report.html

testpaths = testcase

pytest_files = Test_*.py
pytest_class = Test_*
pytest_functions = test_*

失败重跑插件

应用场景:当失败后再次尝试
安装:pip3 install pytest-rerunfailures
使用方式:在pytest.ini文件中的ml行参数中增加 --reruns n
如果期望加上出错重试的等待时间,–reruns-delay

举报

相关推荐

0 条评论