Python 如何对与块设备交互的程序进行单元测试

Python 如何对与块设备交互的程序进行单元测试,python,unit-testing,Python,Unit Testing,我有一个程序,可以在linux上与块设备(/dev/sda等)进行交互和更改。我使用各种外部命令(主要是来自fdisk和GNU fdisk包的命令)来控制设备。我已经创建了一个类,作为块设备的大多数基本操作的接口(用于信息,如:它的大小?安装在哪里?等等) 下面是一种查询分区大小的方法: def get_drive_size(device): """Returns the maximum size of the drive, in sectors. :device the de

我有一个程序,可以在linux上与块设备(/dev/sda等)进行交互和更改。我使用各种外部命令(主要是来自fdisk和GNU fdisk包的命令)来控制设备。我已经创建了一个类,作为块设备的大多数基本操作的接口(用于信息,如:它的大小?安装在哪里?等等)

下面是一种查询分区大小的方法:

def get_drive_size(device):
    """Returns the maximum size of the drive, in sectors.

    :device the device identifier (/dev/sda and such)"""

    query_proc = subprocess.Popen(["blockdev", "--getsz", device], stdout=subprocess.PIPE) 
    #blockdev returns the number of 512B blocks in a drive
    output, error = query_proc.communicate()
    exit_code = query_proc.returncode
    if exit_code != 0:
        raise Exception("Non-zero exit code", str(error, "utf-8")) #I have custom exceptions, this is slight pseudo-code

    return int(output) #should always be valid
所以这个方法接受一个块设备路径,并返回一个整数。测试将以root用户身份运行,因为整个程序最终都必须以root用户身份运行

我是否应该尝试测试这些方法之类的代码?如果是,怎么做?我可以尝试为每个测试创建和挂载图像文件,但这似乎需要很大的开销,而且本身可能很容易出错。它需要块设备,因此我无法直接操作文件系统中的图像文件

正如一些答案所暗示的那样,我可以试着嘲笑,但这感觉不够。如果我模拟Popen对象,而不是输出,我似乎开始测试方法的实现。在这种情况下,这是正确的单元测试方法评估吗


我在这个项目中使用python3,我还没有选择单元测试框架。在没有其他原因的情况下,我可能只使用Python中包含的默认unittest框架。

您应该研究模拟模块(我认为它现在是Python 3中unittest模块的一部分)

它使您能够在不依赖任何外部资源的情况下运行测试,同时控制模拟如何与代码交互

我将从中的文档开始

下面是一个例子:

import unittest2 as unittest
import mock

class GetDriveSizeTestSuite(unittest.TestCase):

  @mock.patch('path/to/original/file.subprocess.Popen')
  def test_a_scenario_with_mock_subprocess(self, mock_popen):
    mock_popen.return_value.communicate.return_value = ('Expected_value', '')
    mock_popen.return_value.returncode = '0'
    self.assertEqual('expected_value', get_drive_size('some device'))

我在方法中使用了非python命令。如何模拟这些系统命令?您可以模拟subprocess.Popen,然后告诉它返回一个适合您希望测试的场景的值。mock的要点是,除了测试的代码之外,您不需要与其他任何东西进行交互。您可以让mock返回您想要的任何输出,甚至在调用时引发异常。我想这可以工作,尽管Popen对象没有传递到方法中。我将如何插入Popen mock?我不想让它成为一个参数,这会破坏方法的用途。在unittest中,对subprocess.Popen应用一个补丁,然后为它设置一个返回值,以及它的communicate方法和返回代码属性的返回值。我将添加一个简单的示例