【问题标题】:writing a pytest function to check outputting to a file in python?编写一个pytest函数来检查输出到python中的文件?
【发布时间】:2023-03-08 21:18:01
【问题描述】:

我向this 询问了有关如何编写 pytest 来检查stdout 中的输出的问题并得到了解决方案。现在我需要写一个test case,以检查内容是否写入文件以及内容是否按预期写入 例如:

def writetoafile():
   file = open("output.txt",w)
   file.write("hello\n")
   file.write("world\n")
   file.close()

现在是一个 pytest 函数来检查它是否写了:

def test_writeToFile():
    file = open("ouput.txt",'r')
    expected = "hello\nworld\n"
    assert expected==file.read()

虽然这似乎可行,但我认为这并不理想,尤其是硬编码。这种写文件的test functions通常是怎么写的?

【问题讨论】:

  • 为什么这不理想?您写道您想检查内容是否按预期写入,因此查看文件并检查似乎是最好的选择。您总是可以用一系列随机字符创建一个变量并检查它是否写入成功;您可以检查“expected in file.read()”以查看是否附加了数据(但您使用了标志 'w',所以这是一个糟糕的测试);等等。如果不是这个,你想测试什么?也许知道你想要什么才是真正的问题,就像在大多数测试中一样。

标签: python function file-io pytest


【解决方案1】:

tmpdir fixture 将为您创建一个每次测试的临时目录。所以测试看起来像这样:

def writetoafile(fname):
    with open(fname, 'w') as fp:
        fp.write('Hello\n')

def test_writetofile(tmpdir):
    file = tmpdir.join('output.txt')
    writetoafile(file.strpath)  # or use str(file)
    assert file.read() == 'Hello\n'

在这里,您正在重构代码,使其也不会被硬编码,这是测试代码如何让您设计得更好的一个典型例子。

【讨论】:

  • tmpdir 是做什么的?所以它会在内存中虚拟地创建一个文件?
  • 它会创建一个真实的目录,之后您可以检查它,在 UNIX 上,您通常会在 /tmp/pytest-xxxx 中找到它们,并带有指向最新运行的符号链接。您始终可以通过调用py.test --fixtures 来了解fixture,对于tmpdir 案例,请参阅pytest.org/latest/tmpdir.html 了解更多详细信息。
  • pytest.org/latest/tmpdir.html 不再存在。
  • 文档的链接是 404。您应该始终将文档直接粘贴到您的答案中。
  • 再次更新了文档链接,注意这些天你可能会使用tmp_path 而不是tmpdir。我认为答案已经包含有关如何使用 api 的示例,因此不太确定复制文档的含义。
【解决方案2】:

假设您在一个名为main.py 的文件中拥有这个“惊人”的软件:

"""
main.py
"""

def write_to_file(text):
    with open("output.txt", "w") as h:
        h.write(text)

if __name__ == "__main__":
    write_to_file("Every great dream begins with a dreamer.")

要测试write_to_file 方法,您可以在名为test_main.py 的同一文件夹中的文件中编写类似这样的内容:

"""
test_main.py
"""
from unittest.mock import patch, mock_open

import main


def test_do_stuff_with_file():
    open_mock = mock_open()
    with patch("main.open", open_mock, create=True):
        main.write_to_file("test-data")

    open_mock.assert_called_with("output.txt", "w")
    open_mock.return_value.write.assert_called_once_with("test-data")

我总是尽量避免将文件写入磁盘,即使它是专门用于我的测试的临时文件夹:不实际接触磁盘会使您的测试更快,尤其是当您在代码中与文件进行大量交互时。

【讨论】:

  • 感谢您的回答,在这里提及模拟非常有帮助。这是一篇关于测试的精彩文章(包括像模拟这样的 DoubleTests):martinfowler.com/articles/practical-test-pyramid.html
  • 这应该是正确的答案。始终避免在测试中写入/读取磁盘。虽然它可能更“罗嗦”,但测试会运行得更快,并且比 Flub 提供的答案更多地隔离正在测试的内容
  • 这非常有用!我需要做的一项更改是在调用patch(...) 时将“main.open”换成“builtins.open”
  • 我不会说“总是”避免做任何事情。有时您想要断言您的代码实际上正在按照您认为的方式处理文件系统。
猜你喜欢
  • 2013-12-28
  • 2023-02-02
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多