对已经运行的flask服务测试代码覆盖率

上一篇文章《用pytest-cov获取flask项目的测试代码覆盖率》展示了用pytest的测试用例验证flask的函数,获取代码覆盖率信息。但是上述方法要求web服务没有提前启动,而是由pytest来启动,然后运行测试用例。
那么对于已经启动的web服务,能否也用pytest来做代码覆盖率的验证呢?答案是肯定的,需要使用Coverage.py

整体思路

  • 手动启动Flask Web项目,项目启动代码中包含coverage信息收集
  • pytest的testcase使用requests模块对Web服务发起HTTP请求,对回复进行验证
  • 手动退出Web项目,终止coverage信息收集,输出报告

源码展示

  • 文件目录结构
admin@pc:~/my_flask_app$ tree -a
.
├── app.py
├── __init__.py
└── tests
    └── test_app.py

1 directory, 3 files
  • app.py主程序中,需要加入
    • 通过环境变量判断是否启动COV收集
    • 定义函数响应"Ctrl+C",从而停止COV收集,输出COV报告
admin@pc:~/my_flask_app$ cat app.py 
import os
import signal
import sys
from flask import Flask, jsonify


# 仅在测试模式下启用覆盖率
if os.getenv("FLASK_COVERAGE"):
    import coverage
    COV = coverage.coverage(branch=True, include="./app.py")  # 确保只覆盖项目代码
    COV.start()

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

@app.route('/api/data')
def get_data():
    return jsonify({'data': 'Here is some data'})


def handle_sigint(signum, frame):
    """Handle Ctrl+C (SIGINT) to properly save coverage data."""
    if os.getenv("FLASK_COVERAGE"):
        COV.stop()
        COV.save()
        print("\nCoverage Report:")
        COV.report()
        COV.html_report(directory='htmlcov')
        COV.erase()
    sys.exit(0)


if __name__ == '__main__':
    # 捕获 SIGINT 信号 (Ctrl+C)
    signal.signal(signal.SIGINT, handle_sigint)

    # 启动 Flask 应用
    app.run()
admin@pc:~/my_flask_app$ 
  • 测试用例中要用到requests,需要保证已经安装
admin@pc:~/my_flask_app$ cat tests/test_app.py 
# tests/test_app.py
import requests

def test_hello_world():
    """Test the root route"""
    response = requests.get('http://127.0.0.1:5000/')
    assert response.status_code == 200
    assert response.text == 'Hello, World!'

def test_get_data():
    """Test the /api/data route"""
    response = requests.get('http://127.0.0.1:5000/api/data')
    assert response.status_code == 200
    assert response.json() == {'data': 'Here is some data'}
admin@pc:~/my_flask_app$ 

运行和调试

  • 首先设置环境变量然后运行app
admin@pc:~/my_flask_app$ export FLASK_APP=my_flask_app.app
admin@pc:~/my_flask_app$ export FLASK_COVERAGE=1
admin@pc:~/my_flask_app$ 
admin@pc:~/my_flask_app$ python3 app.py 
 * Serving Flask app 'app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

  • 另外开一个端口,运行测试用例,都是pass的
admin@pc:~/my_flask_app$ pytest tests/
================================================================= test session starts ==================================================================
platform linux -- Python 3.10.12, pytest-8.3.3, pluggy-1.5.0
rootdir: /home/admin/my_flask_app
plugins: anyio-4.4.0, cov-5.0.0
collected 2 items                                                                                                                                      

tests/test_app.py ..                                                                                                                             [100%]

=================================================================== warnings summary ===================================================================
../../../usr/lib/python3/dist-packages/requests/__init__.py:87
  /usr/lib/python3/dist-packages/requests/__init__.py:87: RequestsDependencyWarning: urllib3 (2.2.2) or chardet (4.0.0) doesn't match a supported version!
    warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "

tests/test_app.py::test_hello_world
tests/test_app.py::test_get_data
  /home/admin/.local/lib/python3.10/site-packages/urllib3/poolmanager.py:315: DeprecationWarning: The 'strict' parameter is no longer needed on Python 3+. This will raise an error in urllib3 v2.1.0.
    warnings.warn(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================================ 2 passed, 3 warnings in 0.19s =============================================================
admin@pc:~/my_flask_app$ 
  • 回到第一个终端,用ctrl+c中断app的运行,可以看到打印
admin@pc:~/my_flask_app$ python3 app.py 
 * Serving Flask app 'app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [29/Sep/2024 10:59:02] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [29/Sep/2024 10:59:02] "GET /api/data HTTP/1.1" 200 -
^C
Coverage Report:
Name     Stmts   Miss Branch BrPart  Cover
------------------------------------------
app.py      27     23      6      1    15%
------------------------------------------
TOTAL       27     23      6      1    15%
admin@pc:~/my_flask_app$ 
  • 要看详细报告,可以用浏览器打开下面的文件
admin@pc:~/my_flask_app$ ls -lt htmlcov/index.html 
-rw-rw-r-- 1 admin admin 4929  9月 29 11:00 htmlcov/index.html
admin@pc:~/my_flask_app$ 

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值