国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

should.js源碼分析與學(xué)習(xí)

Turbo / 2583人閱讀

摘要:結(jié)構(gòu)其中為整個項(xiàng)目入口,為中的類,負(fù)責(zé)對測試信息進(jìn)行記錄。通過拋出錯誤而不是返回布爾值的方式來通知用戶,能夠更加明顯的通知用戶,也方便向上拋出異常進(jìn)行傳遞。

背景

為了研究與學(xué)習(xí)某些測試框架的工作原理,同時也為了完成培訓(xùn)中實(shí)現(xiàn)一個簡單的測試框架的原因,我對should.js的代碼進(jìn)行了學(xué)習(xí)與分析,現(xiàn)在與大家來進(jìn)行交流下。

目錄

ext

assertion.js

assertion-error.js

config.js

should.js

util.js

其中ext為文件夾,其余為js文件。

結(jié)構(gòu)

其中should.js為整個項(xiàng)目入口,asssertion.js為should.js中的類,負(fù)責(zé)對測試信息進(jìn)行記錄。assertion-error.js為should.js定義了一個錯誤類,負(fù)責(zé)存儲錯誤信息。config.js中存儲了一些should.js中的一些配置信息。util.js中則定義了一些項(xiàng)目中常用的工具函數(shù)。

should.js
var should = function should(obj) {
    return (new should.Assertion(obj));
};

should.AssertionError = require("./assertion-error");
should.Assertion = require("./assertion");

should.format = util.format;
should.type = require("should-type");
should.util = util;
should.config = require("./config");

exports = module.exports = should;

should.js入口文件初始化了一個類,并將所有文件中其他的模塊進(jìn)行引入。同時將自己export出去,讓自己能夠被require到。

should.extend = function (propertyName, proto) {
    propertyName = propertyName || "should";
    proto = proto || Object.prototype;

var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);

Object.defineProperty(proto, propertyName, {
    set: function () {
    },
    get: function () {
        return should(util.isWrapperType(this) ? this.valueOf() : this);
    },
    configurable: true
});

return {
    name: propertyName, descriptor: prevDescriptor, proto: proto};
};

should.js自身定義了一個extend方法,用于兼容should.js的另一種調(diào)用方式,即should(obj)的方式等于should.js的常規(guī)調(diào)用方式obj.should,從而兼容另一種寫法。

should
    .use(require("./ext/assert"))
    .use(require("./ext/chain"))
    .use(require("./ext/bool"))
    .use(require("./ext/number"))
    .use(require("./ext/eql"))
    .use(require("./ext/type"))
    .use(require("./ext/string"))
    .use(require("./ext/property"))
    .use(require("./ext/error"))
    .use(require("./ext/match"))
    .use(require("./ext/contain"));
    

should.js中還定義了use方法,從而讓我們能夠自己編寫一些類型判斷例如isNumber等函數(shù)導(dǎo)入到項(xiàng)目中,從而方便進(jìn)行測試。項(xiàng)目目錄中的ext文件夾就是編寫的一些簡單的should.js的擴(kuò)展。后面將在介紹擴(kuò)展時對兩者的工作原理以及使用方法進(jìn)行介紹。

assertion.js
function Assertion(obj) {
    this.obj = obj;

    //any標(biāo)志位
    //@type {boolean}
    this.anyOne = false;
    
    //not標(biāo)志位
    //@type {boolean}
    this.negate = false;

    this.params = {actual: obj};
}

assertion.js中定義了一個Assertion類,其中any為should.js中的any方法的標(biāo)志位,而not則為其not方法的標(biāo)志位。

Assertion.add = function(name, func) {
    var prop = {enumerable: true, configurable: true};

    prop.value = function() {
        var context = new Assertion(this.obj, this, name);
        context.anyOne = this.anyOne;

        try {
            func.apply(context, arguments);
        } catch(e) {
            //check for fail
            if(e instanceof AssertionError) {
                //negative fail
                if(this.negate) {
                    this.obj = context.obj;
                    this.negate = false;
                    return this;
                }

                if(context !== e.assertion) {
                    context.params.previous = e;
                }

                //positive fail
                context.negate = false;
                context.fail();
            }
            // throw if it is another exception
            throw e;
        }

        //negative pass
        if(this.negate) {
            context.negate = true;//because .fail will set negate
            context.params.details = "false negative fail";
            context.fail();
        }

        //positive pass
        if(!this.params.operator) this.params = context.params;//shortcut
        this.obj = context.obj;
        this.negate = false;
        return this;
    };

    Object.defineProperty(Assertion.prototype, name, prop);
};

assertion.js中的add方法在Assertion的原型鏈中添加自定義命名的方法,從而讓我們能夠打包一些判斷的方法來進(jìn)行調(diào)用,不需要重復(fù)進(jìn)行代碼的編寫。該方法具體的使用方式我們在后面對擴(kuò)展進(jìn)行講解時將會提到。

Assertion.addChain = function(name, onCall) {
    onCall = onCall || function() {
        };
    Object.defineProperty(Assertion.prototype, name, {
        get: function() {
            onCall();
            return this;
        },
        enumerable: true
    });
};

addChain方法添加屬性到原型鏈中,該屬性在調(diào)用方法后返回調(diào)用者本身。該方法在should.js的鏈?zhǔn)秸{(diào)用中起著重要的作用。

同時,Assertion類還支持別名功能,alias方法使用Object對象的getOwnPropertyDescriptor方法來對屬性是否存在進(jìn)行判斷,并調(diào)用defineProperty進(jìn)行賦值。

Assertion類在原型鏈中定義了assert方法,用來對各級限制條件進(jìn)行判斷。assert方法與普通方法不同,它并未采用參數(shù)來進(jìn)行一些參數(shù)的傳遞,而是通過assert方法所在的Assertion對象的params屬性來進(jìn)行參數(shù)的傳遞。因?yàn)樵?b>Assertion對象中存儲了相關(guān)的信息,使用這個方法來進(jìn)行參數(shù)傳遞方便在各級中assert函數(shù)的調(diào)用方便。具體使用方法我們將在擴(kuò)展的分析時提到。

assert: function(expr) {
    if(expr) return this;

    var params = this.params;

    if("obj" in params && !("actual" in params)) {
        params.actual = params.obj;
    } else if(!("obj" in params) && !("actual" in params)) {
        params.actual = this.obj;
    }

    params.stackStartFunction = params.stackStartFunction || this.assert;
    params.negate = this.negate;

    params.assertion = this;

    throw new AssertionError(params);
}

Assertion類也定義了一個fail方法能夠讓用戶直接調(diào)用從而拋出一個Assertion的Error。

fail: function() {
    return this.assert(false);
}
assertion-error.js

在此文件中,定義了assertion中拋出來的錯誤,同時在其中定義了一些信息存儲的函數(shù)例如messagedetail等,能夠讓錯誤在被捕獲的時候帶上一些特定的信息從而方便進(jìn)行判斷與處理。由于實(shí)現(xiàn)較為簡單,因此在此就不貼出代碼,需要了解的人可以自己去查閱should.js的源碼。

ext/bool.js

下面簡單介紹一個Assertion的擴(kuò)展的工作方式。讓我們能夠?qū)hould.js的工作原理有一個更加深刻的理解。

module.exports = function(should, Assertion) {
    Assertion.add("true", function() {
        this.is.exactly(true);
    });
    
    Assertion.alias("true", "True");

    Assertion.add("false", function() {
        this.is.exactly(false);
    });
    Assertion.alias("false", "False");

    Assertion.add("ok", function() {
        this.params = {operator: "to be truthy"};

        this.assert(this.obj);
    });
};

//should.js
should.use = function (f) {
    f(should, should.Assertion);
    return this;
};

//use
"1"should.be.true();

通過上面的擴(kuò)展模塊代碼以及should.js文件中的use函數(shù),我們可以發(fā)現(xiàn),use函數(shù)向擴(kuò)展模塊傳入了should方法和Assertion構(gòu)造函數(shù)。在bool.js這個擴(kuò)展模塊中,它通過調(diào)用Assertion對象上的add函數(shù)來添加新的判斷方式,并且通過params參數(shù)來告訴Assertion對象如果判斷失敗應(yīng)該如何提示用戶。

感想 should.js如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用?

Assertion類中,有一個addChain方法,該方法為某些屬性定義了一些在getter函數(shù)中調(diào)用的操作方法,并且返回對象本身。通過這個方法,在ext/chain.js中,它為should.js中常見的語義詞添加了屬性,并通過返回對象本身來達(dá)到鏈?zhǔn)秸{(diào)用的Assertion對象傳遞。

["an", "of", "a", "and", "be", "has", "have", "with", "is", "which", "the", "it"].forEach(function(name) {
    Assertion.addChain(name);
});

以下兩段代碼在結(jié)果上是一模一樣的效果:

"1".shoud.be.a.Number();
"1".should.be.be.be.be.a.a.a.a.Number();
should.js的實(shí)現(xiàn)方式有哪些值得借鑒的地方?

should.js中,通過將一些語義詞添加為屬性值并返回Assertion對象本身,因此有效解決了鏈?zhǔn)秸{(diào)用的問題。

通過Asseriton對象的屬性來進(jìn)行參數(shù)的傳遞,而不是通過函數(shù)參數(shù),從而有效避免了函數(shù)調(diào)用時參數(shù)的傳遞問題以及多層調(diào)用時結(jié)構(gòu)的復(fù)雜。

should.js通過擴(kuò)展的方式來添加其判斷的函數(shù),保證了良好的擴(kuò)展性,避免了代碼耦合在一起,通過也為其他人編寫更多的擴(kuò)展代碼提供了接口。

should.js通過extend方法,讓should(obj)obj.should兩種方式達(dá)到了相同的效果。通過在defineProperty中定義should屬性并且在回調(diào)函數(shù)中用should(obj)的方式來獲取obj對象。

通過拋出錯誤而不是返回布爾值的方式來通知用戶,能夠更加明顯的通知用戶,也方便向上拋出異常進(jìn)行傳遞。

總結(jié)

總的來說,should.js是一個比較小而精的測試框架,他能夠滿足在開發(fā)過程中所需要的大部分測試場景,同時也支持自己編寫擴(kuò)展來強(qiáng)化它的功能。在設(shè)計(jì)上,這個框架使用了不少巧妙的方法,避免了一些復(fù)雜的鏈?zhǔn)秸{(diào)用與參數(shù)傳遞等問題,而且結(jié)構(gòu)清晰,比較適合進(jìn)行閱讀與學(xué)習(xí)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87723.html

相關(guān)文章

  • 前端單元測試初探

    摘要:本文只討論單測的范疇,對集成測試有興趣的話,可以看下的集成測試代碼。前端單測現(xiàn)狀測試本質(zhì)上就是假定一個輸入,然后判斷得到預(yù)期的輸出。 原文發(fā)于我的博客:https://github.com/hwen/blogS... 要不要寫單測? 關(guān)于這個 cnode 上就有個很有意思的討論 做個調(diào)查,你的 Node 應(yīng)用有寫單測嗎? 看完這個應(yīng)該會有結(jié)論?如果沒有,就回帖跟別人探討下~ 測試 測試...

    isLishude 評論0 收藏0
  • 單元測試學(xué)習(xí)總結(jié)

    摘要:通過添加一個回調(diào)函數(shù)通常命名為給方法,就會知道,它應(yīng)該等這個函數(shù)被調(diào)用的時候才能完成測試。此外提供了一些鉤子函數(shù)和。這些鉤子函數(shù)可以用于設(shè)置測試的先決條件或者對測試進(jìn)行清理。鉤子函數(shù)會按照它們被定義的順序運(yùn)行。 Mocha 的安裝和使用 1. 安裝 使用npm全局安裝: npm install -g mocha 安裝Mocha >= v3.0.0,npm的版本應(yīng)該>=v1.4...

    netScorpion 評論0 收藏0
  • 聊一聊前端自動化測試

    摘要:在真正寫了一段時間的基礎(chǔ)組件和基礎(chǔ)工具后,才發(fā)現(xiàn)自動化測試有很多好處。有了自動化測試,開發(fā)者會更加信任自己的代碼。由于維護(hù)測試用例也是一大筆開銷畢竟沒有多少測試會專門幫前端寫業(yè)務(wù)測試用例,而前端使用的流程自動化工具更是沒有測試參與了。 本文轉(zhuǎn)載自 天貓前端博客,更多精彩文章請進(jìn)入天貓前端博客查看 前言 為何要測試 以前不喜歡寫測試,主要是覺得編寫和維護(hù)測試用例非常的浪費(fèi)時間。在真正寫了...

    wthee 評論0 收藏0
  • Mocha中文文檔

    摘要:中文文檔這個是對文檔的翻譯,都是我一個字一個字敲出來的。任何鉤子函數(shù)在執(zhí)行的時候都可以傳遞一個可選的描述信息,可以更容易地準(zhǔn)確指出測試中的錯誤。不給測試用例傳遞一個回調(diào)函數(shù),就是被等待實(shí)現(xiàn)的測試用例,但同樣會在報(bào)告中體現(xiàn)出來。 mocha中文文檔 這個是對mocha文檔的翻譯,都是我一個字一個字敲出來的。水平有限,激情無限,歡迎大家批評指正。文檔我也放在了我的github上,后續(xù),我會...

    lentrue 評論0 收藏0
  • MEAN.js 文檔

    摘要:感謝使用框架本文檔涵蓋構(gòu)建應(yīng)用所需的基礎(chǔ)知識。用于數(shù)據(jù)校驗(yàn)的組件及相關(guān)文件在此目錄進(jìn)行管理。除了自定義中間件外,還是用了諸多第三方的中間件,它們是五測試我們使用組件對服務(wù)端代碼進(jìn)行測試。識別當(dāng)前導(dǎo)航從已有導(dǎo)航中刪除給定標(biāo)識的導(dǎo)航配置。 本文同步至個人博客 MEAN.js 文檔,轉(zhuǎn)載請注明出處。 Overview 感謝使用 MEAN.js 框架! 本文檔涵蓋構(gòu)建 MEAN 應(yīng)用所需的基礎(chǔ)...

    Hydrogen 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<