2015-01-27 6 views
3

Я пытался бороться с несколькими ошибками при попытке написать некоторые модульные тесты Python для приложения Google App Engine, которое состоит из нескольких модулей.InvalidModuleError() при использовании Testbed для тестирования модулей Google App Engine

Я был в соответствии с указаниями, представленными на https://cloud.google.com/appengine/docs/python/tools/localunittesting

Для начала я получаю следующее:

ERROR:root:AssertionError('No api proxy found for service "modules"’,)

Однако я решил, что это потому, что я не инициализирован Testbed правильно и нужен отдельный звоните в:

self.testbed.init_modules_stub() 

Это, несмотря на уже называют:

self.testbed.init_all_stubs() 

Это кажется странным для меня, но это не главная проблема ... Теперь я прошел мимо этой ошибки, и вместо этого я получаю:

ERROR:root:InvalidModuleError()

код довольно прост. Вот соответствующие части корпуса испытания:

def setUp(self): 
    self.testbed = testbed.Testbed() 
    self.testbed.activate() 
    self.testbed.init_all_stubs 
    self.testbed.init_modules_stub() 

def test_should_submit_a_task(self): 
    post_content = '{ "bucket": "/test/", "filename", "test", "operation": "read" }' 
    request = webapp2.Request.blank('/path/to/module/method', POST=post_content) 
    response = request.get_response(main.application) 

    self.assertEquals(response.status_int, 200) 

Строка из кода тестируемой где генерируется ошибка следующим образом:

 host = get_hostname(queue) 

Я могу видеть, что «очередь» правильно инициализирован с именем модуля.

Комментарии в google_appengine из get_hostname() состояние:

"Поднимает: InvalidModuleError если данный moduleversion является недействительным."

По какой-то причине моя moduleversion недействительна.

Итак, необходимо ли вручную передать версию модуля get_hostname(), когда код находится под тестированием?

Или мне не удалось инициализировать тестовый стенд каким-либо образом, чтобы убедиться, что версия модуля действительна?

EDIT: Я продолжал работать над этим и проследил через код Google App Engine, к классу _LocalFakeDispatcher в request_info.py. Этот класс устанавливает некоторые значения по умолчанию для использования при тестировании. Проблема в том, что мой тест прибывает сюда, пытаясь определить, является ли модуль действительным, но он не соответствует одному из значений по умолчанию в этом заглушке, и поэтому в конечном итоге возвращается ошибка Invalid Module.

Есть ли способ переопределить значения по умолчанию в этом диспетчере, чтобы настроить его на наличие ожидаемых имен модулей и версий?

См:

class _LocalFakeDispatcher(Dispatcher): 
    """A fake Dispatcher implementation usable by tests.""" 

    def __init__(self, 
       module_names=None, 
       module_name_to_versions=None, 
       module_name_to_default_versions=None, 
       module_name_to_version_to_hostname=None): 
    super(_LocalFakeDispatcher, self).__init__() 
    if module_names is None: 
     module_names = ['default'] 
    if module_name_to_versions is None: 
     module_name_to_versions = {'default': ['1']} 
etc. ... 

Большое спасибо

R.

$ gcloud --version Google Cloud SDK 0.9.44

приложение 2015.01.15 приложение-двигатель-гоу-Darwin-x86_64 1.9.17 приложение-двигатель-Java 1.9.17 приложение-engine- управляемый VMS 2014.11.03 приложение-двигатель-питон 1.9.17 т.д.

ответ

4

проблема с необходимости вызвать init_modules_stub связана с каким выпуском SDK (и, таким образом testbed/__init__.py) у вас есть; это было добавлено в init_all_stubs в текущей версии (не уверен, когда именно), поэтому обновление должно позволить вам удалить необходимость явного вызова. Но, как вы говорите, не главная проблема.

Но к более существенной проблеме - моими огнями вы ничего не сделали, потому что ни одна документация не говорит о том, что вы должны что-то делать, в частности, для инициализации заглушки модулей.

К счастью, обход не тоже ужасный. В частности, вы могли бы, в начале вашего модульного тестирования кода инициализации:

from google.appengine.api import request_info 

# edit all_versions per modules & versions thereof needing tests 
all_versions = {'default':[1], 'andsome':[2], 'others':[1]} 
def_versions = {m:all_versions[m][0] for m in all_versions} 
m2h = {m:{def_versions[m]:'localhost:8080'} for m in def_versions} 

request_info._local_dispatcher = request_info._LocalFakeDispatcher(
    module_names = list(all_versions), 
    module_name_to_versions = all_versions, 
    module_name_to_default_versions = def_versions, 
    module_name_to_version_to_hostname = m2h) 

при условии, конечно, что эти имена модулей и версии, которые вы хотите!

Да, он должен определенно легче (стендовый или некоторые модуль должен выставить функцию, делая это - в идеале, анализируя соответствующие yaml файлы, но, по крайней мере, с явными аргументами) и, что очень важно, он должен быть хорошо документирован.

Будучи первым автором предшественника первой версии тестового стенда пять лет назад, я лично прошу прощения за не следит за ней (извините - я был занят очень различными рабочими местами в то же время - но , будучи фанатиком об модульном тестировании, я должен был использовать около 20% времени на этом).

Просьба открыть подробный запрос об экспонировании и документировать его, и благодарит как за ваше терпение, так и за отличную «детективную работу», определяющую суть проблемы!

+0

Благодарим вас за подробный ответ и комментарии. Ваше предложение работало очень хорошо; именно то, что я искал. Я потрачу время, чтобы сделать запрос функции, как вы предлагаете. Еще раз спасибо. –

+0

@rdc вы можете связать запрос функции здесь, а также для будущего поиска? –

+0

@Trii Я открыл запрос функции: https://code.google.com/p/googleappengine/issues/detail?id=11780 –

Смежные вопросы