python - 在unittest中使用assertRaises引发但未捕获的自定义异常

标签 python unit-testing ssh paramiko

我编写了一个单元测试来测试我的 SSH 模块,并添加了一个自定义“RemoteCmdError”异常类来通知用户远程命令已经失败。但是,当我将此测试用例添加到单元测试中时,它总是失败并显示“AssertionError:RemoteCmdError 未引发”,尽管异常已经引发。我尝试修改异常名称并使用官方示例重写我的自定义类,但这一切都不起作用。有什么不对??我该如何解决这个问题?这是我的代码:

/BaseLibrary/SSH.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
import logging.config
import json

logger = logging.getLogger(__name__)
with open("logging.json") as f:
    config = json.load(f)
logging.config.dictConfig(config)

import paramiko
import socket

class SSHClient:
    def __init__(self, hostname, username, password, port=22):
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(hostname, username=username, password=password, port=port, look_for_keys=False, timeout=10)

    def run(self, cmd):
        stdin, stdout, stderr = self.ssh.exec_command(cmd, timeout=3600)
        stdin.close()

        try:
            res = "".join(stdout.readlines())
            if stdout.channel.recv_exit_status() != 0:
                error_msg = "Remote command error"
                raise RemoteCmdError(error_msg, cmd, res)
        except RemoteCmdError as e:
            logger.exception("%s (RemoteCmd='%s', ErrorMsg=%s)" %(e.msg, e.cmd, e.res))

        return res.strip() , stdout.channel.recv_exit_status()

    def __del__(self):
        self.ssh.close()

class WindowsSSHClient(SSHClient):
    def powershell(self, cmd):
        prefix = 'powershell '
        powershell_cmd = prefix + cmd
        res = self.run(powershell_cmd)
        return res

class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class RemoteCmdError(Error):
    def __init__(self, msg, cmd, res, *args):
        super(RemoteCmdError, self).__init__(self, *args)
        self.args = args
        self.msg = msg
        self.cmd = cmd
        self.res = res

/测试/test_SSH.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from BaseLibrary.SSH import *
import unittest

class Basic_WindowsSSHClient(unittest.TestCase):

    def setUp(self):
        self.hostname = "10.77.0.123"
        self.username = "Administrator"
        self.password = "1234"

    def tearDown(self):
        self.client = None

    def test_powershell_fail(self):
        self.client = WindowsSSHClient(self.hostname, self.username, self.password)
        with self.assertRaises(RemoteCmdError):
            self.client.powershell("Get-Item afilethatdoesntexist.txt")

控制台输出:

test@virtual-machine:~/$ python -m unittest Tests.test_SSH.Basic_WindowsSSHClient.test_powershell_fail
2016-01-19 09:38:10,557 - [INFO] - paramiko.transport - Connected (version 2.0, client WeOnlyDo)
2016-01-19 09:38:10,699 - [INFO] - paramiko.transport - Authentication (password) successful!
2016-01-19 09:38:11,526 - [ERROR] - BaseLibrary.SSH - Remote command error (RemoteCmd='powershell Get-Item afilethatdoesntexist.txt', ErrorMsg=Get-Item : Cannot find path 
'C:\Users\Administrator\Desktop\afilethatdoesntexist.txt' because it does not 
exist.
At line:1 char:1
+ Get-Item afilethatdoesntexist.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\Admini...doesntexist.t 
   xt:String) [Get-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetIt 
   emCommand

)
Traceback (most recent call last):
  File "BaseLibrary/SSH.py", line 29, in run
    raise RemoteCmdError(error_msg, cmd, res)
RemoteCmdError
F
======================================================================
FAIL: test_powershell_fail (Tests.test_SSH.Basic_WindowsSSHClient)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Tests/test_SSH.py", line 75, in test_powershell_fail
    self.client.powershell("Get-Item afilethatdoesntexist.txt")
AssertionError: RemoteCmdError not raised

----------------------------------------------------------------------
Ran 1 test in 1.066s

FAILED (failures=1)

最佳答案

您需要在记录异常后重新引发:

try:
    res = "".join(stdout.readlines())
    if stdout.channel.recv_exit_status() != 0:
        error_msg = "Remote command error"
        raise RemoteCmdError(error_msg, cmd, res)
except RemoteCmdError as e:
    logger.exception("%s (RemoteCmd='%s', ErrorMsg=%s)" %(e.msg, e.cmd, e.res))
    raise  # HERE

关于python - 在unittest中使用assertRaises引发但未捕获的自定义异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34867971/

相关文章:

python - 更改python请求的IP

C++ Google Test 将测试夹具构造函数定义放在哪里

用作 ssh 输入的 here-document 中的 shell 脚本没有给出任何结果

java - ssh 套接字工厂

c - 通过 SSH 使用 Eclipse 处理远程项目

python - Django:如何在我的模板中有效显示数据?

Python - urllib3 在爬行网站时收到 403 'Forbidden'

python - 如何使用正则表达式在非数字之前拆分句点?

php - 如何对一个方法进行单元测试,该方法调度改变被测方法行为的事件?

c# - MS Test 的测试覆盖率工具