摘要:框架本身可以很好地支持自下而上的單元測(cè)試。在中,這些原因可以分為性能真實(shí)的操作,依靠定時(shí)行為及網(wǎng)絡(luò)活動(dòng)減慢了測(cè)試隔離單元測(cè)試應(yīng)把重點(diǎn)放在小的一塊功能成為可能,并解耦不可靠的或低依賴(lài)使用對(duì)象是擁抱和的基本組成部分。
最近在慢慢深入Backbone,也試著寫(xiě)一些測(cè)試,找一些合適的文檔來(lái)學(xué)習(xí)。于是就找到了一個(gè)系列的文章 : Testing Backbone applications with Jasmine and Sinon – Part 1
概覽這是第一次展示如何測(cè)試Backbone.js應(yīng)用的一系列文章,在這里我們使用Jasmine BDD測(cè)試框架以及Sinon.JS庫(kù)的spying,stubbingt和mocking。
在這一部分,我們將簡(jiǎn)單地說(shuō)一下Backbone,緊接著我們將介紹Jasmine和Sinon的一些細(xì)節(jié)。在這個(gè)過(guò)程中,我們將會(huì)看到這些工具是如何完美地測(cè)試Backbone應(yīng)用。
無(wú)處不在的Backbone最近的幾個(gè)月里,隨著大量教程的推出以及一些高性能的實(shí)現(xiàn),使得Backbone獲得了更多的關(guān)注。
我們可以用下面的原因來(lái)解釋Backbone的流行。它提供了一個(gè)最小化的model-view-controller(模式-視圖-控制器)的框架來(lái)幫助開(kāi)發(fā)者控制復(fù)雜的代碼,但是與此同時(shí)它可以與其他一些框架一起工作。這就意味著,與Cappuccino這些富JS UI框架相比,Backbone不提供UI框架或者主題,但是它可以讓開(kāi)發(fā)者去選擇DOM庫(kù)。Backbone對(duì)于jQuery或者Zepto支持得特別好,但是你也可以使用別的庫(kù)來(lái)代替他們。
Backbone MVC框架本身可以很好地支持自下而上的單元測(cè)試。models,collections,views和routers的隔離,意味著每個(gè)部分的行為可以多帶帶地測(cè)試,使調(diào)試更簡(jiǎn)單。
對(duì)于那些有MVC框架(如Rails和Django)開(kāi)發(fā)測(cè)試經(jīng)驗(yàn)的人來(lái)說(shuō),這部分的開(kāi)發(fā)也會(huì)很熟悉。很有多成熟的單元測(cè)試庫(kù),工具和方法可以測(cè)試這些應(yīng)用。你只需要去寫(xiě)Javascript測(cè)試去保證你的前端代碼和你的服務(wù)端代碼同樣的高效。
Jasmine BDD(這里就不引用原文對(duì)于Jasmine的介紹了,簡(jiǎn)單地來(lái)說(shuō)就是下面這樣子)
不依賴(lài)于其它任何框架;
不需要DOM支持(也就是說(shuō)可以脫離瀏覽器?。?/p>
行為驅(qū)動(dòng)式語(yǔ)法,寫(xiě)起來(lái)非常簡(jiǎn)單;
支持對(duì)異步調(diào)用的測(cè)試;
可以在多種環(huán)境中運(yùn)行(包括Ruby、NodeJS、Scala、Java、BPM、.net、Perl)
Specs多說(shuō)無(wú)益,讓我們來(lái)看看一個(gè)簡(jiǎn)單地用于Backbone Model的Jasmine測(cè)試。
it("should expose an attribute", function() { var episode = new Backbone.Model({ title: "Hollywood - Part 2" }); expect(episode.get("title")) .toEqual("Hollywood - Part 2"); });
一個(gè)spec只是簡(jiǎn)單地描述了一下預(yù)期的行為,上面的代碼會(huì)執(zhí)行該行為,以及一種或多種期望測(cè)試行為的代碼。
個(gè)別spec應(yīng)短而且只測(cè)試行為的一個(gè)方面。如果你發(fā)現(xiàn)自己寫(xiě)了一些不同的期望或spec變得非常長(zhǎng),那么考慮將它變成其他spec。將你的spec與suites分組,并使用set up和teardown函數(shù)可以幫助這一點(diǎn)。
SuitesSpecs分組為Suites,這被定義在describe()函數(shù)。例如,所有的specs為集模式可以被分成一組,如下所示:
describe("Episode model", function() { it("should expose an attribute", function() { ... }); it("should validate on save", function() { ... }); });
很不錯(cuò)的一點(diǎn)是,Suites也可以嵌套。當(dāng)你有很多specs的,因?yàn)槟憧梢詫⑺鼈兘M織成組離散塊。我喜歡用一個(gè)描述塊包與特定語(yǔ)境出發(fā)specs。這更好地保留了specs的會(huì)話(huà)風(fēng)格。例如:
describe("Episode model", function() { describe("when creating a new episode", function() { it("should expose the title attribute", function() { ... }); it("should have a default parental rating", function() { ... }); }); });beforeEach() and afterEach()
作為傳統(tǒng)風(fēng)格的xUnit測(cè)試框架,可以選擇指定的代碼在每次測(cè)試后運(yùn)行。這是一個(gè)很不錯(cuò)的功能,以確保一致的條件下對(duì)每個(gè)試驗(yàn),并用于設(shè)置變量和對(duì)象中的規(guī)格使用。
下面的示例使用beforeEach()來(lái)創(chuàng)建一個(gè)用于每個(gè)sepc的Model實(shí)例。
describe("Episode", function() { beforeEach(function() { this.episode = new Backbone.Model({ title: "Hollywood - Part 2" }); }); it("should expose an attribute", function() { expect(this.episode.get("title")) .toEqual("Hollywood - Part 2"); }); it("should validate on save", function() { ... }); });
你可以提供一個(gè)beforeEach()和afterEach()方法在每個(gè)嵌套的describe,接著在你的specs,讓你擁有專(zhuān)為每個(gè)Suites的規(guī)格一般或者特殊setup()和teardown()。正如您將在本文的其它部分看,這是非常方便的確實(shí)減少重復(fù)和控制每個(gè)specs的確切條件。
The spec runner這種結(jié)構(gòu)使得specs對(duì)于其他開(kāi)發(fā)者能夠直易讀和容易理解的。,主要是因?yàn)閷?duì)每個(gè)specs的說(shuō)明以及期望的匹配的格式。
Jasmine還提供了一個(gè)簡(jiǎn)單的spec runner,這簡(jiǎn)直是與將運(yùn)行所有你所提供的規(guī)范的腳本的HTML頁(yè)面。下面顯示了一個(gè)suite的specs與單一spec故障的輸出:
我們將推出茉莉花其他一些有用的功能在本文的其它部分,因?yàn)槲覀冃枰麄?,包括?chuàng)建固定裝置,使用jQuery和創(chuàng)建自己的自定義期望的匹配?,F(xiàn)在,到Sinon.JS。
我們將在本文的其他部分說(shuō)明一些Jasmine有用的功能,因?yàn)槲覀冃枰@些功能,包括creating fixtures,使用jQuery和創(chuàng)建自己的自定義期望的匹配?,F(xiàn)在,讓我們?cè)囋嘢inon.JS。
Sinon.JSSinon.js提供了fake對(duì)象——spies,stubs和mocks,是一個(gè)專(zhuān)用于Javascript的個(gè)測(cè)試輔助工具。利用這些結(jié)構(gòu)在測(cè)試JavaScript代碼是不是已經(jīng)真正流行起來(lái),只是剛剛開(kāi)始。但是,如果你正在開(kāi)發(fā)一個(gè)豐富的,復(fù)雜的應(yīng)用程序,如您在使用Backbone,然后fake對(duì)象是測(cè)試工具集的一個(gè)非常有用的部分。
Christian Johansen——Sinon.JS的創(chuàng)建者,解釋了為什么你需要fake。在Javascript中,這些原因可以分為
性能 真實(shí)的DOM操作,依靠定時(shí)行為及網(wǎng)絡(luò)活動(dòng)減慢了測(cè)試
隔離 單元測(cè)試應(yīng)把重點(diǎn)放在小的一塊功能成為可能,并解耦不可靠的或低依賴(lài)
使用fake對(duì)象是擁抱TDD和BDD的基本組成部分。他們基本上是讓代碼能夠脫離其依賴(lài)進(jìn)行測(cè)試。任何API或模塊測(cè)試你的代碼依賴(lài)于可以fake的,你需要為你的測(cè)試的方式作出回應(yīng)。您也可以檢查fake的方法,看看測(cè)試的過(guò)程中,究竟他們是如何被調(diào)用。
Sinon.JS允許你提供fake幾乎所有的東西。您可以將自己的應(yīng)用程序的fake,在jQuery的,當(dāng)XMLHttpRequest API本身特定的行為,或者你甚至可以fake JavaScript的計(jì)時(shí)方法,對(duì)于有時(shí)間依賴(lài)性,如動(dòng)畫(huà)和超時(shí)快速的測(cè)試代碼。
Sinon.JS提供了三種類(lèi)型的fake對(duì)象:spies, stubs and mocks。
Spies(ps:這部分翻譯得很爛)
Spies是跟蹤的方式和他們被調(diào)用的函數(shù),以及返回想要的值。這是異步的,這在事件驅(qū)動(dòng)的應(yīng)用非常有用,你可以發(fā)送一個(gè)spy以記錄正在發(fā)生的事情,即使這些方法都是匿名或封閉。
spies可以“匿名”,也可以對(duì)現(xiàn)有功能的spy。
一個(gè)匿名的spy只是用spying功能的空函數(shù),可以記錄下它是如何被使用的。像一個(gè)真正的speis 被送往敵后與連接到它的胸口的麥克風(fēng),而測(cè)試方法是不知道。這里是一個(gè)spy測(cè)試一個(gè)簡(jiǎn)單的Backbone自定義事件綁定的例子:
it("should fire a callback when "foo" is triggered", function() { // Create an anonymous spy var spy = sinon.spy(); // Create a new Backbone "Episode" model var episode = new Episode({ title: "Hollywood - Part 2" }); // Call the anonymous spy method when "foo" is triggered episode.bind("foo", spy); // Trigger the foo event episode.trigger("foo"); // Expect that the spy was called at least once expect(spy.called).toBeTruthy(); });
這測(cè)試將會(huì)通過(guò),當(dāng)spies被調(diào)用一次或多次,不管它是如何調(diào)用或什么參數(shù)。然而,Sinon提供了一些方法,讓你嚴(yán)格的限制調(diào)用次數(shù),的確是每次調(diào)用看起來(lái)都像,spy返回了什么。
Spying行為也可以被連接到一個(gè)現(xiàn)有的方法。歡快的,我喜歡叫這些“moles”。這是有用的,以檢查某些小部分的功能被調(diào)用的代碼的另一部分與預(yù)期一樣。例如,您可能要檢查模型的保存方法,確保正確的jQuery $.ajax 調(diào)用 :
it("should make the correct server request", function() { var episode = new Backbone.Model({ title: "Hollywood - Part 2", url: "/episodes/1" }); // Spy on jQuery"s ajax method var spy = sinon.spy(jQuery, "ajax"); // Save the model episode.save(); // Spy was called expect(spy).toHaveBeenCalled(); // Check url property of first argument expect(spy.getCall(0).args[0].url) .toEqual("/episodes/1"); // Restore jQuery.ajax to normal jQuery.ajax.restore(); });Stubs and Mocks
保留原文關(guān)于Stubs和Mocks的解釋
Stubs and mocks in Sinon implement all the features of spies, but with some added features. Stubs allow you to replace the existing behaviour of a particular method with whatever you like. This is great for emulating exceptions and error scenarios from external dependencies so you can test that your code will respond appropriately. It also allows you to start development when other dependencies are not yet in place.
Mocks provide all this, but instead mock an entire API and set built-in expectations on how they will be utilised. Like spies they track how they have been used, and like stubs they respond in a pre-programmed manner according to the needs of the test. However, unlike a spy, the expectations for their behaviour is pre-programmed, and a single verification step at the end will fail if any of these individual expectations are not met.
簡(jiǎn)單的來(lái)說(shuō)
Stubs就是返回你想要的結(jié)果。
Mocks就是確保方法被調(diào)用 。
Stub是代碼的一部分。其目的就是用簡(jiǎn)單的行為替換復(fù)雜的行為,從而允許獨(dú)立地測(cè)試代碼的一部分。
Mock Object是使用來(lái)代替與你的代碼協(xié)作的對(duì)象的對(duì)象,這樣代碼可以調(diào)用Mock Object的方法,這些方法的調(diào)用的結(jié)果是由你的測(cè)試設(shè)置好的。
相關(guān)文章: mock stub與tdd
Fake Ajax and fake serversSinon不局限于Spying on和stubbing普通函數(shù)和方法。它還提供了快捷的偽造Ajax響應(yīng)方式。這意味著您可以從您的JSON數(shù)據(jù)源完全隔離測(cè)試你的代碼,并且不依賴(lài)于以運(yùn)行spec suites運(yùn)行的Web應(yīng)用程序。此外,你可以測(cè)試你的應(yīng)用程序響應(yīng)適當(dāng)?shù)臅r(shí)候?qū)⑵鋸男腋5穆窂?,包括無(wú)效的JSON和各種HTTP響應(yīng)代碼偏離。
這里有用于Backbone模型spec的獲取方法,它使用一個(gè)fake的server來(lái)響應(yīng)Ajax請(qǐng)求的一個(gè)簡(jiǎn)單的例子:
describe("Episode model", function() { beforeEach(function() { this.server = sinon.fakeServer.create(); }); afterEach(function() { this.server.restore(); }); it("should fire the change event", function() { var callback = sinon.spy(); // Set how the fake server will respond // This reads: a GET request for /episode/123 // will return a 200 response of type // application/json with the given JSON response body this.server.respondWith("GET", "/episode/123", [200, {"Content-Type": "application/json"}, "{"id":123,"title":"Hollywood - Part 2"}"]); var episode = new Episode({id: 123}); // Bind to the change event on the model episode.bind("change", callback); // makes an ajax request to the server episode.fetch(); // Fake server responds to the request this.server.respond(); // Expect that the spy was called with the new model expect(callback.called).toBeTruthy(); expect(callback.getCall(0).args[0].attributes) .toEqual({ id: 123, title: "Hollywood - Part 2" }); }); });
這個(gè)spec測(cè)試可以通過(guò)下面這個(gè)簡(jiǎn)單的Backbone Model
var Episode = Backbone.Model.extend({ url: function() { return "/episode/" + this.id; } });
還有更多的興農(nóng),我們這里不討論。特別是,fake timer是為測(cè)試時(shí)間依賴(lài)的功能非常有用,例如動(dòng)畫(huà),而不會(huì)減慢您的測(cè)試。
總結(jié)(ps:總結(jié),就是翻譯得一般般)
在Backbone應(yīng)用的帶血的世界里,復(fù)雜的異步和相互依存的行為可能會(huì)導(dǎo)致任何開(kāi)發(fā)人員傷透腦筋。Backbone可以幫助開(kāi)發(fā)人員構(gòu)建自己的代碼轉(zhuǎn)換成小的,獨(dú)立的models,collections, views和routers。但是,這是真的只是成功的一半。如果沒(méi)有經(jīng)過(guò)充分測(cè)試的代碼將會(huì)有更多的未被發(fā)現(xiàn)的缺陷,而那些被發(fā)現(xiàn)將很難追查。其他團(tuán)隊(duì)成員可能會(huì)無(wú)意中破壞你的代碼,或者干脆誤解了它的目的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/8692.html
摘要:主要由三部分組成創(chuàng)建數(shù)據(jù),進(jìn)行數(shù)據(jù)驗(yàn)證,銷(xiāo)毀或者保存到服務(wù)器上。綁定模板,綁定界面元素的事件,初始的渲染,模型值改變后的重新渲染和界面元素的銷(xiāo)毀等。這樣我們便可以完成一個(gè)簡(jiǎn)單地測(cè)試的書(shū)寫(xiě)。 在一點(diǎn)點(diǎn)慢慢地寫(xiě)一個(gè)簡(jiǎn)單的SPA應(yīng)用,在這樣的一個(gè)過(guò)程里,我們也不得不寫(xiě)一些測(cè)試以方便重構(gòu)。 Backbone Collection Bacbkbone主要由三部分組成 model:創(chuàng)建數(shù)據(jù)...
摘要:很快我發(fā)現(xiàn)有一個(gè)誤區(qū),許多人認(rèn)為單元測(cè)試必須是一個(gè)集中運(yùn)行所有單元的測(cè)試,并一目了然。許多人認(rèn)為單元測(cè)試,甚至整個(gè)測(cè)試都是在編碼結(jié)束后的一道工序,而修復(fù)也不過(guò)是在做垃圾掩埋一類(lèi)的工作。 單元測(cè)試Unit Test 很早就知道單元測(cè)試這樣一個(gè)概念,但直到幾個(gè)月前,我真正開(kāi)始接觸和使用它。究竟什么是單元測(cè)試?我想也許很多使用了很久的人也不一定能描述的十分清楚,所以寫(xiě)了這篇文章來(lái)嘗試描述它...
摘要:首先安裝單元測(cè)試環(huán)境使用模塊來(lái)模擬定義的模型。根據(jù)刪除這是單元測(cè)試的最后一小節(jié)。需要根據(jù)需求和單元測(cè)試用例來(lái)編寫(xiě)應(yīng)用邏輯,使我們的程序更加穩(wěn)定。我們會(huì)運(yùn)行自動(dòng)測(cè)試用例,一直重構(gòu),直到所有單元測(cè)試都通過(guò)。 本文轉(zhuǎn)載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/746原文:https://semaphoreci.com/community/tutoria...
摘要:首先安裝單元測(cè)試環(huán)境使用模塊來(lái)模擬定義的模型。根據(jù)刪除這是單元測(cè)試的最后一小節(jié)。需要根據(jù)需求和單元測(cè)試用例來(lái)編寫(xiě)應(yīng)用邏輯,使我們的程序更加穩(wěn)定。我們會(huì)運(yùn)行自動(dòng)測(cè)試用例,一直重構(gòu),直到所有單元測(cè)試都通過(guò)。 本文轉(zhuǎn)載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/746原文:https://semaphoreci.com/community/tutoria...
閱讀 2931·2021-11-23 09:51
閱讀 3178·2021-11-12 10:36
閱讀 3214·2021-09-27 13:37
閱讀 3168·2021-08-17 10:15
閱讀 2596·2019-08-30 15:55
閱讀 2757·2019-08-30 13:07
閱讀 800·2019-08-29 16:32
閱讀 2655·2019-08-26 12:00