web-dev-qa-db-ja.com

Pythonでの単体テストのグローバルパラメータを適切に処理する方法

私たちは、多くのアルゴリズムを実装しています。これらのアルゴリズムには、一般に多くの共有された、既知の、セキュリティ関連のパラメーターがあります。

現在、すべてのパラメータと2つの定義済みグローバルオブジェクトを保持するクラスを使用しています。

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に渡されると、2つの異なるオブジェクトが使用されます。

ユニットテストの傾向が少ないが柔軟性を提供するより良い方法はありますか?これは本当にベストプラクティスですか?

11
netik

構成ファイルtest_config.pyおよびproduction_config.pyを作成します。環境変数またはコマンドライン引数を使用して、それらの1つを選択します。それをインポートし(または.jsonではなく.txt/.pyを選択した場合は読み取り/解析)、モジュール内のグローバルオブジェクトを通じてプログラム全体で結果を利用できるようにします。どこにでもインポートできます。

これは、グローバルスコープからPythonを起動するシェルまで、さらに一歩進んだことを除いて、すでに行っていることと非常に似ています。利点は、本番環境とテスト構成を誤って混同するリスクがなくなることです。環境変数/コマンドラインが1つしかないため、同じpythonセッションで両方のファイルを読み取ることはできません。

1
max

できることはたくさんあります。

  • グローバルの使用をやめる
  • デフォルトの使用をやめる
  • デフォルトの使用を許可しないプライベートヘルパーメソッドを通じて常にテストする

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

確かに、これらのオプションはどれも手間がかかりますが、これが問題ではないかどうか尋ねる必要はありません。

0
candied_orange

常に値のコレクションをグローバルコンテキストとそれらのパラメーターの処理から分離することができます。

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
0
user166988