2015-03-31 104 views
0

我想在同一時間建立和測試一個功能。測試是有道理的,我理論上喜歡它,但是當它歸結於它時,它總是背後的痛苦。測試承諾和同步功能,拋出錯誤

我有一個函數,將一個字符串時的東西都被打亂拋出錯誤,如果一切順利的話這將返回原來的text論證,因此一個truthy值,如果不應該由它無論是在或承諾被抓本身就是承諾。

這是測試/我真正想要做什麼(哪個不行)。

var main = require("./index.js") 
var Promise = require("bluebird") 
var mocha = require("mocha") 
var chai = require("chai") 
var chaiPromise = require("chai-as-promised") 
chai.use(chaiPromise) 

var shouldThrow = [ 
    "random", // invalid non-flag 
    "--random", // invalid flag 
    "--random string", //invalid flag 
    "--wallpaper", // invalid flag w/ match 
    "--notify", // invalid flag w/ match 
    "wallpaper", // valid non-flag missing option(s) image 
    "wallpaper image.jpg" // invalid flag value 
    "wallpaper http://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621", // invalid flag value 
    "wallpaper //cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag value 
    "wallpaper http://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag value 
    "wallpaper https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag value 
    "wallpaper https://cdn.example.com/s/files/1/0031/5352/files/holstee_logo_2.png?4803", // invalid flag value 
    "wallpaper https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue", // invalid flag value 
    "wallpaper https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().subtract(1, "month").format("YYYY-MM-DD-HH-mm"), // invalid flag value 
    "wallpaper https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().add(1, "month").format("YY-MM-DD-HH"), // invalid flag value 
    "wallpaper --image http://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621", // invalid flag value not https 
    "wallpaper --image //cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag no protocol 
    "wallpaper --image http://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag value not https 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/favicon.ico?12375621748379006621", // invalid flag value not valid image 
    "wallpaper --image https://cdn.example.com/s/files/1/0031/5352/files/holstee_logo_2.png?4803", // invalid flag image not found 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue", // invalid subflag queue missing value 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().subtract(1, "month").format("YYYY-MM-DD-HH-mm"), // invalid subflag queue date value is past 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().add(1, "month").format("YY-MM-DD-HH"), // invalid subflag queue date value format 
    "--wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621", //no action non-flag 
    "--wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().add(1, "month").format("YYYY-MM-DD-HH-mm"), //no action non-flag 
    "notify", // valid non-flag missing option(s) message, open 
    'notify --message "Hello world"', // valid flag missing params open 
    'notify --open "https://www.holstee.com"', // valid flag missing params message 
    'notify --message "Hello world" --open "http://www.holstee.com"', // invalid subflag value `open` should be https 
    'notify --message "Hello world" --open "https://www.holstee.com" --queue', // invalid subflag queue missing value 
    'notify --message "Hello world" --open "https://www.holstee.com" --queue '+moment().subtract(1, "month").format("YYYY-MM-DD-HH-mm"), // invalid subflag queue date value is past 
    'notify --message "Hello world" --open "https://www.holstee.com" --queue '+moment().add(1, "month").format("YY-MM-DD-HH"), // invalid subflag queue date value format 
    '--notify --message "Hello world" --open "https://www.holstee.com"', //no action non-flag 
    '--notify --message "Hello world" --open "https://www.holstee.com --queue "'+moment().add(1, "month").format("YYYY-MM-DD-HH-mm"), //no action non-flag 
] 

var shouldNotThrow = [ 
    'notify --message "Hello world" --open "https://www.holstee.com"', 
    'notify --message "Hello world" --open "https://www.holstee.com --queue "'+moment().add(1, "month").format("YYYY-MM-DD-HH-mm"), 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621", 
    "wallpaper --image https://cdn.shopify.com/s/files/1/0031/5352/t/28/assets/holstee-calendar-2015-03-flow-desktop.jpg?12375621748379006621 --queue "+moment().add(1, "month").format("YYYY-MM-DD-HH-mm"), 
] 

describe('Process Text', function(){ 
    return Promise.map(shouldThrow, function(option){ 
    it('throw error', function(){ 
     return main.processText(option).should.throw() 
    })  
    }) 
    return Promise.map(shouldNotThrow, function(option){ 
    it('throw error', function(){ 
     return main.processText(option).should.not.throw() 
    })  
    }) 
}) 

下面是我試圖測試的非工作*函數的快照。

main.processText = function(text){ 
    var args = minimist(text.split(" ")) 
    var actions = _.keys(actionsFlags) 
    var flags = _.chain(_.map(actionsFlags, _.keys)).flatten().uniq().value() 
    var extraUnparsed = _.extra(actions, args._) 
    var providedFlags = _.chain(args).keys().without("_").value() 
    var extraParsed = _.extra(flags, providedFlags) 
    var validActions = _.intersection(actions, args._) 
    var requiredFlags = _.mapObject(actionsFlags, function(flags){ 
    return _.filterObject(flags, function(flag){ 
     return flag 
    }) 
    }) 
    if(extraUnparsed.length) throw new Error("invalid unparsed argument(s): "+extraUnparsed.join(", ")) 
    if(extraParsed.length) throw new Error("invalid parsed argument(s): "+extraParsed.join(", ")) 
    if(validActions.length > 1) throw new Error("too many actions: "+validActions.join(", ")) 
    if(validActions.length == 0) throw new Error("no action: "+actions.join(", ")) 
    _.each(actions, function(action){ 
    var missingFlags = _.missing(_.keys(requiredFlags[action]), providedFlags) 
    var extraFlags = _.extra(_.keys(requiredFlags[action]), providedFlags) 
    if(_.contains(args._, action)){ 
     if(missingFlags.length) throw new Error(util.format("missing required flags for %s: %s", action, missingFlags.join(", "))) 
     if(extraFlags.length) throw new Error(util.format("extra flags for %s: %s", action, extraFlags.join(", "))) 
    } 
    }) 
    return text 
} 

注意它不是承諾,並且不返回任何承諾。我想要的驗證功能之一是檢查一個url是否響應200狀態碼,這將是一個request的承諾。如果我更新了這個函數,那麼所有的函數內容都需要嵌套在Promise.resolve(false).then()之內?也許這個承諾不應該在這個代碼塊中,並且所有的驗證操作都應該存在於其他地方?

我不知道我在做什麼,我有點沮喪。當然,我正在尋找一些金色子彈或任何能夠理解這一切的東西。

理想情況下,我可以使用一些關於如何測試這種功能的幫助。如果我稍後將其作爲承諾,我仍然希望所有測試都能正常工作。


下面是我所說的同步函數和承諾的一些示例代碼。

function syncFunction(value){ 
    if(!value) throw new Error("missing value") 
    return value 
} 

function asyncFunction(url){ 
    return requestPromise(url) 
} 

// Both of these will throw errors the same way they will be caught by the promise then you can use `.catch` (in bluebird). 

Promise.resolve(false).then(function(){ 
    return syncFunction() 
}) 

Promise.resolve(false).then(function(){ 
    return asyncFunction("http://404.com") 
}) 

我想這反映了我測試錯誤和判斷一件事情shouldshould not拋出一個錯誤,在我的測試方式。


我離開了承諾,它是一個同步功能,我正在測試這樣。

describe('Process Text', function(){ 
    _.each(shouldThrow, function(option){ 
    it('throw error ('+option+')', function(){ 
     expect(function(){ 
     main.textValidation(option) 
     }).to.throw() 
    }) 
    }) 
    _.each(shouldNotThrow, function(option){ 
    it('not throw error ('+option+')', function(){ 
     expect(function(){ 
     main.textValidation(option) 
     }).to.not.throw() 
    }) 
    }) 
}) 
+2

可以請你苗條這個問題的方式,一路下跌;變成一個更容易理解的(更少的邏輯),它表明了你所要問的基本問題?你有多個問題,我試圖找出如何解決這個有效的答案。現在最主要的是'Promise.each(shouldThrow,function(option){'沒有任何意義,'.each'函數接受函數迭代器的第一個參數,而不是字符串數組。這種方式只需幾行即可拋出/不拋出,並且還可以最小化您的實現邏輯,這將更容易幫助 – 2015-03-31 17:59:57

+0

偉大的反饋@JustinMaat!我只是尋找一種方法來異步循環數組字符串(使用'.map'而不是'.each',抱歉),那麼就可以決定一個承諾是否應該或者不應該爲給定的測試拋出一個錯誤。 – ThomasReggi 2015-03-31 18:56:05

+0

理想情況下,無論採用什麼方法,我都可以將它傳遞給一個同步函數,該函數可能會拋出錯誤或可能拋出錯誤的承諾,並且測試的界面也是相同的,因爲理想情況下它已經包含在承諾中了,被抓住。 – ThomasReggi 2015-03-31 18:57:56

回答