在我的 python 应用程序中,我使用程序启动位置的相对路径打开 mp3 文件。为了简单起见,我对我的项目中遇到的问题做了最小化的重现here。
基本上,我有这样的结构:
src
└─ main.py
test
└─ test_main.py
在
main.py
中,我有一个简单的函数,可以打印并返回当前工作目录:
def get_cwd() -> str:
directory = os.path.basename(os.getcwd())
print('Current directory =', directory)
return directory
因此,如果我
cd
进入 src
文件夹并运行 python main.py
我会看到:
Current directory = src
这是期望的行为,因为在我的程序中,mp3 文件的文件路径是相对于
src
。
当我尝试编写测试时,问题就出现了。我似乎无法通过这样的测试,无论我通过什么
--start-directory
和--top-level-directory
:
def test_get_cwd(self):
print('testing get_cwd()')
current_dir = get_cwd()
self.assertIsNotNone(current_dir)
self.assertEqual(current_dir, 'src')
问题:如果将测试保存到不同的目录,我如何才能像在特定目录的上下文中运行测试一样运行测试?
限制:
from
src.main import get_cwd
有一个
os
功能可以更改目录,尝试将os.chdir('src')
添加到您的测试中。
import unittest
import os
from src.main import get_cwd
class TestMain(unittest.TestCase):
def test_get_cwd(self):
os.chdir('src')
print('testing get_cwd()')
current_dir = get_cwd()
self.assertIsNotNone(current_dir)
self.assertEqual(current_dir, 'src')
一个选项是模拟由
os.path.basename
给出的值,返回值为"src"
import unittest
from mock import patch
from src.main import get_cwd
class TestMain(unittest.TestCase):
@patch('os.path.basename')
def test_get_cwd(self, basename):
basename.return_value = "src"
print('testing get_cwd()')
current_dir = get_cwd()
self.assertIsNotNone(current_dir)
self.assertEqual(current_dir, 'src')
我经常这样做是为了为每个测试创建一个临时目录,特别是在测试文件解析脚本时。
import unittest
import tempfile
import os
class TempDirTest(unittest.TestCase):
def setUp(self):
# Create temp folder (deleted when test is done)
self.tempdir = tempfile.TemporaryDirectory()
self.addCleanup(self.tempdir.cleanup)
# Remember original CWD, and go back there after each test
self._origin_cwd = os.getcwd()
os.chdir(self.tempdir.name)
def _revert_cwd():
os.chdir(self._origin_cwd)
self.addCleanup(_revert_cwd)
def test_stuff(self):
# Create all the relative files & folders you want
os.mkdir('./nested')
with open('nested/foo.txt', 'w') as fh:
fh.write('bar')
这将为每个测试创建一个新文件夹(带有清理),因此在一个测试中创建的文件不会影响下一个测试。
注意:如果进行大量测试或非常频繁(例如:持续集成),请考虑将
tempfile
指向 ramdisk,这将提高磁盘的速度和使用寿命。
还可以考虑使用
StreamIO
对象而不是文件名 str
来制作代码接口,但这并不适合所有情况。