我在使用 Pytest 时遇到一些问题。我的 Flask API 使用 pyodbc 与 MSSQL 服务器数据库对话。该 API 在 Docker 容器中运行,我在 Mac 上运行它。
我有一个健康检查(根级别即
localhost:5000/
)路由的单元测试,如下所示:
from app import app
def test_healthcheck(self):
"""
Test the healthcheck endpoint
EXPECTS: A 200 status code and the string "Healthcheck"
"""
with app.test_client() as test_client:
response = self.app.get("/")
assert response.status_code == 200
assert response.data, b"Healthcheck"
我的项目是结构化的如下:
myproject
| app.py
| — api/
| — routes/
| — utils/
| db.py
| helpers.py
| — tests/
| test_healthcheck.py
当我运行
python3 -m pytest
时,出现以下错误:
ERROR tests/test_healthcheck.py - pyodbc.Error: ('01000', "[01000] [unixODBC][Driver Manager]Can't open lib 'ODBC Driver 18 for SQL Server' : file not found (0) (SQLDriverConnect)")
错误日志显示pyodbc错误源于
pyodbc.connect()
行我的db.py util文件,这是一个基于类的抽象数据库操作的。
class DB:
"""
Class to abstract out MS SQL Server DB operations
"""
def __init__(self):
self.conn_str = os.getenv("CONN_STR")
if not self.conn_str:
raise RuntimeError("Missing 'CONN_STR' env var")
self.conn = pyodbc.connect(self.conn_str)
但是我在本地计算机上安装了 pyodbc,当我在 Docker 中运行 API 时,我没有遇到任何 pyodbc 问题。
如果这有帮助,app.py 如下:
import logging
from flask import Flask
from dotenv import load_dotenv
from api.routes.healthcheck import bp as health_bp
from api.routes.generate import bp as generate_bp
load_dotenv()
app = Flask(__name__)
app.register_blueprint(health_bp)
app.register_blueprint(generate_bp)
logging.basicConfig(level=logging.INFO)
logging.getLogger("werkzeug").setLevel(logging.INFO)
我看到 Pytest 文档谈论 conftest.py 文件,但这似乎依赖于工厂应用程序模式,而该应用程序则不然。我需要比赛吗?我该如何消除这个 pyodbc 错误?
问题在于 Pytest 在运行测试时,是在独立的进程中运行,而不是在 Docker 容器内。因此,它找不到 Docker 容器中安装的 ODBC 驱动和配置。
解决这个问题有几种方法:
1. 使用 Docker Compose 运行测试:
这是最干净和最推荐的方法。 你可以使用 Docker Compose 来启动一个包含你的应用程序和依赖项的测试环境,并在该环境中运行 Pytest。
-
在你的项目根目录创建一个
docker-compose.test.yml
文件:
version: '3.8'
services:
api:
build: .
command: python3 -m pytest
volumes:
- .:/app:ro
environment:
- CONN_STR=YOUR_TEST_CONN_STR
-
将
YOUR_TEST_CONN_STR
替换为你的测试数据库连接字符串。 -
运行
docker-compose -f docker-compose.test.yml up
来启动测试环境并运行测试。
2. 模拟数据库连接:
你可以使用
unittest.mock
或
pytest-mock
库来模拟
pyodbc.connect
函数,并返回一个模拟的数据库连接对象。 这种方法不需要安装 ODBC 驱动,但你需要修改测试代码以使用模拟的连接。
-
安装
pytest-mock
:pip install pytest-mock
- 修改测试代码:
from unittest.mock import MagicMock
# ...
def test_healthcheck(mocker):
"""Test the healthcheck endpoint"""
mock_conn = MagicMock()
mocker.patch('pyodbc.connect', return_value=mock_conn)
with app.test_client() as test_client:
response = test_client.get("/")
assert response.status_code == 200
assert response.data == b"Healthcheck"
3. 在测试环境中安装 ODBC 驱动:
你可以尝试在你的本地环境中安装与 Docker 容器相同的 ODBC 驱动和配置。 但是,这种方法容易出错,并且在不同的环境中可能难以维护。
建议使用第一种方法,因为它可以提供一个更可靠和可重复的测试环境。
标签:python,flask,pytest From: 78785596