pytest与coverage联合使用

目录

安装 

运行方式

命令行方式

 .py文件方式

测试结果各参数含义

pytest与coverage联合使用示例

运行方式

方式一:coverage的终端使用

方式二:运行run.py

report HTML页面结果


覆盖率测量通常用于衡量测试的有效性。Coverage可以显示测试正在执行代码的哪些部分,以及哪些部分没有被执行。

coverage作用:用于检查代码测试覆盖率的工具。

官方文档:Coverage.py — Coverage.py 6.6.0b1 documentation

 

安装 

# 安装
$ pip install coverage

# 验证安装版本
$ coverage --version
Coverage.py, version 6.5.0 with C extension
Full documentation is at https://coverage.readthedocs.io

运行方式

命令行方式

# 搜集被测代码覆盖率信息,保存到 .coverage 文件中
$ coverage run 测试文件.py

# 生成覆盖率统计结果报告
$ coverage report

# 以HTML的形式生成覆盖率统计结果报告
$ coverage html

 .py文件方式

命名为run.py文件,放置在项目根目录下,具体如下:

import coverage
import pytest

# 实例化对象
cov = coverage.coverage()
cov.start()

# 测试
pytest.main(["-v", "-s"])

# 结束分析
cov.stop()

# 结果保存
cov.save()

# 命令行模式展示结果,并展示未执行代码具体行数,用于测试结果查看使用
cov.report(show_missing=True)

# 生成HTML覆盖率结果报告
cov.html_report(directory="res_html")

运行方式:进入到run.py文件所在路径执行以下命令

# 运行.py文件
$ python run.py

测试结果各参数含义

终端report里测试结果各参数含义:

  • Stmts :代码总行数
  • Miss:未执行代码行数
  • Cover:代码覆盖率

report HTML中测试结果各参数含义:

  • statements :代码总行数,不包含空行和注释行
  • missing:未执行代码行数
  • coverage:代码覆盖率

pytest与coverage联合使用示例

目录结构如下:

pytest与coverage联合使用_第1张图片

运行测试后的文件夹目录结构:

pytest与coverage联合使用_第2张图片

 运行测试+生成report HTML后的文件夹目录结构:

pytest与coverage联合使用_第3张图片

 各py文件内容具体如下:

# demofunc.py

def add(a, b):
    if isinstance(a, int) and isinstance(b, int):
        return a+b
    else:
        raise TypeError("数据类型错误")
# demofunc2.py

def add(a, b):
    raise NameError("名称错误")
    if isinstance(a, int) and isinstance(b, int):
        return a+b
    else:
        raise TypeError("数据类型错误")
# test_func.py

import pytest
from demofunc import add


class Testfunc:

    # 正常测试用例
    def test_add_by_class(self):
        assert add(2, 3) == 5

    # 异常测试用例,期望结果为抛出TypeError异常
    def test_add_by_func_aaa(self, *args, **kwargs):
        with pytest.raises(TypeError) as E:
            add("3", 4)
        print(E.type)
        print(E.value)
        print(E.traceback)


def test_zero_division_long():
    with pytest.raises(ZeroDivisionError) as excinfo:
        1 / 0
    print("----------------")
    print(excinfo.type)
    print(excinfo.value)
    print(excinfo.traceback)
# test_func2.py

import pytest
from demofunc2 import add


class Testfunc:

    # 异常用例
    def test_add_by_func_aaa(self, *args, **kwargs):
        # 将预期中多个错误信息组成一个元组
        # with pytest.raises((TypeError, NameError), match=r"错误") as E:
        with pytest.raises((TypeError, NameError), match=r".*错.*$") as E:
            add("3", 4)

    # 检查断言装饰器
    @pytest.mark.xfail(raises=(TypeError, NameError))
    def test_add_by_func_aaa2(self):
        add("3", 4)

运行方式

方式一:coverage的终端使用

使用pytest作为run.py文件的内容:

# run.py

import pytest

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

注意:使用此方式运行后,run.py文件会计入测试覆盖率中

运行后终端显示的结果如下:

# 进入到已安装了coverage的环境中

# 运行run.py进行测试
PS F:\workspace\练习题\assertcode> coverage run run.py
======================================================== test session starts ========================================================
platform win32 -- Python 3.7.3, pytest-7.1.3, pluggy-1.0.0 -- c:\users\xxx\appdata\local\programs\python\python37\python.exe    
cachedir: .pytest_cache
rootdir: F:\workspace\练习题\assertcode
plugins: cov-4.0.0
collected 5 items                                                                                                                     

test_case/test_func.py::Testfunc::test_add_by_func_aaa 
数据类型错误
[, ]
PASSED
test_case/test_func.py::test_zero_division_long ----------------

division by zero
[]
test_case/test_func2.py::Testfunc::test_add_by_func_aaa PASSED
test_case/test_func2.py::Testfunc::test_add_by_func_aaa2 XFAIL

=================================================== 4 passed, 1 xfailed in 0.05s ================================================================================== 

# 查看测试覆盖报告
PS F:\workspace\练习题\assertcode> coverage report
Name                      Stmts   Miss  Cover
---------------------------------------------
demofunc2.py                  5      3    40%
demofunc.py                   4      0   100%
run.py                        3      0   100%
test_case\test_func2.py       8      0   100%
test_case\test_func.py       18      0   100%
---------------------------------------------
TOTAL                        38      3    92%

方式二:运行run.py

使用pytest+coverage结合作为run.py文件的内容:

# run.py

import coverage
import pytest

cov = coverage.coverage()

cov.start()

pytest.main(["-v", "-s"])

cov.stop()
cov.save()

cov.report()
cov.html_report(directory="res_html")

注意:使用此方式运行后,run.py文件不计入测试覆盖率中

运行后终端显示的结果如下:

PS F:\workspace\练习题\assertcode> & C:/Users/xxx/Envs/ctpenv/Scripts/python.exe f:/workspace/练
习题/assertcode/run.py
======================================== test session starts =========================================
platform win32 -- Python 3.7.3, pytest-7.1.3, pluggy-1.0.0 -- C:\Users\xxx\Envs\ctpenv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: F:\workspace\练习题\assertcode
plugins: anyio-3.6.1
collected 5 items

test_case/test_func.py::Testfunc::test_add_by_func_aaa 
数据类型错误
[, ]
PASSED
test_case/test_func.py::test_zero_division_long ----------------

division by zero
[]
test_case/test_func2.py::Testfunc::test_add_by_func_aaa PASSED
test_case/test_func2.py::Testfunc::test_add_by_func_aaa2 XFAIL

=================================================== 4 passed, 1 xfailed in 0.05s ================================================================================== 
Name                      Stmts   Miss  Cover
---------------------------------------------
demofunc2.py                  5      3    40%
demofunc.py                   4      0   100%
test_case\test_func2.py       8      0   100%
test_case\test_func.py       17      0   100%
---------------------------------------------
TOTAL                        34      3    91%

report HTML页面结果

总计结果页面显示:

pytest与coverage联合使用_第4张图片

单个文件覆盖详情显示:

pytest与coverage联合使用_第5张图片

你可能感兴趣的:(Pytest,Python,pytest,python,开发语言)