Pythonでユニットテストのグローバルパラメータを適切に処理する方法は?


11

私たちは多くのアルゴリズムを実装していますが、それらは通常、多くの共有され、公に知られており、セキュリティ関連のパラメーターを持っています。

現在、すべてのパラメーターと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ます。テストオブジェクトが渡された場合、2つの異なるオブジェクトが使用されます。AlgoOne

発生しにくいが、単体テストに柔軟性を提供するより良い方法はありますか?これは本当にベストプラクティスですか?

回答:


1

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

これは、グローバルスコープからpythonを起動するシェルまでさらに一歩進んだことを除いて、既に実行しているものと非常に似ています。利点は、本番環境とテスト構成を誤って混同するリスクがなくなることです。環境変数/コマンドラインが1つしかないため、同じ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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.