Вложенная паста содержит соответствующие фрагменты из трех отдельных файлов Python. Первый - это сценарий, который вызывается из командной строки, который передает CIPuller определенные аргументы. Что происходит, так это то, что скрипт вызывается с чем-то вроде: script.py ci
(другие аргументы проглотили argparse).Как проверить классы Python, которые зависят от argparse?
Второй является частью подкласса Puller
. Третий является частью подкласса Puller
под названием CIPuller
.
Это прекрасно работает, поскольку вызывается правильный подкласс, и любой пользователь, использующий неправильные другие аргументы, получает возможность видеть правильные аргументы для данного подкласса, а также общие аргументы суперкласса. (Хотя мне сообщили в автономном режиме, что, возможно, я должен использовать для этого argparse sub-commands.)
Я застреваю, пытаясь написать тесты для этих классов. В настоящее время мне нужен ArgumentParser
для создания экземпляров классов, но при тестировании я не создаю объекты из командной строки, поэтому мой ArgumentParser
бесполезен.
Я попытался создание ArgumentParser
в тестовом жгуте, чтобы перейти к CIPuller's
конструктору в тестовом коде, но если я использую 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' или monkeypatch' ArgumentParser', чтобы использовать ваш пользовательский 'arvg' по умолчанию? – Amir
Дайте 'Puller' отдельный метод' parse', который принимает необязательный параметр 'argv', который передается' parse_args'. Затем вы можете использовать его в обычном режиме или с тестовыми значениями. 'test_argparse' проверяет оба подхода. – hpaulj
Это было действительно полезно, хотя я уже упоминал некоторые ссылки, основная идея установки sys.argv мне не пришла в голову. Иногда мы не видим леса для деревьев. :) – topper