You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:22:52