使用 Testbed 进行单元测试时的 InvalidModuleError() Google App Engine

InvalidModuleError() when using Testbed to Unit Test Google App Engine

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

我一直在遵循 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)

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

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

”提出: InvalidModuleError 如果给定的模块版本无效。"

所以出于某种原因我的模块版本无效。

那么,在测试代码的时候,是否需要手动传递一个模块版本给get_hostname()?

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

编辑:我继续致力于此,并通过 Google App Engine 代码追踪到 class _LocalFakeDispatcherrequest_info.py 中。 class 设置了一些用于测试的默认值。问题是,我的测试到达这里试图确定模块是否有效,但它与此存根中的默认值之一不匹配,因此最终返回无效模块错误。

有什么方法可以覆盖此调度程序中的默认值,以设置它填充预期的模块名称和版本?

参见:

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 云 SDK 0.9.44

应用2015.01.15 app-engine-go-darwin-x86_64 1.9.17 应用引擎-java 1.9.17 应用程序引擎管理的虚拟机 2014.11.03 应用引擎-python 1.9.17 等等

需要调用 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)

当然假设这些是您想要的模块名称和版本!

是的,它应该 绝对 更容易(测试平台或 some 模块应该暴露一个函数来做这个——理想情况下通过解析适当的yaml 个文件,但至少有显式参数),非常重要的是,它应该被详细记录。

我是五年前 testbed 第一个版本的前身的第一作者,我个人很抱歉没有关注它(抱歉——我 当时 忙于非常同时做不同的工作!--但是,作为一个单元测试的狂热者,我应该在这上面花费大约 20% 的时间。

请打开一个关于很好地公开并记录它的功能请求,感谢您的耐心和出色的 "detective work" 识别问题的关键!