Pytest Cov 报告缺少模拟异常 Returns
Pytest Cov Report Missing Mock Exception Returns
我是一名网络工程师,正在尝试编写一些 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
我写了一个单元测试,它通过了。我正在使用 pytest-mock 来处理 DNS 查找套接字的模拟。副作用似乎是在嘲笑异常,我将 return_value 设置为 False,我假设我断言 False 是 returned,测试通过了,这就是为什么我假设我的测试没问题
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 报告显示 return 假线未被覆盖。
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
任何关于为什么 False 的 return 没有被声明为涵盖的指示将不胜感激。就像我上面说的,我对 Python 和编码很陌生,这是我在 Whosebug 上的第一个问题。希望我已经解释了我的问题,并为一些指导提供了足够的信息。
当你申报时
mocker.patch.object(network_utils, 'socket')
您正在用一个 mock 替换整个 socket
模块,因此 socket
模块中的所有内容也都变成了 mock,包括 socket.gaierror
。因此,当尝试捕获 socket.gaierror
而 运行 测试时,Python 会抱怨它不是异常(不从 BaseException
继承)并失败。因此,没有执行所需的 return 行。
总的来说,您的测试看起来设计过度并且包含很多不必要的代码。你需要 test_setup_network_utils
做什么?为什么要在测试中捕获任意异常?重温 test_get_ip__unhappy
,涵盖 gaierror
案例中的完整代码:
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
只是一个例子;将其替换为您的实际导入。
我是一名网络工程师,正在尝试编写一些 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
我写了一个单元测试,它通过了。我正在使用 pytest-mock 来处理 DNS 查找套接字的模拟。副作用似乎是在嘲笑异常,我将 return_value 设置为 False,我假设我断言 False 是 returned,测试通过了,这就是为什么我假设我的测试没问题
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 报告显示 return 假线未被覆盖。
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
任何关于为什么 False 的 return 没有被声明为涵盖的指示将不胜感激。就像我上面说的,我对 Python 和编码很陌生,这是我在 Whosebug 上的第一个问题。希望我已经解释了我的问题,并为一些指导提供了足够的信息。
当你申报时
mocker.patch.object(network_utils, 'socket')
您正在用一个 mock 替换整个 socket
模块,因此 socket
模块中的所有内容也都变成了 mock,包括 socket.gaierror
。因此,当尝试捕获 socket.gaierror
而 运行 测试时,Python 会抱怨它不是异常(不从 BaseException
继承)并失败。因此,没有执行所需的 return 行。
总的来说,您的测试看起来设计过度并且包含很多不必要的代码。你需要 test_setup_network_utils
做什么?为什么要在测试中捕获任意异常?重温 test_get_ip__unhappy
,涵盖 gaierror
案例中的完整代码:
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
只是一个例子;将其替换为您的实际导入。