对写入加密钱包文件的函数或方法进行单元测试的正确方法是什么?

2024-05-23 22:28:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我的代码看起来像这样:

def write_wallet_file_entry(name, value, wallet_file, wallet_password):
    some_code
    some_more_code_to_write_to_the_wallet
    ...

我正在使用Python(2.6)和unittest模块对这段代码进行单元测试。如果钱包文件不存在,代码将创建钱包文件,然后向其中写入一组键值对。你知道吗

一旦我给钱包写了信,我就无法进行文本分析来确认写的东西是干净的。你知道吗

澄清:陈述“不太明显:我不能使用”单元测试.mock或“模拟”模块,使问题更容易解决。我的环境停留在python2.6上,没有“virtualenv”,没有“mock”模块,不允许在系统上安装外部模块。你知道吗

任何建议都会很有帮助。你知道吗


Tags: 模块文件to代码namedefcodesome
1条回答
网友
1楼 · 发布于 2024-05-23 22:28:51

一些假设

这些假设不会改变我回答的要点,但它们意味着我们可以清楚地了解术语,因为您还没有发布Minimum, Complete and Verifiable Example。你知道吗

  • “钱包文件”实际上是一个类似文件的对象。它遵循与文件流对象相同的语义,Python的open()是该对象的直接包装器。

  • 只有wallet_filewallet_password是特定于钱包文件的。namevalue是要传递到文件的键值对。

问题

你的问题在于你是否能够测试你的书写是“干净的”。你知道吗

但是,您不需要检查文件是否正确写入或是否已创建- 您只需要以这种方式测试Python的file对象,这种测试已经非常可靠了。你知道吗

单元测试的重点是测试您编写的代码,而不是外部服务。应该始终假定外部服务在单元测试中完成了它的工作—您只在集成测试中测试外部服务。你知道吗

您需要的是一种方法来确保您发送要写入的值被正确地接收并且没有被篡改,并且您创建文件的请求以您想要的格式被接收。测试邮件,而不是收件人。你知道吗

一种方法

一种技术是将您的输入抽象为一个类,并将其子类化为具有伪方法。然后,您可以将子类用作美化的mock,无论出于何种目的。你知道吗

换言之,改变

def write_wallet_file_entry(name, value, wallet_file, wallet_password):
    ...

class Wallet(object):

    def __init__(self, wallet_file, wallet_password):
        self.file = wallet_file
        self.password = wallet_password

    def exists(self):            
        # code to check if file exists in filesystem

    def write(self, name, value):
        # code to write name, value

def write_wallet_file_entry(name, value, WalletObject):
    assert isinstance(WalletObject, Wallet), "Only Wallets allowed" 
    if WalletObject.exists():
        WalletObject.write(name, value)

要进行测试,现在可以创建MockWallet

class MockWallet(Wallet):

    def __init__(self, wallet_file, wallet_password):
        super(MockWallet, self).__init__(wallet, wallet_password)
        self.didCheckExists = False
        self.didAttemptWrite = False
        self.didReceiveCorrectly = False

    def exists(self):
        super(MockWallet, self).exists()
        self.didCheckExists = True

    def write(self, name, value):
        # ... some code to validate correct arguments were pass
        self.didReceiveCorrectly = True
        if super(MockWallet, self).write(name, value):
            self.didAttemptWrite = True

现在您可以在生产环境中使用相同的函数(只需传递一个Wallet!)在测试中(只需传递MockWallet并检查该对象的属性!)地址:

import unittest
from ... import MockWallet, write_wallet_file_entry

class Test(unittest.TestCase):

    def testWriteFlow(self):
        mock = MockWallet()
        name, value = 'random', 'more random'
        write_wallet_file_entry(name, value, mock)

        self.assertTrue(mock.didCheckExists)
        self.assertTrue(mock.didAttemptWrite)
        self.assertTrue(mock.didReceiveCorrectly)

瞧!现在,您已经有了一个经过测试的写流,它带有一个简单的临时模拟,只使用dependency injection而不是任意函数参数。你知道吗

相关问题 更多 >