使用Testbed到单元测试Google App Engine时出现InvalidModuleError()

时间:2015-01-27 09:00:13

标签: python google-app-engine

在尝试为包含许多模块的Google App Engine应用程序编写一些Python单元测试时,我一直在努力解决一些错误。

我一直在遵循https://cloud.google.com/appengine/docs/python/tools/localunittesting

上给出的指导

首先,我得到以下内容:

  

错误:root:AssertionError('没有为服务找到api代理"模块"',)

但是我确定这是因为我没有正确初始化Testbed并需要单独调用:

self.testbed.init_modules_stub()

尽管已经在呼唤:

self.testbed.init_all_stubs()

这对我来说似乎很奇怪,但不是主要问题......现在我已经超越了这个错误,而是我得到了:

  

错误:根: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)

我可以看到'排队'已使用模块名称正确初始化。

来自get_hostname()状态的google_appengine中的评论:

"引发:     如果给定的moduleversion无效,则为InvalidModuleError。"

因此,由于某种原因,我的模块转换无效。

那么,当代码处于测试阶段时,是否有必要手动将模块版本传递给get_hostname()?

或者我是否未能以某种方式初始化测试平台以确保模块的版本有效?

编辑:我已继续处理此问题,并已通过Google App Engine代码跟踪_LocalFakeDispatcher中的班级request_info.py。该类设置了一些用于测试的默认值。问题是,我的测试到达这里试图确定模块是否有效,但它不匹配此存根中的一个默认值,因此最终返回无效模块错误。

我是否可以通过某种方式覆盖此调度程序中的默认值以将其设置为填充预期的模块名称和版本?

见:

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

app 2015.01.15 app-engine-go-darwin-x86_64 1.9.17 app-engine-java 1.9.17 app-engine-managed-vms 2014.11.03 app-engine-python 1.9.17 等

1 个答案:

答案 0 :(得分: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文件,但是至少有明确的论点),非常重要的是,它应该有详细记录。

五年前,作为testbed第一个版本的前身的第一作者,我个人为没有留意它而道歉(对不起 - 在此期间我 忙于完成非常不同的工作! - 但是,作为一个关于单元测试的狂热分子,我应该花费大约20%的时间用于此。)

请打开一个功能请求,详细说明并记录下来,并感谢,以便您的耐心和优秀的“侦探工作”确定问题的症结所在!