标签: python-unittest

为什么我的Python模拟补丁以错误的顺序出现?

我有一个模块test.py,它使用键盘导入*从另一个模块keyboard.py导入函数.

在keyboard.py里面有两个功能:

def get_keys(keyList, timeStamped):
    return event.getKeys(keyList=keyList, timeStamped=timeStamped)

def wait_keys(keyList, timeStamped):
    return event.waitKeys(keyList=keyList, timeStamped=timeStamped)
Run Code Online (Sandbox Code Playgroud)

现在,我在test.py中的测试函数如下所示:

@mock.patch('keyboard.wait_keys')
@mock.patch('keyboard.get_keys')
def test_2(self, mock_waitKeys, mock_getKeys):

    mock_waitKeys.return_value = [['wait_keys!', 0.1]]
    mock_getKeys.return_value = [['get_keys!',0.1]]

    run_blocks(trials,noise,win,expInfo, incorrect, tone1, tone2, experiment_details,allPoints,32,60)            
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我正在尝试将两个模拟返回值放在适当的位置.

然而,他们的影响似乎是倒置的!

当我在交互式控制台中调用它们而在断点处停止时(或在正常调用时检查值),两个模拟函数返回彼此的假返回值!

从控制台:

get_keys()
Out[2]: [['wait_keys!', 0.1]]
wait_keys()
Out[3]: [['get_keys!', 0.1]]
Run Code Online (Sandbox Code Playgroud)

我是否误解了传递给测试函数的模拟参数的顺序?

这可能与修补keyboard.get_keys而不是test.get_keys有关吗?

谢谢!路易丝

python mocking python-mock python-unittest

15
推荐指数
1
解决办法
3366
查看次数

单元测试:如何断言同一方法的多个调用?

我有一个方法,它使用不同的参数调用另一个方法两次.

class A(object):
    def helper(self, arg_one, arg_two):
        """Return something which depends on arguments."""

    def caller(self):
        value_1 = self.helper(foo, bar)  # First call.
        value_2 = self.helper(foo_bar, bar_foo)  # Second call!
Run Code Online (Sandbox Code Playgroud)

使用assert_called_with帮助我断言第一个呼叫,而不是第二个呼叫.甚至assert_called_once_with似乎没有帮助.我在这里错过了什么?有没有办法测试这样的电话?

python unit-testing python-unittest

14
推荐指数
1
解决办法
8226
查看次数

Flask单元测试:获取响应的重定向位置

我有一个基于Flask的webapp,当以某种方式发布到他们的父文档时偶尔会创建带有新随机密钥的新文档.新密钥进入父级的数据结构,更新的父级临时存储在会话中,并且在成功保存子文档后,存储的父级被拉出会话并存储在一起,以便将两者链接在一起.这是针对某些类型的关系完成的,其中一个人希望在键之间具有固有顺序,因此键被存储为父项上的列表.

现在,当我想使用Werkzeug提供的单元测试客户端进行单元测试时,问题出现了.做一个

 ret = self.test_client.post(
    request_path,
    data=data,
    follow_redirects=True
)
Run Code Online (Sandbox Code Playgroud)

在测试用例对象中将成功使用新密钥重定向到子文档 - 但我不知道在单元测试中检索此新密钥的位置.我无法在返回值的顶部找到一个属性,该属性将指示它被重定向到的位置.dir(ret)给我

 ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_ensure_sequence', '_get_mimetype_params', '_on_close', '_status', '_status_code', 'accept_ranges', 'add_etag', 'age', 'allow', 'autocorrect_location_header', 'automatically_set_content_length', 'cache_control', 'calculate_content_length', 'call_on_close', 'charset', 'close', 'content_encoding', 'content_language', 'content_length', 'content_location', 'content_md5', 'content_range', 'content_type', 'data', 'date', 'default_mimetype', 'default_status', 'delete_cookie', 'direct_passthrough', 'expires', 'force_type', 'freeze', 'from_app', 'get_app_iter', 'get_data', 'get_etag', 'get_wsgi_headers', 'get_wsgi_response', 'headers', 'implicit_sequence_conversion', 'is_sequence', 'is_streamed', 'iter_encoded', 'last_modified', 'location', …
Run Code Online (Sandbox Code Playgroud)

python werkzeug flask python-unittest

14
推荐指数
2
解决办法
4716
查看次数

使用Python Unittest在Flask中测试重定向

我目前正在尝试为Flask应用程序编写一些单元测试.在我的许多视图功能(例如我的登录)中,我重定向到新页面.例如:

@user.route('/login', methods=['GET', 'POST'])
def login():
    ....
    return redirect(url_for('splash.dashboard'))
Run Code Online (Sandbox Code Playgroud)

我正在尝试验证此重定向是否发生在我的单元测试中.现在,我有:

def test_register(self):
    rv = self.create_user('John','Smith','John.Smith@myschool.edu', 'helloworld')
    self.assertEquals(rv.status, "200 OK")
    # self.assert_redirects(rv, url_for('splash.dashboard'))
Run Code Online (Sandbox Code Playgroud)

此函数确保返回的响应为200,但最后一行显然不是有效的语法.我怎么能断言呢?我的create_user功能很简单:

def create_user(self, firstname, lastname, email, password):
        return self.app.post('/user/register', data=dict(
            firstname=firstname,
            lastname=lastname,
            email=email,
            password=password
        ), follow_redirects=True)
Run Code Online (Sandbox Code Playgroud)

谢谢!

python unit-testing flask python-unittest

14
推荐指数
3
解决办法
1万
查看次数

Django测试运行器在Ubuntu上的virtualenv失败

我一直在努力解决在Ubuntu 14.04上安装在Python virtualenv中的Django测试运行器的问题.相同的软件在MacOS上运行正常,我认为在早期版本的Ubuntu上运行良好.

失败消息是:

ImportError: '<test>' module incorrectly imported from '<base-env>/local/lib/python2.7/site-packages/<package-dir>'. Expected '<base-env>/lib/python2.7/site-packages/<package-dir>'. Is this module globally installed?
Run Code Online (Sandbox Code Playgroud)

并且错误的完整堆栈跟踪是:

  Traceback (most recent call last):
    File "/home/annalist/anenv/bin/django-admin", line 11, in <module>
      sys.exit(execute_from_command_line())
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
      utility.execute()
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
      self.fetch_command(subcommand).run_from_argv(self.argv)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 50, in run_from_argv
      super(Command, self).run_from_argv(argv)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
      self.execute(*args, **options.__dict__)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 71, in execute
      super(Command, self).execute(*args, **options)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
      output = self.handle(*args, **options) …
Run Code Online (Sandbox Code Playgroud)

python django ubuntu virtualenv python-unittest

14
推荐指数
2
解决办法
2771
查看次数

断言已使用特定字符串调用日志记录

我正在尝试用来unittest测试我制作的SimpleXMLRPCServer的一些功能.Togethere with Mock,我现在试图断言在达到if语句时已经记录了一条特定的消息,但是我无法让它工作.我已经尝试在StackOverflow或Googling上找到我在这里找到的各种答案,但仍然没有运气.我在测试用例中进行的调用如下:

def test_listen_for_tasks(self):
    el = {'release': 'default', 'component': None}
    for i in range(50):
        self.server._queue.put(el)
    ServerThread.listen_for_tasks(self.server, 'bla', 'blabla')
    with mock.patch('queue_server.logging') as mock_logging:
        mock_logging.warning.assert_called_with('There are currently {}'
                                                ' items in the queue'.format(
                                                 str(len(self.server._queue.queue))))
Run Code Online (Sandbox Code Playgroud)

服务器中的功能如下:

def listen_for_tasks(self, release, component):
    item = {'release': release, 'component': component}
    for el in list(self._queue.queue):
        if self.is_request_duplicate(el, item):
            logger.debug('Already have a request'
                         ' for this component: {}'.format(item))
            return
    self._queue.put(item, False)
    if len(self._queue.queue) > 50:
        logger.warning('There are currently {}'
                       ' items in the queue'.format(
                        str(len(self._queue.queue))))
Run Code Online (Sandbox Code Playgroud)

知道为什么这不起作用吗?我是Python的单元测试的新手,并声称记录器已经完成了某些事情似乎是人们可能遇到的最大问题,所以我可能已经搞砸了代码中非常简单的东西.任何形式的帮助将不胜感激! …

logging unit-testing mocking python-2.7 python-unittest

14
推荐指数
2
解决办法
8828
查看次数

mock.patch的正确路径

在 Python 中使用模拟时,我遇到了计算路径的问题。

假设我有以下文件

文件1.py

def func1():
    return 'X'
Run Code Online (Sandbox Code Playgroud)

文件2.py

from file1 import func1

class ClassA():

    def func_that_uses_func1(self):
        x = func1()
Run Code Online (Sandbox Code Playgroud)

如何修补 ClassA 上 func1 的使用?我尝试过 @mock.patch('file2.func1'),但出现错误AttributeError: <class 'ClassA'> does not have the attribute 'func1'

python unit-testing mocking python-unittest

14
推荐指数
1
解决办法
1万
查看次数

使用unittest discover传递参数(对于argparse)

foo是一个具有深层目录嵌套的Python项目,包括unittest各种子目录中的~30个文件.在foos内setup.py,我在内部运行了一个自定义的"test"命令

 python -m unittest discover foo '*test.py'
Run Code Online (Sandbox Code Playgroud)

请注意,这使用了unittest发现模式.


由于一些测试非常慢,我最近决定测试应该有"级别".这个问题的答案非常清楚地说明了如何相处unittestargparse相互配合.所以,现在,我可以运行一个单独的单元测试文件,比方说foo/bar/_bar_test.py,与

python foo/bar/_bar_test.py --level=3
Run Code Online (Sandbox Code Playgroud)

并且只运行3级测试.

问题是我无法弄清楚如何使用发现传递自定义标志(在本例中为"--level = 3".我尝试的一切都失败了,例如:

$ python -m unittest discover --level=3 foo '*test.py'
Usage: python -m unittest discover [options]

python -m unittest discover: error: no such option: --level

$ python -m --level=3 unittest discover foo '*test.py'
/usr/bin/python: No module named --level=3
Run Code Online (Sandbox Code Playgroud)

我怎样才能--level=3转到单独的单元测试?如果可能的话,我想避免将不同级别的测试划分为不同的文件.

赏金编辑

pre-bounty(精细)解决方案建议使用系统环境变量.这还不错,但我正在寻找更清洁的东西.

将多文件测试运行器(即python -m …

python command-line argparse python-unittest

14
推荐指数
3
解决办法
4905
查看次数

断言__init__是用正确的参数调用的

我正在使用python模拟声明一个特定的对象是用正确的参数创建的.这是我的代码的样子:

class Installer:
    def __init__(foo, bar, version):
        # Init stuff
        pass
    def __enter__(self):
        return self

    def __exit__(self, type, value, tb):
        # cleanup
        pass

    def install(self):
        # Install stuff
        pass

class Deployer:
    def deploy(self):
        with Installer('foo', 'bar', 1) as installer:
            installer.install()
Run Code Online (Sandbox Code Playgroud)

现在,我想断言installer用正确的参数创建.这是我到目前为止的代码:

class DeployerTest(unittest.TestCase):
    @patch('Installer', autospec=True)
    def testInstaller(self, mock_installer):
        deployer = Deployer()
        deployer.deploy()

        # Can't do this :-(
        mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

  File "test_deployment.py", line .., in testInstaller
    mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
Run Code Online (Sandbox Code Playgroud)

这是固定代码(Call …

python testing mocking python-unittest

14
推荐指数
1
解决办法
5263
查看次数

如何修补一个对象,以便除了一个方法之外的所有方法都被模拟?

我有一个入口点函数main在一个对象上调用它,我想保持未被模拟,因为它在对象上调用了几个其他方法:

class Thing(object):

    def main(self):
        self.alpha()
        self.bravo()

    def alpha(self):
        self.charlie()

    def bravo(self):
        raise TypeError("Requires Internet connection!")

    def charlie(self):
        raise Exception("Bad stuff happens here!")
Run Code Online (Sandbox Code Playgroud)

这很简单,可以手动模拟:

thing = Thing() 
thing.alpha = MagicMock()
thing.bravo = MagicMock()
Run Code Online (Sandbox Code Playgroud)

我可以测试以确保alpha和bravo都被调用一次,我可以在alpha和bravo中设置副作用以确保它们被处理等等.

我担心的是,如果代码定义发生变化并且有人添加了一个charlie调用main.它没有被嘲笑,所以现在会感觉到副作用(而且它们就像写入文件,连接到数据库,从Internet上获取东西,因此这个简单的异常不会提醒我现在的测试坏).

我的计划是验证我的模拟对象不会调用其他方法而不是我应该说的方法(或者引发测试异常).但是,如果我做这样的事情:

MockThing = create_autospec(Thing)
thing = Thing()
thing.main() 

print thing.method_calls
# [calls.main()] 
Run Code Online (Sandbox Code Playgroud)

然后main也被嘲笑,所以它没有其他方法.我怎么能模仿每个方法但主要的方法呢?(我想要method_calls [calls.alpha(), calls.bravo()]).

编辑:用于黑客答案

好吧,我有一个非常hacky解决方案,但我希望有一个比这更好的答案.基本上我从原始类重新绑定方法(Python绑定一个未绑定的方法)

MockThing = create_autospec(Thing)
thing = MockThing()
thing.main = Thing.ingest.__get__(thing, Thing)
thing.main()

print thing.method_calls
# [calls.alpha(), …
Run Code Online (Sandbox Code Playgroud)

python python-mock python-unittest

14
推荐指数
3
解决办法
2080
查看次数