摘要:任何彈珠字符串的首字符永遠(yuǎn)都表示零幀?;镜膹椫檎Z(yǔ)法時(shí)間幀的時(shí)間段。完成表示成功完成。錯(cuò)誤終止的錯(cuò)誤。它是此的零幀,在前的所有幀都將是無(wú)效的。
羅里吧嗦的一些解釋
RxJS使用的越來(lái)越多,但發(fā)現(xiàn)很多開(kāi)發(fā)者都是使用最基礎(chǔ)的部分用來(lái)處理http請(qǐng)求,其實(shí)RxJS可以做的事情不僅僅是在對(duì)網(wǎng)絡(luò)資源處理過(guò)程中替代Promise,但如果按照一些已有的網(wǎng)絡(luò)博客和分享來(lái)看,對(duì)二者在實(shí)踐上的差異確實(shí)體現(xiàn)的不明顯,所以想從測(cè)試的角度,和大家一起理解RxJS,發(fā)現(xiàn)它更大的威力。
另外其實(shí)本人實(shí)際上是在網(wǎng)絡(luò)上自己學(xué)習(xí)過(guò)一些RxJS的基本概念和使用,并在項(xiàng)目上小小嘗試過(guò)RxJS,只是覺(jué)得嘗試的不夠徹底,建議看這篇文章的時(shí)候最好還是對(duì)RxJS的基本概念有一個(gè)大的了解。
此文作為對(duì)RxJS有了大概了解后,從另一個(gè)觀察角度去了解RxJS的一個(gè)分享。
測(cè)試,什么樣的測(cè)試?接觸過(guò)測(cè)試的人可能馬上會(huì)想知道,你說(shuō)的是什么測(cè)試?在測(cè)試金字塔的哪一層?可以TDD嗎?和我們之前了解的測(cè)試有什么特別不一樣的?
我說(shuō)的測(cè)試叫彈珠測(cè)試(Marble Tests),它屬于底層的單元測(cè)試級(jí)別,主要用于針對(duì)自定義操作符的測(cè)試,可以TDD,比較特別的算是它是基于DSL的,你必須了解它的DSL之后才能開(kāi)始寫(xiě)測(cè)試。
關(guān)于如何寫(xiě)彈珠測(cè)試,在官方github上面也有一些文檔可以參考,但不是特別詳細(xì),沒(méi)法像一個(gè)框架的quick start幫助大家起步。我會(huì)嘗試和大家一起動(dòng)手來(lái)寫(xiě)這些測(cè)試(從最基本的環(huán)境搭建開(kāi)始),不會(huì)步步到位,但是關(guān)鍵步驟都有。
看第一個(gè)測(cè)試?以下是官網(wǎng)隨便找的一個(gè)測(cè)試,一個(gè)簡(jiǎn)單的map你可以記住你看完這個(gè)測(cè)試的感受。
asDiagram("map(x => 10 * x)")("should map multiple values", function () { var a = cold("--1--2--3--|"); var asubs = "^ !"; var expected = "--x--y--z--|"; var r = a.map(function (x) { return 10 * x; }); expectObservable(r).toBe(expected, { x: 10, y: 20, z: 30 }); expectSubscriptions(a.subscriptions).toBe(asubs); });
我并不知道你的感受,我第一眼是有點(diǎn)懵的反正,原因也很簡(jiǎn)單為什么出現(xiàn) | ^ - 這些字符,它們?cè)谶@里是干什么的? 這個(gè)時(shí)候要放出DSL這個(gè)大招了。
學(xué)彈珠測(cè)試的DSL前面我們隨意找的一個(gè)測(cè)試,似乎并不符合測(cè)試語(yǔ)義化這一點(diǎn),其實(shí)是因?yàn)槲覀儧](méi)有理解它所使用的DSL,此處的DSL可以理解為編寫(xiě)彈珠測(cè)試的時(shí)候使用的一種特定的語(yǔ)言,是基于彈珠測(cè)試的上下文可以讓機(jī)器懂得你語(yǔ)義的一種語(yǔ)言。
我們需要簡(jiǎn)單介紹下彈珠測(cè)試所使用的DSL中的一些基本知識(shí)(此部分信息摘自cn.rx.js.org)
首先彈珠語(yǔ)法是用字符串表示隨“時(shí)間”流逝而發(fā)生的事件。任何彈珠字符串的首字符永遠(yuǎn)都表示“零幀”?!皫笔怯悬c(diǎn)類(lèi)似于虛擬毫秒的概念。
基本的彈珠語(yǔ)法
"-" 時(shí)間: 10“幀”的時(shí)間段。
"|" 完成: 表示 Observalbe 成功完成。這是 Observable 生產(chǎn)者所發(fā)出的 complete() 信號(hào)。
"#" 錯(cuò)誤: 終止 Observable 的錯(cuò)誤。 這是 Observable 生產(chǎn)者所發(fā)出的 error() 信號(hào)。
"a" 任意字符: 所有其他字符表示由 Observalbe 生產(chǎn)者所發(fā)出的 next() 信號(hào)的值。
"()" 同步分組: 當(dāng)多個(gè)事件需要在同一幀中同步地發(fā)出,用圓括號(hào)來(lái)將這些事件聚集在一起。你可以以這種形式來(lái)聚合值、完成或錯(cuò)誤。 起始 ( 的位置決定了值發(fā)出的時(shí)間。
"^" 訂閱時(shí)間點(diǎn): (只適用于熱的 Observabe) 顯示測(cè)試 Observable 訂閱熱的 Observable 的點(diǎn)。它是此 Observable 的“零幀”,在 ^ 前的所有幀都將是無(wú)效的。
Subscription 的彈珠語(yǔ)法
"-" 時(shí)間: 10“幀”的時(shí)間段。
"^" 訂閱時(shí)間點(diǎn): 顯示訂閱發(fā)生的時(shí)間點(diǎn)。
"!" 取消訂閱時(shí)間點(diǎn): 顯示取消訂閱發(fā)生的時(shí)間點(diǎn)。
所以我們嘗試逐行理解下前面出現(xiàn)的測(cè)試
asDiagram("map(x => 10 * x)")("should map multiple values", function () { *** });
asDiagram是指基于測(cè)試生成 PNG 彈珠圖,生成彈珠圖的原理是根據(jù)一些結(jié)構(gòu)化的信息,加上一些如imagemagick的庫(kù),就可以生成如下的圖了,更多的操作符對(duì)應(yīng)的彈珠圖例子可以再rxmarbles.com找到。
var a = cold("--1--2--3--|"); var asubs = "^ !"; var expected = "--x--y--z--|"; var r = a.map(function (x) { return 10 * x; }); expectObservable(r).toBe(expected, { x: 10, y: 20, z: 30 }); expectSubscriptions(a.subscriptions).toBe(asubs);
這個(gè)測(cè)試的步驟是這樣的
創(chuàng)建一個(gè) Observable a,a在第30幀傳入1,第60幀傳入2,第90幀傳入3,第120幀complete。
對(duì)a進(jìn)行map操作的方法r,r將a中的每個(gè)值變?yōu)樵瓉?lái)的10倍
期待對(duì)a的進(jìn)行方法r的操作后,在第30幀收到10,第60幀收到20,第90幀收到30,第120幀結(jié)束
期待對(duì)a的訂閱在第10幀開(kāi)始,在第120幀結(jié)束
自己搭建環(huán)境?剛剛是我們用官網(wǎng)的例子結(jié)合一些輔助網(wǎng)站的資料,對(duì)彈珠測(cè)試進(jìn)行的簡(jiǎn)單的了解,下面我們開(kāi)始自己搭建一個(gè)可以自己寫(xiě)彈珠測(cè)試、運(yùn)行測(cè)試的環(huán)境。
我們先使用和官網(wǎng)一樣的第三方依賴(lài)創(chuàng)建環(huán)境,等我們慢慢熟悉這套之后,再換用其他第三方的依賴(lài)搭建環(huán)境。
ready go!
首先我們創(chuàng)建一個(gè)ts項(xiàng)目(最近ts寫(xiě)多了),并使用yarn安裝基本的測(cè)試依賴(lài)。
"dependencies": { "@types/chai": "^4.0.10", "@types/mocha": "^2.2.45", "chai": "^4.1.2", "mocha": "^4.0.1", "rxjs": "^5.5.6", "ts-node": "^4.1.0", "typescript": "^2.6.2" }, "scripts": { "test": "TS_NODE_FAST=true mocha --compilers ts:ts-node/register --opts spec/support/coverage.opts "specs/**/*.spec.ts"" }
然后我依樣畫(huà)瓢的把對(duì)TestScheduler的包裝方法copy了下,中間遇到一些寫(xiě)法不一樣的部分稍作調(diào)整。
import { TestScheduler, Observable } from "rxjs"; import { SubscriptionLog } from "rxjs/src/testing/SubscriptionLog"; import { ColdObservable } from "rxjs/src/testing/ColdObservable"; import { HotObservable } from "rxjs/src/testing/HotObservable"; export type observableToBeFn = (marbles: string, values?: any, errorValue?: any) => void; export type subscriptionLogsToBeFn = (marbles: string | string[]) => void; const testScheduler = new TestScheduler(null); export function hot(marbles: string, values?: any, error?: any): HotObservable{ return testScheduler.createHotObservable.apply(testScheduler, arguments); } export function cold(marbles: string, values?: any, error?: any): ColdObservable { return testScheduler.createColdObservable.apply(testScheduler, arguments); } export function expectObservable(observable: Observable , unsubscriptionMarbles: string = null): ({ toBe:observableToBeFn }) { return testScheduler.expectObservable.apply(testScheduler, arguments); } export function expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]): ({ toBe: subscriptionLogsToBeFn }) { return testScheduler.expectSubscriptions.apply(testScheduler, arguments); } export function time(marbles: string): number { return testScheduler.createTime.apply(testScheduler, arguments); }
這樣基本的hot cold方法就可以使用啦!
下一篇 Fancy的彈珠圖彈珠測(cè)試之所以能稱(chēng)之為彈珠測(cè)試,從字面意思上很容易猜測(cè)和彈珠圖相關(guān)。
我們已經(jīng)有一個(gè)基本的測(cè)試了,下一篇我們開(kāi)始把它變成彈珠圖吧。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90459.html
摘要:使用的操作符這條從左到右的橫線代表經(jīng)過(guò)操作符轉(zhuǎn)換后的輸出流。返回值通過(guò)判定函數(shù)檢測(cè)的值組成的流。返回值持續(xù)發(fā)出輸入流上的值,直到通知流上發(fā)出值為止。 上期介紹過(guò)了rxjs中的三大件,Observable,subscription,subject,但是在開(kāi)發(fā)過(guò)程我們最常接觸到的東西非操作符莫屬。比如上期代碼中曾出現(xiàn)過(guò)的from就是一個(gè)操作符。rxjs中的操作符大致上可以分為幾類(lèi),創(chuàng)建類(lèi),...
摘要:技術(shù)積累經(jīng)過(guò)社區(qū)的努力學(xué)習(xí)資料還是很多的,官方中文文檔就已經(jīng)很不錯(cuò),不過(guò)我們先從天精通初步感受一下然后配合一些中文文檔來(lái)補(bǔ)充知識(shí)點(diǎn),最后再根據(jù)官方文檔來(lái)校驗(yàn)整個(gè)知識(shí)體系。資料學(xué)習(xí)操作符的時(shí)候可以對(duì)照彈珠圖的交互彈珠圖的中文版中文文檔 前言 最近準(zhǔn)備畢設(shè),技術(shù)選型的時(shí)候因?yàn)楣δ艿囊恍┬枨鬁?zhǔn)備將RxJs融入到項(xiàng)目中,考慮RxJs的時(shí)候因?yàn)橹暗募夹g(shù)棧還猶豫了一下,查了一些資料以及粗略瀏覽了...
摘要:仿宋可以把想像成一個(gè)可以發(fā)射事件的庫(kù)。在中用來(lái)處理異步事件的核心概念包括代表了未來(lái)可能會(huì)產(chǎn)生的一系列的值或事件的集合回調(diào)函數(shù)的集合,它知道如何去處理上產(chǎn)生的值或者事件,當(dāng)然也包括異常。 又一年要過(guò)去了,回顧2017,rxjs始終是我在項(xiàng)目里使用最頻繁的庫(kù),在我看來(lái),它是一個(gè)非常優(yōu)秀的數(shù)據(jù)處理工具。年初的時(shí)候就計(jì)劃寫(xiě)點(diǎn)什么,礙于目前公司的項(xiàng)目實(shí)在抽不出時(shí)間,這一拖就到了年底。臨近新年,總...
摘要:由于技術(shù)棧的學(xué)習(xí),筆者需要在原來(lái)函數(shù)式編程知識(shí)的基礎(chǔ)上,學(xué)習(xí)的使用。筆者在社區(qū)發(fā)現(xiàn)了一個(gè)非常高質(zhì)量的響應(yīng)式編程系列教程共篇,從基礎(chǔ)概念到實(shí)際應(yīng)用講解的非常詳細(xì),有大量直觀的大理石圖來(lái)輔助理解流的處理,對(duì)培養(yǎng)響應(yīng)式編程的思維方式有很大幫助。 showImg(https://segmentfault.com/img/bVus8n); [TOC] 一. 響應(yīng)式編程 響應(yīng)式編程,也稱(chēng)為流式編程...
閱讀 1096·2021-11-16 11:44
閱讀 1377·2019-08-30 13:12
閱讀 2418·2019-08-29 16:05
閱讀 3082·2019-08-28 18:29
閱讀 918·2019-08-26 13:41
閱讀 3238·2019-08-26 13:34
閱讀 2607·2019-08-26 10:35
閱讀 942·2019-08-26 10:28