Python unittest:如何断言文件或文件夹的存在并在失败时打印路径?

Python unittest: How to assert the existence of a file or folder and print the path on failure?

在 python test case 中,我想断言文件或文件夹的存在,并在断言失败时提供有用的错误消息。我该怎么做?

以下当然有效,但它不会在错误消息中产生 path/filename:

import unittest
import pathlib as pl

class TestCase(unittest.TestCase):
    def test(self):
        # ...
        path = pl.Path("a/b/c.txt")
        self.assertTrue(path.is_file())
        self.assertTrue(path.parent.is_dir())

if __name__ == "__main__":
    unittest.main(verbosity=2)
======================================================================
FAIL: test (__main__.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "my_test.py", line 194, in test
    self.assertTrue(path.is_file())
AssertionError: False is not true

在较大的测试中,一眼就能看出哪个文件的断言失败是有益的。如何扩展 unittest.TestCase 以便为此类测试打印更好的断言消息?

======================================================================
FAIL: test (__main__.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "my_test.py", line 194, in test
    self.assertFileExists(path)
AssertionError: File does not exist: "a/b/c.txt"

您可以编写测试,使断言包含路径名:

import unittest
import pathlib as pl

class TestCase(unittest.TestCase):
    def test(self):
        # ...
        path = pl.Path("a/b/c.txt")
        self.assertEquals((str(path), path.is_file()), (str(path), True))

if __name__ == "__main__":
    unittest.main(verbosity=2)

这会给你这样的输出:

======================================================================
FAIL: test_something (__main__.TextExample)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testfoo.py", line 8, in test_something
    self.assertEqual((path, path.is_file()), (path, True))
AssertionError: Tuples differ: (PosixPath('path/to/file'), False) != (PosixPath('path/to/file'), True)

First differing element 1:
False
True

- (PosixPath('path/to/file'), False)
?                                     ^^^^

+ (PosixPath('path/to/file'), True)
?                                     ^^^

但您也可以决定使用 pytest,并像这样编写您的测试:

from pathlib import Path


def test_something():
    path = Path('path/to/file')
    assert path.is_file()

运行 pytest 将自动在您的失败中包含路径:

============================= test session starts ==============================
platform linux -- Python 3.7.5, pytest-4.6.6, py-1.8.0, pluggy-0.13.0
rootdir: /home/lars/tmp
collected 1 item

testfoo.py F                                                             [100%]

=================================== FAILURES ===================================
________________________________ test_something ________________________________

    def test_something():
        path = Path('path/to/file')
>       assert path.is_file()
E       AssertionError: assert False
E        +  where False = <bound method Path.is_file of PosixPath('path/to/file')>()
E        +    where <bound method Path.is_file of PosixPath('path/to/file')> = PosixPath('path/to/file').is_file

testfoo.py:6: AssertionError
=========================== 1 failed in 0.01 seconds ===========================

用额外的断言扩展 unittest.TestCase 最适合我。

import unittest
import pathlib as pl

class TestCaseBase(unittest.TestCase):
    def assertIsFile(self, path):
        if not pl.Path(path).resolve().is_file():
            raise AssertionError("File does not exist: %s" % str(path))

class ActualTest(TestCaseBase):
    def test(self):
        path = pl.Path("a/b/c.txt")
        self.assertIsFile(path)

这产生:

======================================================================
FAIL: test (__main__.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "my_test.py", line 194, in test
    raise AssertionError("File does not exist: %s" % str(path))
AssertionError: File does not exist: a/b/c.txt