Python 2.7 已达到支持终止期限,并将于 2026 年 1 月 31 日
弃用。弃用后,您将无法部署 Python 2.7 应用,即使您的组织之前曾使用组织政策重新启用旧版运行时的部署也是如此。现有的 Python 2.7 应用在
弃用日期之后将继续运行并接收流量。我们建议您
迁移到最新支持的 Python 版本。
针对 Python 2 的处理程序测试
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
针对 Python 的本地单元测试一文介绍了如何为您的应用运行单元测试。虽然单元测试非常适合分别测试代码的各个单元,但应用的运行离不开这些代码单元的集成 - 因此集成测试同样很重要。
对于 App Engine 应用,请求处理程序是关键的集成点。当 WSGI 应用将请求路由到正确的处理程序时,处理程序本身会处理请求数据并生成响应(详细了解请求处理程序)。请求处理程序是普通的 Python 对象(就像任何其他函数或类一样),这使得它们易于在自动化测试中使用。但是,由于 WSGI 应用会像 shell 一样封装这些处理程序,因此我们将在测试中使用类似的 shell。
WebTest
对于我们的测试,我们将使用 WebTest 框架。WebTest 是一个库,它为您提供了一个简单的界面来测试基于 WSGI 的应用,从而测试请求处理程序。为此,它会将 WSGI 应用封装在一个随后可用于测试的特殊测试应用中。借助 WebTest,您可以在没有完整 App Engine 环境的情况下与处理程序互动;您可以轻松发出请求并修改请求环境。响应也有一个便于测试的界面。您并不是必须使用 WebTest,但它确实可以让测试容易很多。
在开始之前,请在本地机器上或打算运行处理程序测试的任何位置安装 WebTest。http://webtest.pythonpaste.org/#installation 提供了说明
测试简单的“Hello World”处理程序
我们首先测试一个简单的“Hello World!”处理程序,该处理程序使用纯文本回复来响应用户请求。处理程序的响应是“Hello World!”,内容类型为“text/plain”:
import webapp2
import webtest
class HelloWorldHandler(webapp2.RequestHandler):
def get(self):
# Create the handler's response "Hello World!" in plain text.
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello World!')
接下来,创建测试用例并初始化使用您的处理程序的测试应用:
...
class AppTest(unittest.TestCase):
def setUp(self):
# Create a WSGI application.
app = webapp2.WSGIApplication([('/', HelloWorldHandler)])
# Wrap the app with WebTest’s TestApp.
self.testapp = webtest.TestApp(app)
# Test the handler.
def testHelloWorldHandler(self):
response = self.testapp.get('/')
self.assertEqual(response.status_int, 200)
self.assertEqual(response.normal_body, 'Hello World!')
self.assertEqual(response.content_type, 'text/plain')
如您所见,WebTest 可让您通过简单的 get() 调用来发出 GET 请求(其他请求方法具有类似的方法)。返回值是一个响应对象,您可以使用该对象来测试状态代码、正文、内容类型等等。请查看 WebTest 首页,以了解您可以执行的所有操作的详细说明。
创建使用 App Engine 服务的处理程序测试
下面,我们来看看如何测试使用 App Engine 服务的处理程序。这意味着我们现在必须处理可能会影响我们测试的两个组件:处理程序和我们正在使用的服务。如针对 Python 的本地单元测试一文中所述,在测试中处理服务的最佳方法是使用 testbed。
以下示例使用 Memcache,但原则上对于其他服务(如 Datastore 或任务队列)也是如此。
我们测试的处理程序会缓存给定的键和值。请注意,我们从求参数中解析这两个值。
from google.appengine.api import memcache
from google.appengine.ext import testbed
import webapp2
import webtest
class CacheHandler(webapp2.RequestHandler):
def post(self):
key = self.request.get('key')
value = self.request.get('value')
memcache.set(key, value)
和以前一样,首先在测试中创建一个应用并使用 WebTest 封装该应用。另外,还要激活 Testbed 实例并注意在测试后停用该实例。
...
class AppTest(unittest.TestCase):
def setUp(self):
app = webapp2.WSGIApplication([('/cache/', CacheHandler)])
self.testapp = webtest.TestApp(app)
self.testbed = testbed.Testbed()
self.testbed.activate()
def tearDown(self):
self.testbed.deactivate()
def testCacheHandler(self):
# First define a key and value to be cached.
key = 'answer'
value = '42'
self.testbed.init_memcache_stub()
params = {'key': key, 'value': value}
# Then pass those values to the handler.
response = self.testapp.post('/cache/', params)
# Finally verify that the passed-in values are actually stored in Memcache.
self.assertEqual(value, memcache.get(key))
设置测试框架
如果您愿意,可以设置测试框架。针对使用 WebTest 的处理程序的测试,可以像针对 App Engine 的单元测试一样执行。唯一的区别是,您需要确保已安装 WebTest。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-09-04。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-09-04。"],[[["\u003cp\u003eThis guide focuses on integration testing for App Engine applications, particularly emphasizing the testing of request handlers, which are crucial integration points.\u003c/p\u003e\n"],["\u003cp\u003eThe WebTest framework is introduced as a tool to simplify testing WSGI-based applications and request handlers by wrapping them in a test app, allowing easy interaction and environment modification.\u003c/p\u003e\n"],["\u003cp\u003eThe article provides examples of testing a simple "Hello World" handler using WebTest, demonstrating how to make requests and assert on the response's status code, body, and content type.\u003c/p\u003e\n"],["\u003cp\u003eTesting handlers that use App Engine services is covered, highlighting the use of testbed to isolate and manage interactions with services like Memcache, ensuring accurate and controlled testing environments.\u003c/p\u003e\n"],["\u003cp\u003eWebTest allows you to make requests using the get() call, and the return value of this is a response object which you can use to test the status code, body, and content type, among other things.\u003c/p\u003e\n"]]],[],null,["# Handler Testing For Python 2\n\nThe [Local Unit\nTesting for Python](/appengine/docs/legacy/standard/python/tools/localunittesting) article described how to run unit tests for your\napplication. While unit tests are great for testing the separate units of your\ncode, the integration of those code units is what makes your application run---so integration testing is just as important.\n\nFor App Engine applications, request handlers are critical integration\npoints. While a WSGI application routes requests to the right handler, the\nhandler itself processes the request data and generates a response (read more\nabout [Request\nHandlers](/appengine/docs/legacy/standard/python/tools/webapp/requesthandlers)). Request handlers are normal Python objects like any other\nfunction or class, which makes them easy to use in automated tests. But because\na WSGI application wraps them like a shell, we will use a similar shell in our\ntests.\n\nWebTest\n-------\n\nFor our tests, we will utilize the\n[WebTest framework](http://webtest.pythonpaste.org). WebTest is a\nlibrary that gives you a simple interface for testing WSGI-based applications\nand therefore the request handlers. It does so by wrapping a WSGI application\nin a special test app which can then be used for testing. WebTest allows you to\ninteract with your handlers without a full App Engine environment; you can\neasily issue requests and modify the request environment. The responses have a\ntest-friendly interface as well. You don't have to use WebTest, but it sure\nmakes your life a lot easier.\n\nBefore you can start, install WebTest on your local machine or wherever you\nintend to run handler tests. Instructions can be found at\n[http://webtest.pythonpaste.org/#installation](http://webtest.pythonpaste.org/en/latest/index.html#installation)\n\nTesting a Simple \"Hello World\"\nHandler\n--------------------------------------\n\nLet's begin with testing a simple \"Hello World!\" handler that responds to a\nuser request with a plain-text reply. The handle's response is \"Hello World!\"\nand the content type is \"text/plain\": \n\n```python\nimport webapp2\nimport webtest\n\nclass HelloWorldHandler(webapp2.RequestHandler):\n def get(self):\n # Create the handler's response \"Hello World!\" in plain text.\n self.response.headers['Content-Type'] = 'text/plain'\n self.response.out.write('Hello World!')\n```\n\nNext, create the test case and initialize a test application that uses your\nhandler: \n\n```python\n...\nclass AppTest(unittest.TestCase):\n def setUp(self):\n # Create a WSGI application.\n app = webapp2.WSGIApplication([('/', HelloWorldHandler)])\n # Wrap the app with WebTest's TestApp.\n self.testapp = webtest.TestApp(app)\n\n # Test the handler.\n def testHelloWorldHandler(self):\n response = self.testapp.get('/')\n self.assertEqual(response.status_int, 200)\n self.assertEqual(response.normal_body, 'Hello World!')\n self.assertEqual(response.content_type, 'text/plain')\n```\n\nAs you can see, WebTest allows you to make GET requests with a simple get()\ncall (other request methods have similar methods). The return value is a\nresponse object with which you can test the status code, body, content type,\nand much more---check out\nthe [WebTest homepage](http://webtest.pythonpaste.org/) for a\ndetailed description of all the things you can do.\n\nCreating a\nHandler Test that Uses an App Engine Service\n-------------------------------------------------------\n\nNow let's have a look at how to test a handler that uses an App Engine\nservice. This means we must now deal with two components that may affect our\ntests: the handler and the service we are using. As described in\nthe [Local Unit Testing\nfor Python](/appengine/docs/legacy/standard/python/tools/localunittesting) article, the best way to deal with services in tests is to\nuse [testbed](/appengine/docs/legacy/standard/python/tools/localunittesting#intro).\n\nThe following example uses Memcache, but it is the same in principle for\nother services like Datastore or Task Queue.\n\nThe handler we test caches the given key and value. Notice that we parse\nboth values from the request parameters. \n\n```python\nfrom google.appengine.api import memcache\nfrom google.appengine.ext import testbed\nimport webapp2\nimport webtest\n\nclass CacheHandler(webapp2.RequestHandler):\n def post(self):\n key = self.request.get('key')\n value = self.request.get('value')\n memcache.set(key, value)\n```\n\nIn the test, just like before, first create an application and wrap it with\nWebTest. Additionally, activate\na [Testbed](/appengine/docs/legacy/standard/python/tools/localunittesting#intro)\ninstance and take care to deactivate after the test. \n\n```python\n...\nclass AppTest(unittest.TestCase):\n\n def setUp(self):\n app = webapp2.WSGIApplication([('/cache/', CacheHandler)])\n self.testapp = webtest.TestApp(app)\n self.testbed = testbed.Testbed()\n self.testbed.activate()\n\n def tearDown(self):\n self.testbed.deactivate()\n\n def testCacheHandler(self):\n # First define a key and value to be cached.\n key = 'answer'\n value = '42'\n self.testbed.init_memcache_stub()\n params = {'key': key, 'value': value}\n # Then pass those values to the handler.\n response = self.testapp.post('/cache/', params)\n # Finally verify that the passed-in values are actually stored in Memcache.\n self.assertEqual(value, memcache.get(key))\n```\n\nSetting Up a Testing Framework\n------------------------------\n\nYou can set up a testing framework if you like. Tests for handlers that use\nWebTest can be\nexecuted [like\nyour unit tests for App Engine](/appengine/docs/legacy/standard/python/tools/localunittesting#setup). The only difference is that you need to\nmake sure you have WebTest installed."]]