單元測試可讓您在撰寫程式碼之後檢查品質,但也可以在開發期間使用單元測試來改進開發流程。您不需在開發完成後才撰寫測試,而可以在開發過程中即撰寫測試。這麼做可協助您設計可管理且可重複使用的小單元程式碼。測試程式碼也可以更輕鬆且快速徹底。
進行本機單元測試時,可在擁有的開發環境中執行測試,而不需遠端元件的輔助。App Engine 提供的測試公用程式採用了資料儲存庫及其他 App Engine 服務的本機實作。換句話說,您可以在本機執行程式碼的服務用途,無需透過服務虛設常式將程式碼部署至 App Engine。
服務虛設常式是一種模擬服務行為的方法。例如,撰寫 Datastore 與 Memcache 測試所示的資料儲存庫服務虛設常式可讓您測試資料儲存庫程式碼,而無須對真實的資料儲存庫提出任何要求。在資料儲存庫單元測試時儲存的實體不會儲存在資料儲存庫中,而是儲存在記憶體中,執行測試後即會遭到刪除。您可以執行快速的小型測試,而完全不需動用資料儲存庫。
這份文件提供有關設定測試架構的一些資訊,並說明如何針對一些本機 App Engine 服務撰寫單元測試。
設定測試架構
即使 SDK 的測試公用程式並無特定要和任何架構搭配使用,本指南仍使用 JUnit 做為範例,讓您有具體而完整的內容可以參考。在您開始撰寫測試之前,需要將適當的 JUnit 4 JAR 新增至測試類別路徑。完成後,您就可以開始撰寫十分簡單的 JUnit 測試。
如果您執行的是 Eclipse,請選取測試的來源檔案執行。依序選取「Run」選單 >「Run As」 >「JUnit Test」。測試結果會顯示在「主控台」視窗中。
Java 8 測試公用程式簡介
MyFirstTest
示範了最簡單的可能測試設定,如果是對 App Engine API 沒有相依性的測試或本機服務實作,您可能不再需要任何設定。不過,如果您的測試或測試中的程式碼具有這些相依性,請將下列 JAR 檔案新增至您的測試類別路徑:
${SDK_ROOT}/lib/impl/appengine-api.jar
${SDK_ROOT}/lib/impl/appengine-api-stubs.jar
${SDK_ROOT}/lib/appengine-tools-api.jar
這些 JAR 為您的測試提供執行階段 API 與這些 API 的本機實作。
App Engine 服務的執行環境中有眾多項目必須處理,而設定這些項目時,需要使用大量的模組化程式碼。您不必自行設定,可以使用 com.google.appengine.tools.development.testing
套件中的公用程式。如要使用這個套件,請將下列 JAR 檔案新增至您的測試類別路徑:
${SDK_ROOT}/lib/testing/appengine-testing.jar
請花點時間瀏覽 com.google.appengine.tools.development.testing
套件的 javadoc。此套件中最重要的類別是 LocalServiceTestHelper,這個類別可以處理所有必要的環境設定,並為您想要在測試中存取的所有本機服務提供最重要的設定。
如何撰寫存取特定本機服務的測試:
- 使用特定本機服務的
LocalServiceTestConfig
實作項目,建立LocalServiceTestHelper
的例項。 - 在每次測試之前,對您的
LocalServiceTestHelper
例項呼叫setUp()
,並在每次測試後呼叫tearDown()
。
編寫資料儲存庫和 Memcache 測試
以下範例對資料儲存庫服務的使用進行測試。
在這個範例中,LocalServiceTestHelper
會設定並拆解執行環境的部分,這些部分對所有本機服務都通用;LocalDatastoreServiceTestConfig
則會設定並拆解執行環境的部分,這些部分對本機資料儲存庫服務專用。閱讀 javadoc 後,您會瞭解這項操作涉及設定本機資料儲存庫服務,以便將所有資料保留在記憶體中 (而非每隔固定時間就將資料刷新至磁碟),並在每次測試結束時清除所有記憶體內資料。這只是資料儲存庫測試的預設行為,如果您不喜歡這種行為,可以自行變更。
將範例變更為存取 Memcache (而非資料儲存庫)
如要建立存取本機 Memcache 服務的測試,您只需小幅修改上方程式碼,即可用來建立測試。
請改為匯入與 Memcache 相關的類別,而不要匯入與資料儲存庫相關的類別。您仍需要匯入 LocalServiceTestHelper
。
變更您要建立的類別名稱,並變更 LocalServiceTestHelper
的例項,使這些項目專屬於 Memcache。
最後,變更您實際執行測試的方式,這樣測試才會與 Memcache 相關。
如資料儲存庫範例所示,LocalServiceTestHelper
和服務專屬的 LocalServiceTestConfig
(在本例中為 LocalMemcacheServiceTestConfig
) 可管理執行環境。
撰寫 Cloud Datastore 測試
如果應用程式使用的是 Cloud Datastore,建議您撰寫測試來驗證應用程式對於最終一致性的行為。LocalDatastoreServiceTestConfig
提供了選項,讓撰寫相關測試變的十分容易:
請將尚未套用的工作百分比設為 100,指示本機資料儲存庫以最終一致性的數量上限進行運作。採用最高程度的最終一致性表示即使寫入也一律無法套用,導致全域 (非祖系) 查詢永遠都無法找出變更。當然,這不代表您的應用程式在正式作業環境中執行時會面臨的最終一致性程度,但就測試目的而言,能夠每次都以這種方式設定本機資料儲存庫的行為相當實用。
如果您想要更進一步掌握無法套用哪些交易,可以註冊自己的 HighRepJobPolicy
:
如要驗證您的應用程式在面對最終一致性的要求時是否正常運作,測試 API 非常實用。不過,請記住,本機的「高複製」讀取一致性模型只能說相當接近正式作業「高複製」的讀取一致性模型,而非完全相同。在本機環境中,如果執行的 get()
函式所屬 Entity
屬於的實體群組有未套用的寫入,未套用寫入的結果一律可見於後續全域查詢中。但在正式作業環境中就不是這樣。
撰寫工作佇列測試
使用本機工作佇列的測試有一點複雜,因為與資料儲存庫和 Memcache 不同,工作佇列 API 不會公開檢測服務狀態的設備。我們必須直接存取本機工作佇列,確認是否已使用預期的參數來排定工作。如要這麼做,我們需要 com.google.appengine.api.taskqueue.dev.LocalTaskQueue
。
請注意我們會透過某種方式向 LocalTaskqueueTestConfig
要求本機服務執行個體控制代碼,然後對本機服務進行調查,確認依照預期排定工作。所有 LocalServiceTestConfig
實作都會公開類似的方法。您不一定會用到這些方法,但日後需要用到時就可以派上用場。
設定 queue.xml
設定檔
工作佇列測試程式庫可透過 LocalTaskQueueTestConfig.setQueueXmlPath
方法,在 LocalServiceTestHelper 的基礎上指定任何數量的 queue.xml
設定。目前,本機開發伺服器會忽略任何佇列的頻率限制設定。您在本機無法一次同時執行多個工作。
例如,專案可能需要對 App Engine 應用程式上傳及使用的 queue.xml
檔案進行測試。假設 queue.xml
檔案位於標準位置,請如下修改以上範例程式碼,將測試存取權授予在 src/main/webapp/WEB-INF/queue.xml
檔案中指定的佇列:
修改 queue.xml
檔案的路徑,以符合專案的檔案結構。
使用 QueueFactory.getQueue
方法按名稱存取佇列:
撰寫延期工作測試
如果您的應用程式程式碼使用延期工作,Java 測試公用程式可讓您輕鬆撰寫整合測試來驗證這些工作的結果。
與第一個本機工作佇列範例一樣,我們使用 LocalTaskqueueTestConfig
,但這次我們會使用一些額外的引數來初始化,讓我們可以輕鬆驗證工作是否已排定,以及是否已執行:我們呼叫 setDisableAutoTaskExecution(false)
來告知本機工作佇列自動執行工作。我們呼叫 setCallbackClass(LocalTaskQueueTestConfig.DeferredTaskCallback.class)
,藉此通知「本機工作佇列」使用可解讀如何執行延期工作的回呼。最後我們呼叫 setTaskExecutionLatch(latch)
,通知「本機工作佇列」在每次執行工作之後減量閂鎖。這項設定允許我們撰寫測試來將「延期」工作加入佇列、等待工作執行,並且在工作執行期間驗證工作行為是否符合預期。
撰寫本機服務功能測試
功能測試涉及變更某些服務 (例如資料儲存庫、Blobstore、Memcache 等) 的狀態,以及對該服務執行應用程式來確認您的應用程式在不同的情況下是否依預期回應。功能狀態可以使用 LocalCapabilitiesServiceTestConfig 類別變更。
以下程式碼片段將資料儲存庫服務的功能狀態變更為停用,然後對資料儲存庫服務執行測試。您可以視需要用其他服務來取代資料儲存庫。
範例測試首先建立初始化為資料儲存庫的 Capability
物件,然後建立設定為 DISABLED 的 CapabilityStatus
物件。LocalCapabilitiesServiceTestConfig
建立時所使用的功能與狀態,是透過剛建立的 Capability
和 CapabilityStatus
物件設定的。
接著,使用 LocalCapabilitiesServiceTestConfig
物件建立 LocalServiceHelper
。現在測試已經設定完成,DatastoreService
已經建立,也已經為其傳送「查詢」來確認測試是否產生了預期的結果,在本例中,就是 CapabilityDisabledException
。
撰寫其他服務的測試
測試公用程式適用於 BlobStore 和其他 App Engine 服務。如需含有本機測試部署項目的完整服務清單,請參閱 LocalServiceTestConfig
說明文件。
使用驗證預期項目撰寫測試
這個範例顯示如何撰寫測試來驗證使用 UserService 確認使用者是否已登入或是否具有管理員權限的邏輯。請注意,擁有檢視者、編輯者或擁有者基本角色,或 App Engine 應用程式管理員預先定義角色的任何使用者都擁有管理員權限。
在這個範例中,我們使用 LocalUserServiceTestConfig
設定 LocalServiceTestHelper
,這樣我們就可以在測試中使用 UserService
,但我們也在 LocalServiceTestHelper
本身之上設定了一些驗證相關的環境資料。
在這個範例中,我們會使用 LocalUserServiceTestConfig
設定 LocalServiceTestHelper
,以便使用 OAuthService
。