如何正确处理用于python中的单元测试的全局参数?


11

我们正在实现许多算法,这些算法通常具有许多共享的,众所周知的和与安全性相关的参数。

当前,我们仅使用一个包含所有参数和两个预定义全局对象的类:

class PublicParams(object):
    p = q = 0

    def __init__(self, p, q):
        self.p = p
        self.q = q

# used for tests
publicParams_test = PublicParams(15,7)               

# Some 2048 bit numbers for example
publicParams_secure = PublicParams(128378947298374928374,128378947298374928374)  

然后,算法将一个PublicParams对象作为默认为生产性的参数publicParams_secure

def AlgoOne(n, publicParams = publicParams_secure):
    # do stuff with publicParams.p
    # ...
    AlgoTwo(x, publicParams)

def AlgoTwo(x, publicParams= publicParams_secure):
    # do stuff with publicParams.q

这样,我们仍然可以注入不同的公共参数来简化单元测试:

class AlgoOneTest(unittest.TestCase):
    def test(self):
        # compare with manually computed result
        self.assertTrue(AlgoOne(1, publicParams_test) == 10) 

我不喜欢这种方法:

  • 赋予publicParams默认值使其在调用某些算法时是可选的。但是,很容易忘记AlgoTwo从内部调用时传递它AlgoOne,如果将测试对象传递给,则会导致使用两个不同的对象。AlgoOne

有没有一种更好的方法,它不那么容易使用,但仍然为单元测试提供了灵活性?这真的是最佳做法吗?

Answers:


1

创建配置文件test_config.pyproduction_config.py。使用环境变量或命令行参数选择其中之一。导入它(如果选择.json/ .txt而不是,则导入它(或读取/分析.py),并通过模块中的全局对象使结果可用于整个程序,该模块可以导入到任何地方。

这与您已经在做的事情非常相似,不同之处在于,它从全局范围到调用python的shell都更进了一步。这样做的好处是,不再存在意外地将生产和测试配置混淆的风险:因为只有一个环境变量/命令行,所以您无法在同一python会话中读取两个文件。


0

您可以做很多事情。

  • 停止使用全局变量
  • 停止使用默认值
  • 始终通过不允许使用默认值的私有帮助器方法进行测试

    def _AlgoOne(n, publicParams):
        return AlgoOne(n, publicParams)

当然,这些选项中的任何一个都需要大量工作,但是您不会问这对您来说不是问题。


0

人们总是可以将值的收集与全局上下文以及这些参数的处理分开。

def do_the_thing():
    """Provides the public (rather untestable) context.
    _do_the_thing(global1, global2, publicParams)"""

def _do_the_thing(blah, blah, blah):
    "Actually does the thing"
    pass
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.