☯☯☯☯☯☯没有期望 何来失望 做一只快乐的咸鱼 - 北陌☯☯☯☯☯☯

Pytest 测试框架

一 . Pytest 简介

Pytest是python的一种单元测试框架。

1. pytest 特点
  • 入门简单,文档丰富
  • 支持单元测试,功能测试
  • 支持参数化,重复执行,部分执行,测试跳过
  • 兼容其他测试框架(nose,unittest 等)
  • 支持生成html报告
  • 可集成CI环境(Jenkins 等)
  • 第三方插件丰富,良好的自定义扩展性
2. pytest 与 unittest

(1)unittest

  • 测试文件必须先 import unittest
  • 测试类必须继承unittest.TestCase
  • 测试方法必须以“test_”开头
  • 测试类必须要有unittest.main()方法
  • unittest只有setup/teardown装载测试用例
  • ...

(2)pytest

  • 测试文件名必须以“test_”开头
  • 测试类以Test开头,并且不能带有 init 方法
  • 测试方法必须以“test_”开头
  • 除了有setup/teardown,还能更自由的定义fixture装载测试用例
  • ...

(3)Comparison Table

 
Pytest vs Unittest

 


二 . Pytest 安装

# 安装
pip install -U pytest

# 查看安装版本
pip show pytest

# 或者
pytest --version

三 . Pytest 运行

一个简单的例子 test_class.py:

# test_class.py
class TestClass:
    def test_one(self):
        x = "this"
        assert 'h' in x

    def test_two(self):
        x = "hello"
        assert hasattr(x, 'check')
1. cmd 中运行测试用例
# cmd中 cd到 test_class.py所在文件夹
# 运行 该文件夹中所有测试用例
pytest
# 或者
py.test

# 运行指定测试用例,加上-q参数用来指定执行的文件
pytest -q test_class.py

pytest运行规则:
查找当前目录及其子目录下以test_.py或_test.py文件,
找到文件后,在文件中找到以test开头函数并执行。

2. pycharm 中运行测试用例

一个简单的例子 test_sample.py:

# content of test_sample.py
import pytest

def func(x):
    return x + 1


def test_answer():
    assert func(3) == 5

if __name__ == "__main__":
    pytest.main('-q test_sample.py')

pycharm中运行pytest:

  • file->Setting->Tools->Python Integrated Tools->项目名称->Default test runner->选择py.test
  • 右键选择pytest运行或者直接运行.py文件

四 . Pytest 装饰器

1. setup 与 teardown

装载运行级别:

  • 模块级(setup_module/teardown_module)开始于模块始末
  • 类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
  • 方法级(setup_method/teardown_method)开始于方法始末(在类中)
  • 类里面的(setup/teardown)运行在调用方法的前后
  • 函数级(setup_function/teardown_function)只对函数用例生效(不在类中)

一个简单的例子 test_module.py:

# -*- coding: utf-8 -*-
# Version : V1.0
# Author  : Seven
# Date    : 2018/8/2 19:41

import pytest


# 模块中的方法
def setup_module():
    print("setup_module:整个.py模块只执行一次")


def teardown_module():
    print("teardown_module:整个test_module.py模块只执行一次")


def setup_function():
    print("setup_function:每个用例开始前都会执行")


def teardown_function():
    print("teardown_function:每个用例结束后都会执行")


# 测试模块中的用例1
def test_one():
    print("正在执行测试模块----test_one")
    x = "this"
    assert 'h' in x


# 测试模块中的用例2
def test_two():
    print("正在执行测试模块----test_two")
    x = "hello"
    assert hasattr(x, 'check')


# 测试类
class TestCase():

    def setup_class(self):
        print("setup_class:所有用例执行之前")

    def teardown_class(self):
        print("teardown_class:所有用例执行之后")

    def setup(self):
        print("setup:每个用例开始前都会执行")

    def teardown(self):
        print("teardown:每个用例结束后都会执行")

    def test_three(self):
        print("正在执行测试类----test_three")
        x = "this"
        assert 'h' in x

    def test_four(self):
        print("正在执行测试类----test_four")
        x = "hello"
        assert hasattr(x, 'check')


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

运行的效果:

collected 4 items                                                              

test_module.py setup_module:整个.py模块只执行一次
setup_function:每个用例开始前都会执行
正在执行测试模块----test_one
.teardown_function:每个用例结束后都会执行
setup_function:每个用例开始前都会执行
正在执行测试模块----test_two
Fteardown_function:每个用例结束后都会执行
setup_class:所有用例执行之前
setup:每个用例开始前都会执行
正在执行测试类----test_three
.teardown:每个用例结束后都会执行
setup:每个用例开始前都会执行
正在执行测试类----test_four
Fteardown:每个用例结束后都会执行
teardown_class:所有用例执行之后
teardown_module:整个test_module.py模块只执行一次

从结果看出:

  • setup_module/teardown_module的优先级是最大的
  • 然后函数里面的setup_function/teardown_function与类里面的setup_class/teardown_class互不干涉
2. fixture

一个简单的例子 test_fixture.py:

# conftest.py
# -*- coding: utf-8 -*-
import pytest


@pytest.fixture(scope="function")
def login():
    print("请先输入账号和密码,然后登陆")

    yield
    print("退出登陆")
# test_1.py
# -*- coding: utf-8 -*-
import pytest


def test_fix1(login):
    print("test_fix1 in test_1.py:需要登陆再执行操作")


def test_fix2():
    print("test_fix2 in test_1.py:不需要登陆再执行操作")


def test_fix3(login):
    print("test_fix3 in test_1.py:需要登陆再执行操作")


if __name__ == "__main__":
    pytest.main(['-s', 'test_1.py'])
# test_2.py
# -*- coding: utf-8 -*-
import pytest


def test_fix3():
    print("test_fix3 in test_2.py:不需要登陆再执行操作")


def test_fix4(login):
    print("test_fix4 in test_2.py:需要登陆再执行操作")


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

文件结构:

 
conftest configuration

运行效果:

 

pytest -s test_1.py

collected 3 items                                                              

test_1.py 请先输入账号和密码,然后登陆
test_fix1 in test_1.py:需要登陆再执行操作
.退出登陆
test_fix2 in test_1.py:不需要登陆再执行操作
.请先输入账号和密码,然后登陆
test_fix3 in test_1.py:需要登陆再执行操作
.退出登陆
pytest -s test_2.py

collected 2 items                                                              

test_2.py test_fix3 in test_2.py:不需要登陆再执行操作
.请先输入账号和密码,然后登陆
test_fix4 in test_2.py:需要登陆再执行操作
.退出登陆

从结果看出:
(1) scope 参数 实现控制 setup 级别
(2) conftest.py 配置 实现跨文件调用装饰器
(3) yield 实现 teardown


五 . Pytest 断言

  • pytest允许使用python的标准assert语句进行断言处理

六 . Pytest 自动生成报告

# 生成xml格式的报告
pytest -v test_1.py --junitxml=Path

# 生成txt格式的报告
pytest -v test_1.py --resultlog=Path

# 生成html格式的报告
# 需预先装上pytest-html
pip install pytest_html
pytest -v test_1.py --html=Path

生成报告效果图:

 
pytest_report




转自:https://www.jianshu.com/p/75c27fe23b4e

posted @ 2019-04-30 10:14  Mr、北陌  阅读(530)  评论(0编辑  收藏  举报