以下のペーストには、3つの別々のPythonファイルの関連スニペットが含まれています。最初は、コマンドラインから呼び出されたスクリプトで、特定の引数を指定してCIPullerをインスタンス化します。何が起こるかは、スクリプトが script.py ci
(argparseによって他の引数が呑み込まれる)のように呼び出されるということです。argparseに依存するPythonクラスをテストするには?
第2のサブクラスはPuller
というサブクラスの一部です。 3番目のサブクラスは、CIPuller
と呼ばれるPuller
のサブクラスの一部です。
正しいサブクラスが呼び出され、間違った他のargsを使用するユーザーは、指定されたサブクラスに適切なargsとスーパークラスの汎用引数を表示します。 (私はオフラインで、おそらくこのためにargparse sub-commandsを使用する必要があると考えましたが)。
これらのクラスのテストを作成しようとしていません。現在、クラスをインスタンス化するにはArgumentParser
が必要ですが、テストではコマンドラインからインスタンス化しないため、ArgumentParser
は役に立たないです。
私はテストコードにCIPuller's
コンストラクタに渡すテストハーネスでArgumentParser
を作成しようとしたが、私はそこにadd_argument
を使用している場合、argparse当然のことながら、それはCIPuller
コンストラクタでadd_argument
を呼び出すときの引数を(複製)ダブルについて文句を言います。
これらのクラスを引数でテストするには、どのような設計が適していますか?
#!/usr/bin/env python
from ci_puller import CIPuller
import argparse
import sys
# Using sys.argv[1] for the argument here, as we don't want to pass that onto
# the subclasses, which should receive a vanilla ArgumentParser
puller_type = sys.argv.pop(1)
parser = argparse.ArgumentParser(
description='Throw data into Elasticsearch.'
)
if puller_type == 'ci':
puller = CIPuller(parser, 'single')
else:
raise ValueError("First parameter must be a supported puller. Exiting.")
puller.run()
class Puller(object):
def __init__(self, parser, insert_type):
self.add_arguments(parser)
self.args = parser.parse_args()
self.insert_type = insert_type
def add_arguments(self,parser):
parser.add_argument(
"-d", "--debug",
help="print debug info to stdout",
action="store_true"
)
parser.add_argument(
"--dontsend",
help="don't actually send anything to Elasticsearch",
action="store_true"
)
parser.add_argument(
"--host",
help="override the default host that the data is sent to",
action='store',
default='kibana.munged.tld'
)
class CIPuller(Puller):
def __init__(self, parser, insert_type):
self.add_arguments(parser)
self.index_prefix = "code"
self.doc_type = "cirun"
self.build_url = ""
self.json_url = ""
self.result = []
super(CIPuller, self).__init__(parser, insert_type)
def add_arguments(self, parser):
parser.add_argument(
'--buildnumber',
help='CI build number',
action='store',
required=True
)
parser.add_argument(
'--testtype',
help='Job type per CI e.g. minitest/feature',
choices=['minitest', 'feature'],
required=True
)
parser.add_argument(
'--app',
help='App e.g. sapi/stats',
choices=['sapi', 'stats'],
required=True
)
'テスト用sys.argv'を変更する最も簡単なようです。しかし、 'sys.argv'を変更したり、デフォルトであなたのカスタム' arvg'を使うための 'ArgumentParser'をmonkeypatchするのはもっと一般的な習慣です。 – Amir
'' Puller'に、 'parse_args'に渡されるオプションの' argv'パラメータを取る別々の 'parse'メソッドを与えます。その後、通常の実行モードで、またはテスト値で使用できます。 'test_argparse'は両方のアプローチをテストします。 – hpaulj
これは本当に役に立ちました。私が言及したリンクのいくつかを超えていたとしても、sys.argvを設定するという基本的な考えは私には起こりませんでした。時々、木の森は見えません。 :) – topper