摘要:任何彈珠字符串的首字符永遠都表示零幀。基本的彈珠語法時間幀的時間段。完成表示成功完成。錯誤終止的錯誤。它是此的零幀,在前的所有幀都將是無效的。
羅里吧嗦的一些解釋
RxJS使用的越來越多,但發現很多開發者都是使用最基礎的部分用來處理http請求,其實RxJS可以做的事情不僅僅是在對網絡資源處理過程中替代Promise,但如果按照一些已有的網絡博客和分享來看,對二者在實踐上的差異確實體現的不明顯,所以想從測試的角度,和大家一起理解RxJS,發現它更大的威力。
另外其實本人實際上是在網絡上自己學習過一些RxJS的基本概念和使用,并在項目上小小嘗試過RxJS,只是覺得嘗試的不夠徹底,建議看這篇文章的時候最好還是對RxJS的基本概念有一個大的了解。
此文作為對RxJS有了大概了解后,從另一個觀察角度去了解RxJS的一個分享。
測試,什么樣的測試?接觸過測試的人可能馬上會想知道,你說的是什么測試?在測試金字塔的哪一層?可以TDD嗎?和我們之前了解的測試有什么特別不一樣的?
我說的測試叫彈珠測試(Marble Tests),它屬于底層的單元測試級別,主要用于針對自定義操作符的測試,可以TDD,比較特別的算是它是基于DSL的,你必須了解它的DSL之后才能開始寫測試。
關于如何寫彈珠測試,在官方github上面也有一些文檔可以參考,但不是特別詳細,沒法像一個框架的quick start幫助大家起步。我會嘗試和大家一起動手來寫這些測試(從最基本的環境搭建開始),不會步步到位,但是關鍵步驟都有。
看第一個測試?以下是官網隨便找的一個測試,一個簡單的map你可以記住你看完這個測試的感受。
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); });
我并不知道你的感受,我第一眼是有點懵的反正,原因也很簡單為什么出現 | ^ - 這些字符,它們在這里是干什么的? 這個時候要放出DSL這個大招了。
學彈珠測試的DSL前面我們隨意找的一個測試,似乎并不符合測試語義化這一點,其實是因為我們沒有理解它所使用的DSL,此處的DSL可以理解為編寫彈珠測試的時候使用的一種特定的語言,是基于彈珠測試的上下文可以讓機器懂得你語義的一種語言。
我們需要簡單介紹下彈珠測試所使用的DSL中的一些基本知識(此部分信息摘自cn.rx.js.org)
首先彈珠語法是用字符串表示隨“時間”流逝而發生的事件。任何彈珠字符串的首字符永遠都表示“零幀”。“幀”是有點類似于虛擬毫秒的概念。
基本的彈珠語法
"-" 時間: 10“幀”的時間段。
"|" 完成: 表示 Observalbe 成功完成。這是 Observable 生產者所發出的 complete() 信號。
"#" 錯誤: 終止 Observable 的錯誤。 這是 Observable 生產者所發出的 error() 信號。
"a" 任意字符: 所有其他字符表示由 Observalbe 生產者所發出的 next() 信號的值。
"()" 同步分組: 當多個事件需要在同一幀中同步地發出,用圓括號來將這些事件聚集在一起。你可以以這種形式來聚合值、完成或錯誤。 起始 ( 的位置決定了值發出的時間。
"^" 訂閱時間點: (只適用于熱的 Observabe) 顯示測試 Observable 訂閱熱的 Observable 的點。它是此 Observable 的“零幀”,在 ^ 前的所有幀都將是無效的。
Subscription 的彈珠語法
"-" 時間: 10“幀”的時間段。
"^" 訂閱時間點: 顯示訂閱發生的時間點。
"!" 取消訂閱時間點: 顯示取消訂閱發生的時間點。
所以我們嘗試逐行理解下前面出現的測試
asDiagram("map(x => 10 * x)")("should map multiple values", function () { *** });
asDiagram是指基于測試生成 PNG 彈珠圖,生成彈珠圖的原理是根據一些結構化的信息,加上一些如imagemagick的庫,就可以生成如下的圖了,更多的操作符對應的彈珠圖例子可以再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);
這個測試的步驟是這樣的
創建一個 Observable a,a在第30幀傳入1,第60幀傳入2,第90幀傳入3,第120幀complete。
對a進行map操作的方法r,r將a中的每個值變為原來的10倍
期待對a的進行方法r的操作后,在第30幀收到10,第60幀收到20,第90幀收到30,第120幀結束
期待對a的訂閱在第10幀開始,在第120幀結束
自己搭建環境?剛剛是我們用官網的例子結合一些輔助網站的資料,對彈珠測試進行的簡單的了解,下面我們開始自己搭建一個可以自己寫彈珠測試、運行測試的環境。
我們先使用和官網一樣的第三方依賴創建環境,等我們慢慢熟悉這套之后,再換用其他第三方的依賴搭建環境。
ready go!
首先我們創建一個ts項目(最近ts寫多了),并使用yarn安裝基本的測試依賴。
"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"" }
然后我依樣畫瓢的把對TestScheduler的包裝方法copy了下,中間遇到一些寫法不一樣的部分稍作調整。
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的彈珠圖彈珠測試之所以能稱之為彈珠測試,從字面意思上很容易猜測和彈珠圖相關。
我們已經有一個基本的測試了,下一篇我們開始把它變成彈珠圖吧。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90459.html
摘要:使用的操作符這條從左到右的橫線代表經過操作符轉換后的輸出流。返回值通過判定函數檢測的值組成的流。返回值持續發出輸入流上的值,直到通知流上發出值為止。 上期介紹過了rxjs中的三大件,Observable,subscription,subject,但是在開發過程我們最常接觸到的東西非操作符莫屬。比如上期代碼中曾出現過的from就是一個操作符。rxjs中的操作符大致上可以分為幾類,創建類,...
摘要:技術積累經過社區的努力學習資料還是很多的,官方中文文檔就已經很不錯,不過我們先從天精通初步感受一下然后配合一些中文文檔來補充知識點,最后再根據官方文檔來校驗整個知識體系。資料學習操作符的時候可以對照彈珠圖的交互彈珠圖的中文版中文文檔 前言 最近準備畢設,技術選型的時候因為功能的一些需求準備將RxJs融入到項目中,考慮RxJs的時候因為之前的技術棧還猶豫了一下,查了一些資料以及粗略瀏覽了...
摘要:由于技術棧的學習,筆者需要在原來函數式編程知識的基礎上,學習的使用。筆者在社區發現了一個非常高質量的響應式編程系列教程共篇,從基礎概念到實際應用講解的非常詳細,有大量直觀的大理石圖來輔助理解流的處理,對培養響應式編程的思維方式有很大幫助。 showImg(https://segmentfault.com/img/bVus8n); [TOC] 一. 響應式編程 響應式編程,也稱為流式編程...
閱讀 1091·2021-11-16 11:44
閱讀 1376·2019-08-30 13:12
閱讀 2414·2019-08-29 16:05
閱讀 3080·2019-08-28 18:29
閱讀 915·2019-08-26 13:41
閱讀 3236·2019-08-26 13:34
閱讀 2604·2019-08-26 10:35
閱讀 941·2019-08-26 10:28