Windows下使用pytest创建不可读文件做单元测试,有无更简便方法?
在Windows下用pytest创建不可读文件的简便方法
针对你在Windows环境下用pytest测试文件读取权限错误的需求,这里提供几种比手动调用subprocess.run(icacls)更简便的实现方式:
1. 封装成可复用的pytest Fixture
既然你已经知道用icacls,可以把权限修改逻辑封装成fixture,让所有测试用例直接复用,避免重复代码:
import subprocess import pytest @pytest.fixture def unreadable_file(tmp_path): # 创建临时测试文件 test_file = tmp_path / "locked.txt" test_file.write_text("sample content") # 用icacls拒绝当前用户的读取权限 subprocess.run( ["icacls", str(test_file), "/deny", "%USERNAME%:R"], check=True, capture_output=True, text=True ) try: yield test_file finally: # 测试结束后恢复权限,防止临时文件清理失败 subprocess.run( ["icacls", str(test_file), "/remove:d", "%USERNAME%"], check=True, capture_output=True, text=True )
使用示例
测试用例里直接引用这个fixture即可:
def test_read_unreadable_file(unreadable_file): # 验证读取操作触发PermissionError with pytest.raises(PermissionError): with open(unreadable_file, "r") as f: f.read()
2. 用pywin32直接操作Windows权限(无外部命令依赖)
如果不想依赖icacls命令,可以用pywin32库直接通过Windows API修改文件权限,更贴近Python原生实现:
首先安装依赖:
pip install pywin32
然后编写fixture:
import win32api import win32security import pytest from pywintypes import error as PyWinError @pytest.fixture def unreadable_file(tmp_path): test_file = tmp_path / "locked.txt" test_file.write_text("sample content") file_path = str(test_file) # 获取文件安全描述符和当前用户SID sd = win32security.GetFileSecurity(file_path, win32security.DACL_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() current_user = win32api.GetUserName() user_sid, _, _ = win32security.LookupAccountName(None, current_user) # 添加拒绝读取权限的访问控制项(ACE) dacl.AddAccessDeniedAce( win32security.ACL_REVISION, win32security.FILE_GENERIC_READ, user_sid ) sd.SetSecurityDescriptorDacl(True, dacl, False) win32security.SetFileSecurity(file_path, win32security.DACL_SECURITY_INFORMATION, sd) try: yield test_file finally: # 清理:移除拒绝权限的ACE sd = win32security.GetFileSecurity(file_path, win32security.DACL_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() for i in range(dacl.GetAceCount()): ace_type, _, _, sid = dacl.GetAce(i) if ace_type == win32security.ACCESS_DENIED_ACE_TYPE and sid == user_sid: dacl.DeleteAce(i) break sd.SetSecurityDescriptorDacl(True, dacl, False) win32security.SetFileSecurity(file_path, win32security.DACL_SECURITY_INFORMATION, sd)
3. 模拟PermissionError(无需真实权限修改)
如果你的核心需求只是验证程序对PermissionError的处理逻辑,而非真实文件权限场景,可以用monkeypatch fixture直接模拟open函数抛出错误,这种方式最轻便高效:
def test_permission_error_handling(monkeypatch): # 替换内置open函数,让它抛出PermissionError def mock_open(*args, **kwargs): raise PermissionError("无法读取文件:权限不足") monkeypatch.setattr("builtins.open", mock_open) # 调用你的业务逻辑函数,验证是否正确捕获错误 with pytest.raises(PermissionError): your_file_processing_function("any_file_path.txt")
内容的提问来源于stack exchange,提问作者Raúl Núñez de Arenas Coronado
相关产品推荐
相关产品推荐

