Python 3.x Pytest Cov报告缺少模拟异常返回

Python 3.x Pytest Cov报告缺少模拟异常返回,python-3.x,unit-testing,pytest,pytest-mock,pytest-cov,Python 3.x,Unit Testing,Pytest,Pytest Mock,Pytest Cov,我是一名网络工程师,正在尝试编写一些Python,因此每天都在学习。我对单元测试和Pytest覆盖率报告有意见。我想我理解单元测试和pytest的概念 我有一个使用套接字进行DNS查找的函数 def get_ip(d): """Returns the first IPv4 address that resolves from 'd' Args: d (string): string that needs to be resolved

我是一名网络工程师,正在尝试编写一些Python,因此每天都在学习。我对单元测试和Pytest覆盖率报告有意见。我想我理解单元测试和pytest的概念

我有一个使用套接字进行DNS查找的函数

def get_ip(d):
    """Returns the first IPv4 address that resolves from 'd'

    Args:
        d (string): string that needs to be resolved in DNS.

    Returns:
        string: IPv4 address if found
    """
    logger.info("Returns IP address from hostname: " + d)
    try:
        data = socket.gethostbyname(d)
        ip_addr = repr(data).strip("'")
        logger.debug("IP Address Resolved to: " + ip_addr)
        return ip_addr
    except socket.gaierror:
        return False
我已经写了一个单元测试,通过得很好。我正在使用pytestmock来处理DNS查找套接字的模拟。副作用似乎是模仿异常,我将return_值设置为False,我假设我已经断言返回False,测试通过了ok,这就是为什么我假设我的测试是ok

import pytest
import pytest_mock
import socket
from utils import network_utils

@pytest.fixture
def test_setup_network_utils():
    return network_utils

def test_get_ip__unhappy(mocker, test_setup_network_utils):
    mocker.patch.object(network_utils, 'socket')
    test_setup_network_utils.socket.gethostbyname.side_effect = socket.gaierror
    with pytest.raises(Exception):
        d = 'xxxxxx'
        test_setup_network_utils.socket.gethostbyname.return_value = False
        test_setup_network_utils.get_ip(d)
    assert not test_setup_network_utils.socket.gethostbyname.return_value
    test_setup_network_utils.socket.gethostbyname.assert_called_once()
    test_setup_network_utils.socket.gethostbyname.assert_called_with(d)
pytest cov报告显示返回错误行未被覆盖

pytest --cov-report term-missing:skip-covered --cov=utils unit_tests

network_utils.py     126      7    94%   69
第69行是函数中代码的下一行

except socket.gaierror:
    return False <<<<<<<< This is missing from the report
除了socket.gai错误:
声明时返回False

mocker.patch.object(network_utils, 'socket')
您将用单个模拟替换整个
套接字
模块,因此
套接字
模块中的所有内容也将成为模拟,包括
套接字.gaierror
。因此,当试图在运行测试时捕获
socket.gaierro
时,Python会抱怨它不是异常(不从
BaseException
中生成子类),并失败。因此,不执行所需的返回行

总的来说,您的测试看起来过于工程化,并且包含大量不必要的代码。您需要什么
测试设置\u网络\u实用工具
?为什么在测试中捕获任意异常?重新访问的
test\u get\u ip\u unful
,涵盖了
GAIRROR
案例中的完整代码:

def test_get_ip__unhappy(mocker):
    # test setup: patch socket.gethostbyname so it always raises
    mocker.patch('spam.socket.gethostbyname')
    spam.socket.gethostbyname.side_effect = socket.gaierror

    # run test
    d = 'xxxxxx'
    result = spam.get_ip(d)

    # perform checks
    assert result is False
    spam.socket.gethostbyname.assert_called_once()
    spam.socket.gethostbyname.assert_called_with(d)

当然,
spam
只是一个例子;将其替换为您的实际导入。

谢谢您的回复,您用模拟解释的内容是有意义的。在代码中,我在测试中使用test\u setup\u network\u utils fixture参数来删除VScode抛出的错误,这可能不合理,但我每天都在学习。你建议的代码工作得很好,我有一个干净的测试,所有的行都被覆盖了。再次感谢。