首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python试/除块单元测试

Python试/除块单元测试
EN

Stack Overflow用户
提问于 2019-09-17 16:47:03
回答 3查看 6.6K关注 0票数 3

我对单元测试具有以下功能:

代码语言:javascript
复制
#!/usr/bin/env python3
# https://docs.python.org/3/library/ipaddress.html
# https://docs.python.org/3.4/library/unittest.html

import ipaddress
import unittest

from unittest.mock import patch
from unittest import TestCase

def validate_IP():
    """Prompt user for IPv4 address, then validate."""

    while True:
        try:
            return ipaddress.IPv4Address(input('Enter a valid IPv4 address: '))
        except ValueError:
            print('Bad value, try again.')


class validate_IP_Test(unittest.TestCase):

    @patch('builtins.input', return_value='192.168.1.1')
    def test_validate_IP_01(self, input):
        self.assertIsInstance(validate_IP(), ipaddress.IPv4Address)

    @patch('builtins.input', return_value='10.0.0.1')
    def test_validate_IP_02(self, input):
        self.assertIsInstance(validate_IP(), ipaddress.IPv4Address)

    @patch('builtins.input', return_value='Derp!')
    def test_validate_IP_03(self, input):
        self.assertRaises(ValueError, msg=none)


if __name__ == '__main__':
    unittest.main()

该函数使用Python3中的Python3模块验证用户输入,即检查用户输入是否为实际的IPv4 address。我的前两次测试就像预期的一样。但是,我不清楚如何使用Python3 3的unittest模块对函数的异常部分进行无效输入的测试,就像在第三个测试中一样。

输入无效输入时,测试应识别抛出异常并通过测试。作为参考,下面是解释器输入无效地址时的相关输出:

代码语言:javascript
复制
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File 
raise AddressValueError("Expected 4 octets in %r" % ip_str)
ipaddress.AddressValueError: Expected 4 octets in 'derp'`
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-09-17 16:58:49

您可以将assertRaises方法用作上下文管理器:

代码语言:javascript
复制
@patch('builtins.input', return_value='Derp!')
def test_validate_IP_03(self, input):
    with self.assertRaises(ValueError):
        validate_IP()

但是,您的validate_IP函数在无限循环中捕获异常本身,因此上面的测试实际上不会通过。如果希望能够在调用之外捕获异常,则可以使其不重试,并在输出错误消息后重新引发异常:

代码语言:javascript
复制
def validate_IP():
    try:
        return ipaddress.IPv4Address(input('Enter a valid IPv4 address: '))
    except ValueError:
        print('Bad IPv4 address.')
        raise
票数 3
EN

Stack Overflow用户

发布于 2019-09-17 16:55:26

异常不被识别,因为您捕获了它,您需要不捕获它或重新引发它。要重新引发,只需在catch块中不带参数地调用raise,在您的示例中:

代码语言:javascript
复制
 def validate_IP():
    """Prompt user for IPv4 address, then validate."""

    while True:
        try:
            return ipaddress.IPv4Address(input('Enter a valid IPv4 address: '))
        except ValueError:
            print('Bad value, try again.')
            raise

这会让你走出那个while,让它变得毫无意义。对于另一种方法或函数,我会将其移除,这样您就可以单独测试IPv4Address引发行为。

另一个问题是在函数中调用input,这对于测试来说非常烦人。我会选择def validate_ip(ip):,测试起来容易得多。

致以敬意,

票数 1
EN

Stack Overflow用户

发布于 2019-09-17 21:37:54

无效输入的可见行为是请求新输入。它是通过捕获异常来完成的,这是测试最好不关心的实现细节,这样您就可以在不中断测试的情况下更改实现细节。问题中的回溯是IPv4Address会做什么,而不是validate_IP()会做什么。

此外,当地址无效时,您还期望AddressValueError,捕获ValueError可能会隐藏其他意外异常并使调试更加困难,因此您应该更好地捕获更具体的异常:

代码语言:javascript
复制
def validate_IP():
    """Prompt user for IPv4 address, then validate."""

    while True:
        try:
            return ipaddress.IPv4Address(input('Enter a valid IPv4 address: '))
        except ipaddress.AddressValueError:
            print('Bad value, try again.')

您可能希望您的测试告诉您的一个故事是:如果输入流包含无效的IP,然后包含一个有效的IP,那么我们就放弃前者,返回后者。

代码语言:javascript
复制
@patch('builtins.input', side_effect=('Derp!', '10.0.0.1'))
def test_invalid_IP(self, input):
    self.assertEqual(validate_IP(), ipaddress.IPv4Address('10.0.0.1'))

顺便说一句,我建议您重新考虑名称,我认为validate_IP并没有真正说明该函数正在做什么,而且测试名称也几乎毫无意义。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57978703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档