2016 年 1 月

第 31 卷,第 1 期

本文章是由機器翻譯。

程式設計師雜談 - 如何使用 MEAN: 測試 MEAN

Ted Neward |2016 年 1 月

Ted NewardHowdy,「 Nodeists 」。 歡迎回到輸入、 輸出、 資料庫、 使用者、 Ui、 Api 和平行 universe 繼續傳奇的詳細資訊。(請參閱本系列的第一個部分 [msdn.com/magazine/mt185576] 如果您錯過了該參考。)

在前幾期 (msdn.com/magazine/mt595757),應用程式已成長到所建置的 API 端點 (超級簡化 「 person 」 資料庫) 其中包含 CUD,其中前幾期提供了只是"R"其 CRUD 設備出捨入的點 當然,很重要,打造出以小距離,但是是很不錯,可以看到它的變更,並反映它們時要求其相關的一些東西。

這帶出不安的點。在建置這類的 Web API 時,「 簡單測試 」 中的開發人員也可以啟動網頁和看出它來判斷是否有正常運作,並非的選項。嗯,當然說過的最後一次,因為使用 cURL,之類的工具 Postman 或 Runscope 有助於輕鬆地看出,但坦白說,信任目光的不是點。應用程式需要某些自動化的測試,以協助確保一切都運作順暢且正確。它應該是輕鬆地執行,也涵蓋的程式碼並具有所有其他特性,因此許多其他記錄遠比我好的測試套件。

之前往太深這個路徑中,不過一個注意事項。有一點的爭論周圍 「 單位 」 的測試,也有複雜的程式碼的內部運作,而且 (通常) 需要某種程度的模擬 (mock) (在此情況下,快速要求和回應物件,例如)。這些應該很小,已取得焦點且快速地執行,所以當作 (緊接編譯 C# 等語言的編譯) 的建置程序而不需要程式設計師變慢和誘發它們從他們的想法的流程。另一個檢視是 「 整合 」 或 「 功能 」 測試,也就是多個 「 外部的 「 測試,表示測試依賴執行其動作的架構和圖層視為較不透明的實體。針對 Web Api,我比較偏好後者。我發現嘗試撰寫單元測試 Express 控制器通常會比以取得所有模擬 (mock) 權限的好處更多工作。假設控制站通常主要做為單一用途,且有幾個,如果有的話,Express 層會干擾到測試我自己的程式碼中,我發現的 bug,我發現外部測試 dereference-如-您-buck 討論中的較佳的值。

使用該走,就開始撰寫一些測試,以執行人員我建置了到目前為止的 API。因此,有兩個 Node.js 封裝的立即: mocha 和 supertest。

取得測試

當然,使用的所有項目 Nodeish,生命開頭 npm;在此情況下,mocha 和 supertest 必須加入至專案,透過 npm 安裝:

npm install --save-dev mocha supertest

(雖然傳統分開執行,沒有理由做它們一起類似的尤其是在此情況下,我已經知道我想要同時使用。)

除此之外,我傳遞之前,請注意--儲存開發人員引數: 這麼做會放到 package.json 檔案,表示他們正在開發階段專用的相依性,如此一來,當定域機組的 devDependencies 區段的兩個主機 (例如 Microsoft Azure) 準備在生產環境中執行程式碼,請他們將會省略這些。

Node.js 社群會將其測試架構,就像它就會進行其餘的專案: 為小型的位元,尋找建構在一起以開發人員定義的方式,來建立整個也就我們可以假設,開發人員呈現方式。在此情況下,測試開始 mocha 套件,也就是測試套件,目的是要讓 「 非同步測試簡單又有趣 」,根據其網站。如果您將測試工作,它會做為基本 「 scaffolding,」。但因為受測試的項目會是 Web Api (而且我不想要撰寫此低階 HTTP 程式碼),第二個程式庫、 supertest,將會新增一些有用的 HTTP 特定測試的行為。還有一組詳細的選擇性部分應該選擇加入,因為我偏好行為開發 (BDD) 程式庫-樣式應該判斷提示。但 assert 套件,其包含在使用 mocha,也會有的人偏好傳統的判斷提示樣式。

一旦安裝這兩個封裝,測試開始時,不用多說,藉由撰寫第一個測試。雖然並非必要,是很常見的 Node.js 專案,以建立個別的子目錄中的測試程式碼生活呼叫,不用多說,測試。到這個目錄中會如所示的第一個測試檔案,getTest.js, [圖 1

[圖 1 設定某些基準測試只為了好玩

var supertest = require('supertest');
  var express = require('express');
  var assert = require('assert');
  var should = require('should');
  describe('Baseline tests', function() {
    describe('#indexOf()', function () {
      it('should return -1 when the value is not present', function () {
        assert.equal(-1, [1,2,3].indexOf(5));
        assert.equal(-1, [1,2,3].indexOf(0));
        [1,2,3].indexOf(5).should.equal(-1);
        [1,2,3].indexOf(0).should.equal(-1);
      });
    });
  });

有幾件事我繼續之前,需要一些說明。描述方法都是簡單的輸出執行配對,字串是應該會顯示在 [測試] 主控台 (通常是命令提示字元或終端機視窗) 的訊息和函式是什麼應該做為測試執行。請注意,描述區塊可以巢狀 — 這會很有用來分散測試沿著邏輯程式敘述行,因為若要關閉整個區塊它們,不需要再可用略過函式。It 函式接著說明單一測試 — 在此情況下,若要測試 JavaScript 陣列 indexOf 方法運作如預期,然後再次將字串傳遞給 「 」 是測試主控台顯示測試的描述。

巢狀函式內 it 呼叫的是,不用多說,實際的測試和這裡我選擇顯示這兩個傳統的判斷提示樣式的判斷提示,以及更像 BDD 的樣式應該判斷提示,這是更流暢的 API。坦白說,還有其他選項 (mocha Web 網頁會列出兩件事,除了這些兩個),但是因為我想應該是我們即將使用。不過,應該封裝將需要安裝透過 npm,而判斷提示已使用 mocha 和 supertest 大功告成了。

如要快速測試,只要型別 「 mocha 」 到 app.js 及它所包含的目錄將會挑選測試子目錄中的測試自動。但 Node.js 有稍微好一點的慣例,也就是填入具有一組更輕鬆地執行; npm 的命令列參數的 package.json 檔案中的指令碼集合「 npm 開始 」 接著就可以開始在伺服器上,以及 「 npm 測試 」 可以執行測試而不需要知道什麼用來建置程式碼的系統管理員 (或雲端系統)。這只需要據此填寫 「 指令碼 」 集合內 package.json:

{
  "name": "MSDN-MEAN",
  "version": "0.0.1",
  "description": "Testing out building a MEAN app from scratch",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "test": "mocha"
  },
  // ...
}

現在,快速 「 npm 測試 」 會啟動測試並了解,沒錯,indexOf 運作正常。

完成後,讓我們先關閉這些測試。(很明顯地,您可以將它們整個移除,不過我想讓基準,我知道的運作方式,與我的設定項目失敗時)。 即可輕鬆使用略過一部分鏈結的描述,如下所示:

describe.skip('Baseline tests', function() {
  describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function () {
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
      [1,2,3].indexOf(5).should.equal(-1);
      [1,2,3].indexOf(0).should.equal(-1);
    });
  });
});

這現在會略過這些測試 — 它們仍然列出測試主控台中,但以指出執行測試的旁邊沒有核取記號。

測試 Api

那很有趣,但是 indexOf 已經很好已經過測試。GET /persons 端點不...尚未。

這是其中 supertest 派上用場。使用它,您可以建立小型的 HTTP 代理程式知道如何查詢端點 (在此情況下,使用"localhost"、 連接埠 3000,伺服器設定,在此之前撰寫的應用程式程式碼所建立),並確認它的結果。這表示有幾個要加入的事項首先,應用程式程式碼具有要載入及執行測試的一部分,而且需要 app.js 檔案,從測試的第一行的上層目錄中刪除:

require("../app.js")

這會使應用程式啟動 (這部分很容易發現如果偵錯環境變數設定為應用程式時,請記得) 和執行。

然後,使用 supertest 程式庫來建立在本機主機伺服器和連接埠 3000 要求物件,您可以使用,發出對 /persons 端點要求,連絡人識別碼為 1 (因此/人員/1,請記得) 並確認它是傳回 [確定] (200 狀態碼),會以 JSON 和 JSON 主體包含預期的如所示 [圖 2

[圖 2 把我的所有人員!

var request = supertest("http://localhost:3000");
describe('/person tests', function() {
  it('should return Ted for id 1', function(done) {
    request
      .get('/persons/1')
      .expect(200)
      .expect('Content-Type', /json/)
      .expect(function(res) {
        res.body.id.should.equal(1)
        res.body.firstName.should.equal("Ted")
        res.body.lastName.should.equal("Neward")
        res.body.status.should.equal("MEANing")
      })
      .end(done);
    });
});

請注意如何要求物件有 get('/persons/1') 轉譯為針對該 URL 的 GET 要求,因此,使用類似之一切明示、 動詞命令方法樣式的 fluent API。後續預期方法,不過,執行完全什麼聽起來: 預期的結果,特定類型,如果並非如此,則會在整個測試。不過,最後一個 end 方法務必注意,因為它會使用一個參數傳遞至 「 它 」: 「 已完成 」 的物件,這是表示在測試完成的不透明回呼。因為 supertest 會的循序測試,但是以非同步的方式 (以 Node.js 方式),需要有一些表示在測試完成,如果做不能用,則兩秒之後 (根據每個測試),supertest 會假設已逾時的測試,並通知發生錯誤。

最後,因為空間變短的範本,讓我們確認您可以將人員加入的資料庫會使用 post 方法,並傳送新的 JSON 物件,其中包含 person 執行個體中所示,新增至系統時,需要沿著 [圖 3

[圖 3 確認加入使用者實際運作,

it('should allow me to add a person', function(done) {
  request
    .post('/persons')
    .send({'firstName':'Ted', 'lastName':'Pattison','status':'SharePointing'})
    .expect(200)
    .expect('Content-Type',/json/)
    .expect(function(res) {
      should.exist(res.body.id);
      res.body.firstName.should.equal("Ted");
      res.body.lastName.should.equal("Pattison");
    })
    .end(done);
  })

很簡單,對吧? 請注意,本文驗證的第一行預期是測試 id 欄位存在。不過,應該程式庫不能信任,將不會是未定義,而且呼叫方法或屬性上未定義,會產生例外狀況,因此您必須使用應該直接以確認它是否存在。除了,不過,它會讀取得很好。

另外兩個方法,需要的測試,PUT 和 DELETE,是很容易撰寫。PUT 端點測試而不是,使用 post 要求會將使用和 URL 必須指向單數 person url (/ 人員/1 」 狀 」 「 Neward 」 的人員例如)。傳送 JSON 本文看起來相同 POST 案例中,具有不同值 (因為測試是以查看這些更新將會接受),然後測試 (因為若要查看中傳回的新物件,將會反映這些更新,測試也是) 傳回的 JSON 主體會反映這些更新。並刪除端點測試會使用 delete 方法,將 URL 傳遞的特定使用者 (/ 人員/1),以及這次請傳入兩 JSON 主體也期待傳回。(雖然它看起來從刪除端點傳回已刪除的物件的一般 API 慣例,但坦白說,我個人永遠不會真的過,沒什麼意義而且基於任何原因從未使用傳回的 JSON 主體)。

與五個測試的位置,且在 package.json 中最近加強的 npm 指令碼標記為利器,仍是只有要執行 npm 測試,請觀看 rest 執行器執行其動作、 沒看到錯誤、 執行來源的程式碼認可-和-push 和新的程式碼以更新 Azure 環境。

總結

還有一堆資料 mocha,supertest 應該與我沒有空間可進入 — 例如 like 大部分測試架構,mocha 支援之前和之後將會執行每個測試; 周圍的攔截程序此外,supertest 程式庫支援 cookie 為基礎的要求,與使用 cookie 來維護某些種類的工作階段狀態的 HTTP 端點時,這十分有用。所幸,解決每個這些程式庫的文件是很好,而且網路的範例有太多了。可惜的是,現在正是時候回過頭來...假設祝各位寫程式!


Ted Neward是 Neward & Associates,西雅圖 polytechnology 顧問公司的主體。他已寫入超過 100 個文件、 是 F # MVP 和著作對他的名稱。與他連絡 ted@tedneward.com 如果您想要讓他來自與您的小組,或是閱讀他的部落格 blogs.tedneward.com

感謝以下技術專家對本文的審閱: Shawn Wildermuth