RxJS 為RxJS貢獻(xiàn)測(cè)試

2020-09-25 17:19 更新

本文檔涉及針對(duì) RxJS 存儲(chǔ)庫(kù)內(nèi)部的編寫大理石測(cè)試,適用于希望幫助維護(hù) RxJS 存儲(chǔ)庫(kù)的任何人。 相反,RxJS的用戶應(yīng)查看為應(yīng)用編寫大理石測(cè)試的指南。主要區(qū)別在于,在手動(dòng)使用和使用 testScheduler.run(callback)幫助程序之間,TestScheduler 的行為有所不同。

“大理石測(cè)試”是使用稱為的專用 VirtualScheduler 的測(cè)試 TestScheduler。它們使我們能夠以同步且可靠的方式測(cè)試異步操作?!按罄硎?hào)”已經(jīng)被 @jhusain,@headinthebox,@mattpodwysocki 和 @andrestaltz 等人的許多教義和文檔改編而成 。實(shí)際上,AndréStaltz 最初將其推薦為創(chuàng)建單元測(cè)試的 DSL,此后被更改和采用。

也可以看看

基本方法

單元測(cè)試中已添加了輔助方法,以使創(chuàng)建測(cè)試更加容易。

  • hot(marbles: string, values?: object, error?: any)-創(chuàng)建一個(gè)“熱”的可觀察對(duì)象(主題),當(dāng)測(cè)試開始時(shí)其行為就好像已經(jīng)在“運(yùn)行”。一個(gè)有趣的區(qū)別是,hot大理石允許 ^角色發(fā)出“零幀”位置的信號(hào)。這就是開始訂閱要測(cè)試的可觀察對(duì)象的時(shí)間。
  • cold(marbles: string, values?: object, error?: any) -創(chuàng)建一個(gè)“冷”可觀察的對(duì)象,其可在測(cè)試開始時(shí)開始訂閱。
  • expectObservable(actual: Observable<T>).toBe(marbles: string, values?: object, error?: any)-計(jì)劃何時(shí)刷新 TestScheduler 的斷言。TestScheduler 將在您的茉莉花it塊的結(jié)尾自動(dòng)刷新。
  • expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]).toBe(subscriptionMarbles: string)-就像 expectObservable 為 testScheduler 刷新的時(shí)間安排斷言一樣。雙方cold()hot()返回一個(gè)可觀察與屬性 subscriptions 類型 SubscriptionLog[]。給 subscriptions 作為參數(shù)傳遞給 expectSubscriptions 斷言它是否匹配 subscriptionsMarbles 在給定的大理石圖 toBe()。訂閱大理石圖與可觀察大理石圖略有不同。在下面閱讀更多內(nèi)容。

符合人體工程學(xué)的默認(rèn)值 hotcold

hotcold 方法中,除非將 values 參數(shù)傳遞給方法,否則在大理石圖中指定的值字符將作為字符串發(fā)出。為此:

hot('--a--b')將發(fā)出"a","b"

hot('--a--b', { a: 1, b: 2 })將發(fā)出 12。

同樣,未指定的錯(cuò)誤將默認(rèn)為string "error",因此:

hot('---#')將發(fā)出錯(cuò)誤,"error"

hot('---#', null, new SpecialError('test'))` 會(huì)發(fā)出 `new SpecialError('test')

大理石語(yǔ)法

大理石語(yǔ)法是一個(gè)字符串,表示隨著時(shí)間發(fā)生的事件。任何大理石弦的第一個(gè)字符

始終代表“零幀”?!皫痹谀撤N程度上類似于虛擬毫秒。

  • "-" 時(shí)間:10個(gè)“幀”的時(shí)間流逝。
  • "|"complete:成功完成一個(gè)可觀察的對(duì)象。這是可觀察到的生產(chǎn)者信號(hào) complete()
  • "#"錯(cuò)誤:終止可觀察值的錯(cuò)誤。這是可觀察到的生產(chǎn)者信號(hào) error()
  • "a" 任何字符:所有其他字符表示生產(chǎn)者信令發(fā)出的值 next()
  • "()"同步分組:當(dāng)多個(gè)事件需要同步在同一幀中時(shí),使用括號(hào)將這些事件分組。您可以通過(guò)這種方式將下一個(gè)值,完成或錯(cuò)誤分組。初始位置(確定了其值的發(fā)出時(shí)間。
  • "^"訂閱點(diǎn):(僅熱觀測(cè)值)顯示測(cè)試的可觀測(cè)物將訂閱到該熱觀測(cè)值的點(diǎn)。這是可觀察到的“零幀”,在之前的每一幀^都會(huì)為負(fù)。

例子

'-''------':等效于 Observable.never(),或從不發(fā)出或完成的可觀察物

|`: 相當(dāng)于 `Observable.empty()
#`: 相當(dāng)于 `Observable.throw()

'--a--':一個(gè)可觀察的對(duì)象,等待 20個(gè)“幀”,發(fā)出值a,然后永不完成。

'--a--b--|'`:在第20幀發(fā)射`a`,在第50幀發(fā)射`b`和在第80幀上,`complete
'--a--b--#'`:在第20幀發(fā)射`a`,在第50幀發(fā)射`b`和在第80幀上,`error

'-a-^-b--|':在熱觀測(cè)下,在第-20幀發(fā)射a,然后在第 20幀發(fā)射b,在第 50 幀上發(fā)射complete

'--(abc)-|'`:上框架20,發(fā)射`a`,`b`以及`c`,然后在框架80`complete

'-----(a|)':在第50幀上,發(fā)射acomplete

訂閱大理石語(yǔ)法

訂閱大理石語(yǔ)法與常規(guī)大理石語(yǔ)法略有不同。它表示訂閱,并且隨著時(shí)間的推移發(fā)生取消訂閱點(diǎn)。該圖中不應(yīng)顯示其他類型的事件。

  • "-" 時(shí)間:段落的10個(gè)“幀”。
  • "^" 訂閱點(diǎn):顯示訂閱發(fā)生的時(shí)間點(diǎn)。
  • "!" 取消訂閱點(diǎn):顯示取消訂閱的時(shí)間點(diǎn)。

訂購(gòu)大理石圖中,最多 應(yīng)有一個(gè)^點(diǎn),并且最多 應(yīng)有一個(gè)!點(diǎn)。除此之外,該-角色是訂閱大理石圖中唯一允許使用的角色。

例子

'-''------':從未發(fā)生過(guò)訂閱。

'--^--':訂閱發(fā)生在 20 個(gè)“幀”的時(shí)間之后,并且該訂閱并未取消訂閱。

'--^--!-':在第 20 幀發(fā)生了訂閱,而在第50幀未訂閱。

測(cè)試的解剖

基本測(cè)試可能如下所示:

const e1 = hot('----a--^--b-------c--|');
const e2 = hot(  '---d-^--e---------f-----|');
const expected =      '---(be)----c-f-----|';


expectObservable(e1.merge(e2)).toBe(expected);

  • 可觀察對(duì)象的^字符 hot應(yīng)始終對(duì)齊。
  • 第一個(gè)字符cold 觀測(cè)值或預(yù)期的觀測(cè)應(yīng)始終被相互對(duì)準(zhǔn),并與^熱觀測(cè)的。
  • 如果可以,請(qǐng)使用默認(rèn)發(fā)射值。指定 values 何時(shí)需要。

具有指定值的測(cè)試示例:

const values = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  x: 1 + 3, // a + c
  y: 2 + 4, // b + d
}
const e1 =    hot('---a---b---|', values);
const e2 =    hot('-----c---d---|', values);
const expected =  '-----x---y---|';


expectObservable(e1.zip(e2, function(x, y) { return x + y; }))
  .toBe(expected, values);

  • 使用相同的散列查找所有值,這可確保多次使用相同字符具有相同值。
  • 對(duì)于它們代表的結(jié)果,使結(jié)果值盡可能地明顯,畢竟這是測(cè)試,我們要的是清晰度而不是效率,因此 x: 1 + 3, // a + c要好得多 x: 4。前者說(shuō)明了為什么是 4,而后者則沒有。

一個(gè)帶有訂閱斷言的測(cè)試示例:

const x = cold(        '--a---b---c--|');
const xsubs =    '------^-------!';
const y = cold(                '---d--e---f---|');
const ysubs =    '--------------^-------------!';
const e1 = hot(  '------x-------y------|', { x: x, y: y });
const expected = '--------a---b----d--e---f---|';


expectObservable(e1.switch()).toBe(expected);
expectSubscriptions(x.subscriptions).toBe(xsubs);
expectSubscriptions(y.subscriptions).toBe(ysubs);

  • 將和的開頭 xsubsysubs圖表對(duì)齊 expected。
  • 請(qǐng)注意,如何 x 同時(shí)取消 e1 釋放可觀測(cè)的冷信號(hào) y。

在大多數(shù)測(cè)試中,無(wú)需測(cè)試訂閱點(diǎn)和取消訂閱點(diǎn),因?yàn)閺?expected 圖中可以明顯看出或暗示該點(diǎn)。在那些情況下,請(qǐng)勿編寫訂閱聲明。在具有多個(gè)內(nèi)部訂閱者或具有多個(gè)訂閱者的冷可觀察性的測(cè)試用例中,這些訂閱斷言可能很有用。

從測(cè)試生成 PNG 大理石圖

通常,Jasmine 中的每個(gè)測(cè)試用例都寫為it('should do something', function () { /* ... */ })。要標(biāo)記用于生成 PNG 圖的測(cè)試用例,必須使用如下 asDiagram(label) 函數(shù):

it.asDiagram(operatorLabel)('should do something', function () {
});

例如,使用 zip,我們將編寫

it.asDiagram('zip')('should zip by concatenating', function () {
  const e1 =    hot('---a---b---|');
  const e2 =    hot('-----c---d---|');
  const expected =  '-----x---y---|';
  const values = { x: 'ac', y: 'bd' };


  const result = e1.zip(e2, function(x, y) { return String(x) + String(y); });


  expectObservable(result).toBe(expected, values);
});

然后,在運(yùn)行時(shí) npm run tests2png,將分析該測(cè)試用例,并在該文件夾中創(chuàng)建一個(gè) PNG 文件 zip.png(由決定的文件名 ${operatorLabel}.pngimg/

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)