首页 > 编程问答 >每次测试后自动清理 postgres 数据库

每次测试后自动清理 postgres 数据库

时间:2024-07-23 15:39:50浏览次数:12  
标签:python postgresql sqlalchemy pytest

我有与 postgres 数据库对话的 sqlalchemy 应用程序。我想使用测试容器进行一些“集成测试”并尝试各种场景。

只是为了让事情变得简单,假设在我的应用程序中我只期望一个表 users 至少包含 admin 行。

我希望这在所有 测试中可用。这就像我的数据库状态的“基线”。 然后我想做多个测试,例如检查我是否可以登录到应用程序,无论是管理员还是普通用户

我想创建不同的“场景” - 每个测试可能有一个,数据库上有不同的数据。

例如,我想做 3 个测试

,其中只有

  1. admin ,其中有 2 行:| ||和
  2. 其中有 4 行: admin user_foo
  3. admin user_x 对于每个测试,我想要/需要编写 3 个不同的装置。我可以使用“原始sql”或sqlalchemy本身,现在并不重要。 user_y 但是在运行测试之后(它本身也可能改变数据库的内容)我需要“回滚”到原始的“基线”状态。 user_z

但是我不能只是运行

,因为所有更改实际上都已提交。

如何确保数据库在每次测试之前处于“基线”状态(+适当的固定装置)?|| |我发现的唯一解决方案是 ROLLBACK 在每次测试之前删除数据库并从头开始重建

手动编写适当的sql来恢复数据库状态

忽略该问题并希望它有效...| ||第一个运行缓慢,第二个难以维护,第三个......不是解决方案。

  • 理想情况下,我希望有一种方法告诉 pg “标记”数据库的状态并恢复我运行测试后。 是否可以?
  • manually write the appropriate sql to restore the db status
  • ignore the issue and hope it works...

The first one is slow to run, the second is unmantainable and the third... is not a solution.

Ideally I would like to have a way to tell pg to "tag" the status of the db and restore it after I've run the test. Is it possible?


可以使用测试函数作为 pytest fixture 的一部分来实现此目的。 此方法依赖于事务在测试完成后回滚这一事实,从而有效地撤消了对数据库所做的任何更改。 下面是操作方法:

import pytest
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker

# 配置测试数据库连接
DATABASE_URL = "postgresql://user:password@host:port/database"

@pytest.fixture(scope="session")
def engine():
    """创建一个 SQLAlchemy 引擎。"""
    engine = create_engine(DATABASE_URL)
    yield engine
    engine.dispose()

@pytest.fixture(scope="session")
def session_factory(engine):
    """创建一个 SQLAlchemy 会话工厂。"""
    return sessionmaker(autocommit=False, autoflush=False, bind=engine)

@pytest.fixture(scope="function")
def session(session_factory):
    """为每个测试函数创建一个 SQLAlchemy 会话,并在完成后回滚事务。"""
    session = session_factory()
    yield session
    session.rollback()
    session.close()

@pytest.fixture(scope="function")
def baseline_data(session):
    """将数据库填充到其基线状态。"""
    session.execute(text("INSERT INTO users (username) VALUES ('admin')"))
    session.commit()

# 测试示例

def test_admin_login(session, baseline_data):  # 注意 baseline_data 依赖项
    """测试管理员登录。"""
    # 执行登录操作并进行断言...

def test_user_creation(session, baseline_data):
    """测试用户创建。"""
    # 执行用户创建操作并进行断言...

    # 对数据库所做的更改将在测试后回滚

说明:

  1. Fixtures: pytest fixtures ( @pytest.fixture ) 用于设置测试环境。 它们有助于避免代码重复,并提供了一种在测试中共享资源的干净方法。

  2. 数据库连接: engine fixture 建立与 PostgreSQL 数据库的连接。 session_factory fixture 创建一个可以生成数据库会话的工厂。

  3. 会话管理: session fixture 对于每个测试函数都至关重要。 它创建了一个新的数据库会话,并且至关重要的是, 在测试完成后回滚 事务。 此回滚可确保每个测试都从一个干净的状态开始,因为在测试期间所做的任何更改都会被撤消。

  4. 基线数据: baseline_data fixture 负责将数据库设置为其基线状态。 在这种情况下,它会插入一个 admin 用户。 通过将其作为依赖项包含在测试函数中,可以在每次测试之前应用此基线状态。

  5. 测试函数:

  6. test_admin_login test_user_creation 是测试函数示例。
  7. 它们都依赖于 session baseline_data fixtures。 这种依赖关系确保:
    • 每个测试都获得一个新的数据库会话。
    • 基线数据在每个测试之前都已加载。
  8. 在这些测试函数中所做的任何数据库更改都将在测试完成后安全地回滚。

如何运行测试:

使用 pytest 运行的测试,它将自动处理 fixtures 的设置和拆除:

pytest

通过此设置,不必在每次测试后手动清理数据库。 回滚机制可确保测试彼此隔离,并且始终从一致的基线状态开始。

标签:python,postgresql,sqlalchemy,pytest
From: 78782122

相关文章

  • 在我的 python 代码中,我无法使用 slixmpp 连接到 Openfire 服务器
    在我的python代码中,我无法连接到Openfire服务器。我想连接到OpenFire服务器我的代码是importthreadingimporttkinterastkfromtkinterimportsimpledialog,scrolledtextimportjsonimportloggingimportasynciofromslixmppimportClientXMPPcla......
  • 如何在Python中获取字符的unicode?
    想要获取中文或越南语的汉名和日文字符的unicode我已经尝试过这些代码text="......
  • 三种语言实现计算逆序对的数量(C++/Python/Java)
    题目给定一个长度为......
  • python项目中__init__.py是什么文件有什么作用
    __init__.py 文件在Python项目中的作用主要是将目录标识为一个Python包。它在包的初始化过程中起到了重要作用。具体来说,__init__.py 文件有以下几个功能:1.标识包:-当一个目录中包含 __init__.py 文件时,这个目录就被视为一个Python包。这样,Python解释器就能够识别......
  • 从零开始构建你的第一个Python Web应用
    在本文中,我们将带领你从零开始构建一个简单的PythonWeb应用。不需要任何先验知识,我们会一步步地指导你完成设置、框架选择、代码编写到部署的整个过程。无论你是Web开发新手还是希望扩展技能的老手,这篇文章都将为你提供一个实践操作的起点。一、前言随着互联网技术的飞速......
  • Python中的global关键字是如何工作的?
    在Python中,global关键字扮演着特殊而重要的角色,它主要用于在函数内部声明全局变量。理解global关键字的工作原理,首先需要明确Python中变量作用域的概念,以及为什么需要global关键字。下面,我将详细解释global关键字的工作机制,包括其作用、使用场景、注意事项,以及它在Python编......
  • Python中enumerate()函数
    Python中enumerate()函数的作用是什么?enumerate()函数在Python中是一个非常有用的内置函数,它用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中。使用enumerate()可以使你在循环中获取每个元素的同时,也能......
  • 我无法解决 python 捕获脚本中的此错误
    defclick_folder(self,文件夹名称):尝试:#单击主文件夹main_folder=self.wait.until(EC.presence_of_element_located((By.XPATH,f"//div[contains(@class,'folders-text_block')]//div[text()='{folder_name}']")))main_folder.click()print......
  • 尝试从图像 url 中抓取图像(使用 python urllib ),但获取 html
    我尝试从以下网址获取图像。http://upic.me/i/fj/the_wonderful_mist_once_again_01.jpg我可以右键单击并另存为,但是当我尝试使用urlretrievelikeimporturllibimg_url='http://upic.me/i/fj/the_wonderful_mist_once_again_01.jpg'urllib.urlretriev......
  • Python-深度学习算法实用指南-全-
    Python深度学习算法实用指南(全)原文:zh.annas-archive.org/md5/844a6ce45a119d3197c33a6b5db2d7b1译者:飞龙协议:CCBY-NC-SA4.0前言深度学习是人工智能领域最受欢迎的领域之一,允许你开发复杂程度各异的多层模型。本书介绍了从基础到高级的流行深度学习算法,并展示了如何使用......