Python 2 適用的處理常式測試

適用於 Python 的本機單位測試一文說明如何為應用程式執行單位測試。雖然單位測試非常適合用於測試個別的程式碼單位,但程式碼單位的整合是讓應用程式得以運作的關鍵,因此,整合測試同樣重要。

就 App Engine 應用程式而言,要求處理常式是關鍵的整合點。WSGI 應用程式會將要求路由至適當的處理常式,而處理常式本身則會處理要求資料並產生回應 (如要瞭解詳情,請參閱要求處理常式)。要求處理常式是如同任何其他函式或類別的一般 Python 物件,易於在自動化測試中使用。但由於 WSGI 應用程式將這些要求處理常式包裝成類似 Shell,因此我們會在測試中使用類似的 Shell。

WebTest

我們會在測試中使用 WebTest 架構。WebTest 是針對測試 WSGI 應用程式提供簡易介面的程式庫,因此適用於要求處理常式。其做法是將 WSGI 應用程式包裝在特殊的測試應用程式中,以供後續測試使用。WebTest 可讓您在不具完整 App Engine 環境的情況下與處理常式互動;您可以輕鬆發出要求及修改要求環境。回應也有便於測試的介面。您未必需要使用 WebTest,但 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 或 Task Queue 等其他服務是相同的。

我們測試的處理常式會快取指定的鍵和值。請注意,我們會剖析要求參數中的兩個值。

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))

設定測試架構

您可以視需要設定測試架構。您可以如同 App Engine 的單位測試方法,針對使用 WebTest 的處理常式進行測試。唯一的差別在於您必須確定已安裝 WebTest。