使用Pytest和Coverage进行Flask单元测试

FlaskFlaskBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将学习如何为 Flask 应用编写单元测试。我们将使用 pytestcoverage 来测试和衡量我们的代码。在本实验结束时,你将了解如何确保你的应用按预期运行,并识别需要改进的地方。

注意:你需要自己创建代码文件并在环境中运行它。你可以在 Web 5000 上预览 Flask 服务状态。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL flask(("`Flask`")) -.-> flask/DataHandlingGroup(["`Data Handling`"]) flask(("`Flask`")) -.-> flask/CoreConceptsGroup(["`Core Concepts`"]) flask(("`Flask`")) -.-> flask/DevelopmentToolsGroup(["`Development Tools`"]) flask/DataHandlingGroup -.-> flask/incoming_request_data("`Incoming Request Data`") flask/DataHandlingGroup -.-> flask/application_globals("`Application Globals`") flask/DataHandlingGroup -.-> flask/response_objects("`Response Objects`") flask/CoreConceptsGroup -.-> flask/application_object("`Application Object`") flask/CoreConceptsGroup -.-> flask/session_interface("`Session Interface`") flask/CoreConceptsGroup -.-> flask/test_client("`Test Client`") flask/CoreConceptsGroup -.-> flask/useful_internals("`Useful Internals`") flask/DevelopmentToolsGroup -.-> flask/blueprint_objects("`Blueprint Objects`") flask/DevelopmentToolsGroup -.-> flask/command_line_interface("`Command Line Interface`") subgraph Lab Skills flask/incoming_request_data -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/application_globals -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/response_objects -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/application_object -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/session_interface -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/test_client -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/useful_internals -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/blueprint_objects -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} flask/command_line_interface -.-> lab-136342{{"`使用Pytest和Coverage进行Flask单元测试`"}} end

安装 Pytest 和 Coverage

首先,我们需要安装 pytestcoverage。它们分别是测试工具和代码测量工具。在你的终端中运行以下命令进行安装:

pip install pytest coverage

设置与夹具

接下来,我们将在名为 conftest.py 的文件中设置测试夹具。夹具是一个函数,在应用它的每个测试函数之前运行。

在这一步中,我们将创建一个临时数据库,并用一些数据填充它以进行测试。

以下是要添加到 tests/conftest.py 中的代码:

## tests/conftest.py

import os
import tempfile
import pytest
from flaskr import create_app
from flaskr.db import get_db, init_db

with open(os.path.join(os.path.dirname(__file__), 'data.sql'), 'rb') as f:
    _data_sql = f.read().decode('utf8')

@pytest.fixture
def app():
    db_fd, db_path = tempfile.mkstemp()

    app = create_app({
        'TESTING': True,
        'DATABASE': db_path,
    })

    with app.app_context():
        init_db()
        get_db().executescript(_data_sql)

    yield app

    os.close(db_fd)
    os.unlink(db_path)

@pytest.fixture
def client(app):
    return app.test_client()

@pytest.fixture
def runner(app):
    return app.test_cli_runner()

为工厂函数编写测试

接下来,我们将为负责创建 Flask 应用的工厂函数编写测试。这些测试可确保应用根据传递给它的配置按预期运行。

以下是要添加到 tests/test_factory.py 中的代码:

## tests/test_factory.py

from flaskr import create_app

def test_config():
    assert not create_app().testing
    assert create_app({'TESTING': True}).testing

def test_hello(client):
    response = client.get('/hello')
    assert response.data == b'Hello, World!'

测试数据库连接

在测试工厂函数之后,我们将测试数据库连接。这些测试可确保数据库连接按预期建立和关闭。

以下是要添加到 tests/test_db.py 中的代码:

## tests/test_db.py

import sqlite3
import pytest
from flaskr.db import get_db

def test_get_close_db(app):
    with app.app_context():
        db = get_db()
        assert db is get_db()

    with pytest.raises(sqlite3.ProgrammingError) as e:
        db.execute('SELECT 1')

    assert 'closed' in str(e.value)

测试认证

接下来,我们将编写用户认证的测试。这些测试可确保用户能够按预期登录和注销,并且在必要时显示适当的错误消息。

以下是要添加到 tests/test_auth.py 中的代码:

## tests/test_auth.py

import pytest
from flask import g, session
from flaskr.db import get_db

def test_login(client, auth):
    assert client.get('/auth/login').status_code == 200
    response = auth.login()
    assert response.headers["Location"] == "/"

    with client:
        client.get('/')
        assert session['user_id'] == 1
        assert g.user['username'] == 'test'

测试博客文章

最后,我们将编写博客文章的测试。这些测试可确保用户能够按预期创建、更新和删除博客文章。

以下是要添加到 tests/test_blog.py 中的代码:

## tests/test_blog.py

import pytest
from flaskr.db import get_db

def test_create(client, auth, app):
    auth.login()
    assert client.get('/create').status_code == 200
    client.post('/create', data={'title': 'created', 'body': ''})

    with app.app_context():
        db = get_db()
        count = db.execute('SELECT COUNT(id) FROM post').fetchone()[0]
        assert count == 2

运行测试

既然我们已经编写了测试,就可以使用 pytest 命令来运行它们:

pytest

要测量测试的代码覆盖率,可以使用 coverage 命令来运行 pytest:

coverage run -m pytest

你可以使用以下命令在终端中查看简单的覆盖率报告:

coverage report

总结

在本实验中,我们学习了如何使用 pytestcoverage 为 Flask 应用编写单元测试。这些工具帮助我们确保应用按预期运行,并识别需要改进的地方。为代码编写测试是一种良好的实践,因为它有助于在问题出现之前发现错误。

您可能感兴趣的其他 Flask 教程