为什么我的代码在本地安装和GitHub Action之间生成了一个不同的SQLite文件?

ne5o7dgx  于 2023-01-26  发布在  SQLite
关注(0)|答案(2)|浏览(135)

我有一个Python模块来处理我的SQLite数据库,这个模块提供了两个函数:

  • init_database()创建包含所有CREATE TABLE语句的数据库文件,如果数据库尚不存在,则执行该文件。
  • upgrade_database()更新数据库的模式(ALTER TABLE和其他更改),它在从我的程序的旧版本迁移时执行。

为了确保应用程序的这一关键部分按预期工作,我为PyTest编写了一些测试,以检查一旦执行了这些函数,我们是否确实获得了一些内容。
我检查init部分的测试如下所示:

def test_init_database():
    # PATH_DIRNAME is a constant with the path where the files are stored
    db_path = f"{PATH_DIRNAME}/files/database.db"

    if path.exists(db_path):
        # Delete the file if it exists (happens if the test has already been run)
        remove(db_path)

    get_db(db_path).init_database()

    with open(f"{PATH_DIRNAME}/files/database/database.sha256", "r") as file:
        # The file may contain a blank line at the end, we just take the first one
        # This is the hash sum we should get if the file is correctly generated
        expected_sum = file.read().split("\n")[0]

    with open(db_path, "rb") as file:
        # Compute the SHA-256 hash sum of the generated database file, and compare it
        assert hashlib.sha256(file.read()).hexdigest() == expected_sum

如果我在本地运行这个测试,它会毫无问题地通过。但是如果我在GitHub Action上运行它,它会在Assert时失败,因为哈希值不同。然后我配置了GH Action工作流,将生成的文件上传到一个工件中,这样我就可以自己检查它们。在本地环境中生成的文件和在工作流中生成的文件之间似乎有细微的差异:

$ xxd gha_workflow/database.db > gha_workflow.hex
$ xxd local/database.db > local.hex
$ diff local.hex gha_workflow.hex
7c7
< 00000060: 002e 5f1d 0d0f f800 0a0b ac00 0f6a 0fc7  .._..........j..
---
> 00000060: 002e 5f1c 0d0f f800 0a0b ac00 0f6a 0fc7  .._..........j..

请注意,第四个字节不同(1d1c)。
是什么导致了这种差异?我做错测试了吗?

2izufjch

2izufjch1#

根据sqlite版本或构建选项的不同,生成的数据库的格式可能会有所不同。例如,版本和页面大小可能会更改,这可能会改变数据库的物理格式。根据您要实现的目标,您可能需要尝试与架构和内容的逻辑表示进行比较。
有关文件格式和构建选项的详细信息,请查看以下文档页:

aydmsdu9

aydmsdu92#

基于评论中给出的建议,我认为我已经找到了一种更好的方法来测试数据库模式,而不依赖于文件的元数据。
我没有计算SHA-256和,而是获取表模式并将其与字段进行比较,以查看数据库是否格式良好。
要获取模式,SQLite提供了以下语法:

PRAGMA table_info('my_table');

我可以用Python像运行任何常规SQL查询一样运行它,它将返回一个元组列表,对于每个字段,包含:

  • 所述位置
  • 字段名
  • 字段类型
  • 如果可为空,则为0,否则为1
  • 默认值(如果没有,则为None
  • 如果是主键,则为1

谢谢你帮助我认识到我的错误!

相关问题