You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pytest校验SQLite数据库创建及CSV导出测试报错排查

问题根因
  • 全局共享Crud_db实例导致测试用例之间状态互相干扰,前一个测试打开的数据库连接未关闭就执行下一个测试,容易触发文件占用EBUSY错误
  • tmpdir是pytest自动创建的临时文件夹,你没有将数据库、CSV输出路径指向这个临时目录,文件实际生成在项目根目录,尝试直接读取临时文件夹本身(不是目标文件)自然触发PermissionError
  • 测试逻辑未做资源清理,测试生成的文件残留在工作目录,反复运行容易出现文件锁冲突
正确测试实现
import os
import pytest
import sqlite3
import pandas as pd
from class_helper import Crud_db


def test_connect_creates_db_file(tmpdir):
    # 数据库文件放在临时目录,避免污染项目工作目录
    db_path = tmpdir.join("test.db")
    db = Crud_db(database=str(db_path))
    
    # 连接前确认文件不存在
    assert not os.path.exists(db_path)
    
    db.connect()
    # 连接创建后主动关闭,释放文件锁
    db.close()
    
    # 校验数据库文件成功生成
    assert os.path.exists(db_path)
    # 额外校验生成的是合法sqlite文件
    verify_conn = sqlite3.connect(str(db_path))
    verify_conn.close()


def test_tables(tmpdir):
    # 每个测试用例单独创建db实例,禁止全局共享实例
    db_path = tmpdir.join("test.db")
    db = Crud_db(database=str(db_path))
    db.connect()
    
    # 注意:你原测试用全局实例连接本地已有库才能查到8张表,临时空库必须先执行业务建表逻辑
    # 此处补全你业务的8张表CREATE TABLE语句,执行后commit
    # 示例:
    # db.execute("CREATE TABLE general_bill (...)")
    # db.execute("CREATE TABLE expenses (...)")
    # ... 补全剩余6张表建表语句
    # db.connection.commit()

    query = """ SELECT name FROM sqlite_master WHERE type='table' """
    db.execute(query)
    result = db.cursor.fetchall()
    db.close()
    
    assert len(result) == 8


class TestFile:
    def test_save_all_csv(self, tmpdir, monkeypatch):
        # 切换当前工作目录到临时目录,无需修改业务代码的相对路径逻辑,所有CSV自动输出到临时目录
        monkeypatch.chdir(tmpdir)
        
        # 初始化临时测试库,建表并插入测试数据,避免读空表报错
        db_path = tmpdir.join("test.db")
        db = Crud_db(database=str(db_path))
        db.connect()
        db.execute("CREATE TABLE general_bill (id INT, content TEXT)")
        db.execute("CREATE TABLE expenses (id INT, amount FLOAT)")
        db.execute("CREATE TABLE total (id INT, total FLOAT)")
        # 插入测试数据
        db.execute("INSERT INTO general_bill VALUES (1, 'test')")
        db.execute("INSERT INTO expenses VALUES (1, 100.0)")
        db.execute("INSERT INTO total VALUES (1, 200.0)")
        db.connection.commit()
        db.close()

        # 执行全量导出
        db.save_to_csv()

        # 校验目标CSV文件全部生成
        expected_files = [
            "general_bill_all.csv",
            "expenses_all.csv",
            "total_day_all.csv"
        ]
        for file_name in expected_files:
            target_file = tmpdir.join(file_name)
            assert os.path.exists(target_file), f"导出文件{file_name}未生成"
            # 可选:校验CSV内容正确性
            df = pd.read_csv(str(target_file))
            assert len(df) == 1

    def test_save_specified_day_csv(self, tmpdir, monkeypatch):
        monkeypatch.chdir(tmpdir)
        db_path = tmpdir.join("test.db")
        db = Crud_db(database=str(db_path))
        db.connect()
        # 建表并插入指定日期测试数据
        db.execute("CREATE TABLE general_bill (id INT, date_g TEXT)")
        db.execute("CREATE TABLE expenses (id INT, date TEXT)")
        db.execute("CREATE TABLE total (id INT, date TEXT)")
        test_day = "2024-01-01"
        db.execute(f"INSERT INTO general_bill VALUES (1, '{test_day}')")
        db.execute(f"INSERT INTO expenses VALUES (1, '{test_day}')")
        db.execute(f"INSERT INTO total VALUES (1, '{test_day}')")
        db.connection.commit()
        db.close()

        # 执行指定日期导出
        db.save_to_csv(day=test_day)

        # 校验对应日期的CSV文件生成
        expected_files = [
            f"general_bill_{test_day}.csv",
            f"expenses_{test_day}.csv",
            f"total_day_{test_day}.csv"
        ]
        for file_name in expected_files:
            assert os.path.exists(tmpdir.join(file_name))
关键注意事项
  • 所有测试用例单独初始化Crud_db实例,测试完成后主动调用close()释放数据库连接,从根源避免文件锁占用报错
  • 测试生成的所有文件(数据库、CSV)全部放在tmpdir临时目录下,测试结束后pytest会自动清理,不会残留垃圾文件到项目目录
  • 校验文件存在性时必须指向具体文件路径,不能直接对文件夹调用读方法
  • 用monkeypatch.chdir(tmpdir)切换工作目录,不需要修改原有业务代码的相对路径写文件逻辑,就能实现测试文件隔离

内容的提问来源于stack exchange,提问作者zaki_zardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:42:09