Python学习:如何使用pytest-mock

Posted chaos-god

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习:如何使用pytest-mock相关的知识,希望对你有一定的参考价值。

1.问题

使用pytest做python代码的测试是很容易的,不过被测试代码对网络、数据库等远程服务有依赖,这种情况该如何快速方便的进行测试。

2.方案

python的unitest包是支持单元测试的,有mock可以用。并且pytest-mock进行高层次的封装,用起来更加方便。安装包:

pip3 install pytest-mock

2.1.小试牛刀

直接采用类似官方的例子,我们代码中要使用os.getcwd获取当前工作目录。只是我们的代码是在windows系统上,实际代码需要linux下工作,测试代码如下:

import os

def test_os_getcwd(mocker):
    mocker.patch("os.getcwd", return_value="/root")
    ret = os.getcwd()
    assert ret == '/root'

这段代码可以测试通过。通过使用mocker.patch可以对函数进行mock。这样就本地开发环境进行测试,这也是单元测试魅力所在。

看上去很简单对吧,实际这样例子毫无意义,实际测试根本不会这么用。网上的例子到处是这样的代码,简直是误人子弟,纯粹是浪费时间。因此才想起写一份有用的例子代码出来。

2.2.测试自定义模块

假设我们写了一个模块,有个函数get_pipconf_filename的路径。模块chaos的代码如下:

import os

def get_pipconf_filename():
    upath = os.path.expanduser('~')
    return upath + '/.pip/pip.conf'

我们写下测试代码:

import chaos

def test_get_pipconf_filename(mocker):
    mocker.patch('os.path.expanduser',return_value='/home/chaos')
    ret = chaos.get_pipconf_filename()
    assert ret == 'home/chaos/.pip/pip.conf'

问题来了,你觉得上述测试代码可以通过吗?答案是肯定的,测试通过。

不过,如果chaos模块中是另外一种写法,上述测试还能通过吗?

from os.path import expanduser

def get_pipconf_filename():
    upath = expanduser('~')
    return upath + '/.pip/pip.conf'

实际测试是失败,无法进行mock,原因就是patch打错对象了,实际上没有成功。测试代码该如何写?代码如下:

import chaos

def test_get_pipconf_filename(mocker):
    mocker.patch('chaos.expanduser', return_value='/home/chaos')
    ret = chaos.get_pipconf_filename()
    assert ret == '/home/chaos/.pip/pip.conf'

这个时候应该对chaos.expanduser进行mock才行,因为chaos模块中对os.path.expanduser进行了重新赋值。

截止到这里,给模块函数进行mock几种场景,基本能覆盖实际的测试。但问题又来了,如何根据函数调用传递的参数不同而返回不同的值呢?代码如下:

import chaos

def mock_func(s):
    if s == '~' :
        return 'home/chaos'
    else:
        return '/usr/lib'

def test_get_pipconf_filename(mocker):
    mocker.patch('chaos.expanduser', side_effect=mock_func)
    ret = chaos.get_pipconf_filename('^_^')
    assert ret == '/usr/lib'

上述代码使用了side_effect参数重定向到一个自定义的测试函数上。这个时候就可以根据实际的参数进行返回不同的值了。

3.讨论

实际上,还有一些问题没有解决?比如如何对对象进行patch,如何在初始化的时候把所有的patch都打上,不用在每个测试用例进行patch等等。留在下一篇再讲。

Python学习:如何使用pytest-mock(2)

以上是关于Python学习:如何使用pytest-mock的主要内容,如果未能解决你的问题,请参考以下文章

Python学习:如何使用pytest-mock

Python学习:如何使用pytest-mock

Python学习:如何试用pytest-mock

Python学习:如何试用pytest-mock

Python学习:如何试用pytest-mock

Python学习:如何试用pytest-mock