小编典典

如何对Google Cloud Endpoints进行单元测试

python

我需要一些帮助来设置Google Cloud
Endpoints的单元测试。使用WebTest时,所有请求都将回答AppError:错误的响应:找不到404。我不太确定端点是否与WebTest兼容。

这是生成应用程序的方式:

application = endpoints.api_server([TestEndpoint], restricted=False)

然后我以这种方式使用WebTest:

client = webtest.TestApp(application)
client.post('/_ah/api/test/v1/test', params)

使用curl进行测试可以正常工作。

我应该为不同的端点编写测试吗?GAE Endpoints团队的建议是什么?


阅读 273

收藏
2021-01-20

共1个答案

小编典典

经过大量实验并查看了SDK代码之后,我想出了两种方法来测试python中的端点:

1.使用webtest + testbed测试SPI端

使用webtest时,您处在正确的轨道上,但只需要确保正确转换对SPI端点的请求即可。

Cloud Endpoints
API前端和EndpointsDispatcherindev_appserver将调用转换/_ah/api/*为的相应“后端”调用/_ah/spi/*。转换似乎是:

  • 所有调用都是application/jsonHTTP POST(即使REST端点是其他调用)。
  • 请求参数(路径,查询和JSON正文)都合并在一起成为一条JSON正文消息。
  • “后端”端点在URL中使用实际的python类和方法名称,例如POST /_ah/spi/TestEndpoint.insert_messageTestEndpoint.insert_message()在您的代码中调用。
  • JSON响应仅在重新格式化后才返回给原始客户端。

这意味着您可以使用以下设置来测试端点:

from google.appengine.ext import testbed
import webtest
# ...
def setUp(self):
    tb = testbed.Testbed()
    tb.setup_env(current_version_id='testbed.version') #needed because endpoints expects a . in this value
    tb.activate()
    tb.init_all_stubs()
    self.testbed = tb

def tearDown(self):
    self.testbed.deactivate()

def test_endpoint_insert(self):
    app = endpoints.api_server([TestEndpoint], restricted=False)
    testapp = webtest.TestApp(app)
    msg = {...} # a dict representing the message object expected by insert
                # To be serialised to JSON by webtest
    resp = testapp.post_json('/_ah/spi/TestEndpoint.insert', msg)

    self.assertEqual(resp.json, {'expected': 'json response msg as dict'})

这里的事情是,您可以在调用端点之前轻松地在数据存储或其他GAE服务中设置适当的固定装置,从而可以更充分地断言该调用的预期副作用。

2.启动开发服务器以进行全面集成测试

您可以使用以下类似方法在同一python环境中启动开发服务器:

import sys
import os
import dev_appserver
sys.path[1:1] = dev_appserver._DEVAPPSERVER2_PATHS

from google.appengine.tools.devappserver2 import devappserver2
from google.appengine.tools.devappserver2 import python_runtime
# ...
def setUp(self):
    APP_CONFIGS = ['/path/to/app.yaml'] 
    python_runtime._RUNTIME_ARGS = [
        sys.executable,
        os.path.join(os.path.dirname(dev_appserver.__file__),
                     '_python_runtime.py')
    ]
    options = devappserver2.PARSER.parse_args([
        '--admin_port', '0',
        '--port', '8123', 
        '--datastore_path', ':memory:',
        '--logs_path', ':memory:',
        '--skip_sdk_update_check',
        '--',
    ] + APP_CONFIGS)
    server = devappserver2.DevelopmentServer()
    server.start(options)
    self.server = server

def tearDown(self):
    self.server.stop()

现在,您需要向localhost:8123发出 实际的 HTTP请求,以针对API运行测试,但再次可以与GAE
API交互以设置固定装置等。这显然很慢,因为您要为每个应用创建和销毁新的开发服务器测试运行。

在这一点上,我使用Google API Python客户端来使用API​​,而不是自己构建HTTP请求:

import apiclient.discovery
# ...
def test_something(self):
    apiurl = 'http://%s/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest' \
                    % self.server.module_to_address('default')
    service = apiclient.discovery.build('testendpoint', 'v1', apiurl)

    res = service.testresource().insert({... message ... }).execute()
    self.assertEquals(res, { ... expected reponse as dict ... })

这是对使用CURL进行测试的一项改进,因为它使您可以直接访问GAE
API,以轻松设置固定装置并检查内部状态。我怀疑还有一种更好的集成测试方法,可以通过将实现端点调度机制的dev服务器中的最小组件拼接在一起来绕过HTTP,但这需要比我现在更多的研究时间。

2021-01-20