Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 模仿一个类';s结构_Python_Unit Testing_Mocking - Fatal编程技术网

Python 模仿一个类';s结构

Python 模仿一个类';s结构,python,unit-testing,mocking,Python,Unit Testing,Mocking,我刚刚开始使用Python库来帮助编写更简洁和独立的单元测试。我的情况是,我有一个类,它从一个非常复杂的格式读取数据,我想在这个类上测试一个方法,它以干净的方式呈现数据 格式 上面的代码是我所拥有的代码的简化。实际上,\u parse是一种相当重要的方法,我在功能级别对其进行了测试 但是,我希望能够在单元测试级别上测试x_-coords。如果我通过给这个类一个路径来实例化它,它将违反 在以下情况下,测试不是单元测试: 它涉及到文件系统 因此,我希望能够为保存数据的\uuuu init\uuu

我刚刚开始使用Python库来帮助编写更简洁和独立的单元测试。我的情况是,我有一个类,它从一个非常复杂的格式读取数据,我想在这个类上测试一个方法,它以干净的方式呈现数据 格式

上面的代码是我所拥有的代码的简化。实际上,
\u parse
是一种相当重要的方法,我在功能级别对其进行了测试

但是,我希望能够在单元测试级别上测试
x_-coords
。如果我通过给这个类一个路径来实例化它,它将违反

在以下情况下,测试不是单元测试:

  • 它涉及到文件系统
因此,我希望能够为
保存数据
\uuuu init\uuuuu
方法打补丁,然后只需填写
x\u coords
所需的
self.data
部分。比如:

from mock import patch
with patch('__main__.holds_data.__init__') as init_mock:
    init_mock.return_value = None
    instance = holds_data()
    instance.data = {'points':[(1,1),(2,2),(3,4)]}
    assert(instance.x_coords == [1,2,3])
上面的代码可以工作,但感觉它是以一种相当迂回的方式进行测试的。有没有更惯用的方法修补构造函数,或者这是正确的方法?另外,在我的类或测试中,是否有一些代码的味道我遗漏了

Edit:我的问题是,在初始化过程中,我的类会进行大量的数据处理,以组织将通过
x\u coords
等方法显示的数据。我想知道修补所有这些步骤的最简单方法是什么,而不必提供完整的输入示例。我只想在我控制它使用的数据的情况下测试
x_coords
的行为

我关于这里是否有代码气味的问题归结为这个问题:


我相信,如果我将
x_坐标
重构为一个独立的函数,将
保存数据
作为一个参数,这将更容易实现。如果“更容易测试==更好的设计”成立,这将是一条出路。但是,它需要
x_coords
函数来了解更多我通常熟悉的
holds_data
的内部信息。我应该在哪里进行交易?更干净的代码还是更干净的测试?

由于以下原因,您基本上遇到了这个问题:

在以下情况下,测试不是单元测试:

  • 它涉及到文件系统
如果希望遵循此规则,则应修改
\u parse
方法。特别是,它不应该将文件作为输入。
\u parse
的任务是解析数据,但该方法并不关心数据来自何处

您可以拥有一个包含相同数据的字符串,然后将该字符串传递给
\u parse
。类似地,数据可能来自数据库或其他完全不同的地方。当
\u parse
仅将数据作为输入时,您可以以更简单的方式对该方法进行单元测试

它看起来像这样:

class HoldsData(object):
    def __init__(self, path):
        self.data = {}
        file_data = self._read_data_from_file(path)
        self.data.update(self._parse(file_data))

    def _read_data_from_file(self, path):
        # read data from file
        return data

    def _parse(self, data):
        # do parsing

干净的代码当然会导致干净的测试。最好的情况是模拟数据,提供
\u parse
输入,然后稍后测试
x\u坐标。如果那不可能,我会保持原样。如果您担心的测试用例中只有六行模拟代码,那么您就没事了。

既然您只对测试一个方法感兴趣,为什么不模拟整个
HoldsData
类并在其上固定
x_coords
方法呢

>>> mock = MagicMock(data={'points': [(0,1), (2,3), (4,5)]})
>>> mock.x_coords = HoldsData.__dict__['x_coords']
>>> mock.x_coords(mock)
[0, 2, 4]
这样,您就可以完全控制
x_坐标
输入和输出(通过副作用或返回值)

注意:在py3k中,您只需执行
mock.x_coords=HoldsData.x_coords
,因为有

这也可以在模拟对象的构造函数中完成:

MagicMock(data={'points': [(0,1), (2,3), (4,5)]}, x_coords=HoldsData.__dict__['x_coords'])

这就是我真正的课堂的运作方式。
\uuuu init\uuuu
方法将文件读入字符串列表,然后
\u parse
就可以从中工作。问题是这个方法做了很多事情,我想模拟一下
x_coords
使用的部分。我不确定我是否正确地完成了该部分。请参阅我的编辑。我的问题是,提供我的输入的完全伪造是不可行的。我只想测试单个方法
x_coords
的行为,而不是
\u parse
的行为(我对此进行了功能测试)。在这种情况下,您可以重构
\u parse
并将其拆分为单独的函数。可能吗?然后,您可以提供一部分可以解析的输入,然后您可以测试
x_coords
。我真的无法将其分解为单独的方法。我从一个文件格式中读取数据,如果您为它编写语法,它将是上下文敏感的。我基本上必须一次解析它(我有一个有限状态机可以完成这项工作)。我只是在寻找一种最方便的方法来消除我对
x_coords
的测试,我想尽可能地将它隔离开来。如果这真的是一个非常不寻常的情况(据我所知,我对嘲弄还不熟悉),我会接受我不得不忍受我的黑客,尽管我想知道为什么这不容易=)。例如,我相信,如果我将
x_坐标
重构为一个独立的函数,将
保存数据
作为一个参数,这将更容易实现。如果更容易测试==更好的设计,这将是一条出路。但是,它需要
x_coords
函数来了解更多我通常熟悉的
holds_data
的内部信息。我应该在哪里进行交易?更干净的代码还是更干净的测试?是的,这就是我想要的。谢谢。3年过去了,但可能对某些人有用:一旦你有了
mock
对象,你就可以做
保存数据。x\u坐标(mock)
,省去为事物分配方法的麻烦。
MagicMock(data={'points': [(0,1), (2,3), (4,5)]}, x_coords=HoldsData.__dict__['x_coords'])