单元测试:修补 os 加入覆盖 os 加入测试文件
Unit test: patching os join overwrites os join in test file
我正在为使用 os.makedirs
和 os.path.join
创建文件夹的函数编写单元测试。当我尝试模拟 class BuilddataHelpers 中使用的特定 os.path.join 时,它还会修补测试文件中的 os.path.join
。如何在测试文件中仍然使用 os.path.join
的同时专门修补正在测试的文件中的 os.path.join
?
datamanager/builddatahelpers.py
import os
PATH = 'not/test/data/either'
class BuilddataHelpers:
def create_folder(self, folder_name):
create_folder_path = os.path.join(PATH, folder_name)
os.makedirs(create_folder_path, exist_ok = True)
return path
datamanager/datamanager.py
class DataManager(BuilddataHelpers):
...
test_builddatahelpers.py
import os
class TestBuilddataHelpers(unittest.TestCase):
global TEST_PATH
TEST_PATH = 'tests/data'
def setUp(self):
super(TestBuilddataHelpers, self).setUp()
self.dm = DataManager()
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(os.path.join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , os.path.join('not', 'test', 'data'))
输出SUBFOLDER PATH: tests/data
。由于 os.makedirs
未修补,因此仍会创建该文件夹。
在您测试的代码中,您执行 import os
,这意味着将使用 os.path.join
而不是本地引用。所以如果你这样做:
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
这和写法完全一样:
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
如果您在测试代码中使用了 from x import y
,那么第一个版本才有意义。在您的情况下,os.path.join
将为所有使用它的模块打补丁。
如果你想使用原来的os.path.join
,你必须把它缓存在某个地方。
一种可能性是只使用:
from os.path import join
...
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , join('not', 'test', 'data'))
保存在 join
中的对 os.path.join
的本地引用将不会被修补。您还可以将其缓存为 class 变量:
import os
class TestBuilddataHelpers(unittest.TestCase):
TEST_PATH = 'tests/data'
join = os.path.join
...
self.assertTrue(os.path.exists(self.join(TEST_PATH, folder_name)))
效果相同
我正在为使用 os.makedirs
和 os.path.join
创建文件夹的函数编写单元测试。当我尝试模拟 class BuilddataHelpers 中使用的特定 os.path.join 时,它还会修补测试文件中的 os.path.join
。如何在测试文件中仍然使用 os.path.join
的同时专门修补正在测试的文件中的 os.path.join
?
datamanager/builddatahelpers.py
import os
PATH = 'not/test/data/either'
class BuilddataHelpers:
def create_folder(self, folder_name):
create_folder_path = os.path.join(PATH, folder_name)
os.makedirs(create_folder_path, exist_ok = True)
return path
datamanager/datamanager.py
class DataManager(BuilddataHelpers):
...
test_builddatahelpers.py
import os
class TestBuilddataHelpers(unittest.TestCase):
global TEST_PATH
TEST_PATH = 'tests/data'
def setUp(self):
super(TestBuilddataHelpers, self).setUp()
self.dm = DataManager()
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(os.path.join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , os.path.join('not', 'test', 'data'))
输出SUBFOLDER PATH: tests/data
。由于 os.makedirs
未修补,因此仍会创建该文件夹。
在您测试的代码中,您执行 import os
,这意味着将使用 os.path.join
而不是本地引用。所以如果你这样做:
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
这和写法完全一样:
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
如果您在测试代码中使用了 from x import y
,那么第一个版本才有意义。在您的情况下,os.path.join
将为所有使用它的模块打补丁。
如果你想使用原来的os.path.join
,你必须把它缓存在某个地方。
一种可能性是只使用:
from os.path import join
...
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , join('not', 'test', 'data'))
保存在 join
中的对 os.path.join
的本地引用将不会被修补。您还可以将其缓存为 class 变量:
import os
class TestBuilddataHelpers(unittest.TestCase):
TEST_PATH = 'tests/data'
join = os.path.join
...
self.assertTrue(os.path.exists(self.join(TEST_PATH, folder_name)))
效果相同