Slide 1

Slide 1 text

ই֜̿向瑽̀䌃介手 - RxJS Marble Testing

Slide 2

Slide 2 text

Observable 墋Օ

Slide 3

Slide 3 text

What is Observable ?

Slide 4

Slide 4 text

What is Observable ? Collection + Time

Slide 5

Slide 5 text

Observable 疰猟ฎӞ㮆ଧڜ牧
 愊ᶎጱزᔰ䨝褰茐碻樌വ蝑 What is Observable ?

Slide 6

Slide 6 text

var mouseMove = Observable .fromEvent(DOM, 'mousemove'); var subscription = mouseMove .subscribe(x !=> console.log(x)); subscription.unsubscribe(); Observable ୌ缏膏懪褂

Slide 7

Slide 7 text

Observable.of(2, 3, 4) Observable.from([2, 3, 4]) Observable.fromEvent(DOM, 'click') Observable.interval(1000) Observable.empty() Observable.never() Observable.throw() ୌ缏 Observable

Slide 8

Slide 8 text

var sub = Observable .from([1, 2, 3]) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) .subscribe({ next: x !=> console.log(x), error: err !=> {}, complete: () !=> {}, });

Slide 9

Slide 9 text

observable • Observable ጱᇔկ䋿ֺ • ࣁ๚ᤩ懪褂ԏ獮牧ݝฎ 㮆ᇔկ牧犋䨝蝑ڊزᔰ • ݢᤩ懪褂(subscribe) • ٍ磪ग़圵 operator var sub = Observable .from([1, 2, 3]) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) .subscribe({ next: x !=> console.log(x), error: err !=> {}, complete: () !=> {}, });

Slide 10

Slide 10 text

operator • Observable ጱොဩ • ݢ䌘زᔰ֢螀ᓒ蒂ቘ • ࿞螐ࢧ㯽Ӟ㮆碝ጱ observable var sub = Observable .from([1, 2, 3]) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) .subscribe({ next: x !=> console.log(x), error: err !=> {}, complete: () !=> {}, });

Slide 11

Slide 11 text

observer • አ㬵懪褂 observable ጱ ᇔկ • next 獢ୗӞਧᥝ磪牧
 error 膏 complete ݢ螡 䢔 var sub = Observable .from([1, 2, 3]) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) .subscribe({ next: x !=> console.log(x), error: err !=> {}, complete: () !=> {}, });

Slide 12

Slide 12 text

subscription • observable 懪褂盅ࢧ㯽 ጱᇔկ • ݢ犥ٌ犢懪㻌ݳ㬫 • ݢ೭㬵蝐懪 (unsubscribe) var sub = Observable .from([1, 2, 3]) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) .subscribe({ next: x !=> console.log(x), error: err !=> {}, complete: () !=> {}, });

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Marble Diagram --a--b--c--d--e|

Slide 15

Slide 15 text

Marble Diagram • - : Ӟੜྦྷ碻樌 (10 frames) • n(0-9/a-z): 蝑ڊጱزᔰ(next) • |: 蝑ڊ奾๳ (complete) • #: 蝑ڊ梊藮 (error) • (): ݶྍ蝑ڊ time ----0---1---2---3-- ----0---1---2---3| ----0---1---2---3--# (123|)

Slide 16

Slide 16 text

Observable.of(1, 2, 3) Observable.from([1, 2, 3]) (123|)

Slide 17

Slide 17 text

Observable.interval(10) -0123..

Slide 18

Slide 18 text

Observable .fromEvent(DOM, 'click') ---e--ee-e--e-...

Slide 19

Slide 19 text

Observable.interval(10) .take(3) .map(x !=> x + 1) .filter(x !=> x % 2 ##=== 0) -012.. -012| --2| -01(2|) -12(3|)

Slide 20

Slide 20 text

-a-bc-d--- • 10 frames 碻牧蝑ڊ a • 30 frames 碻牧蝑ڊ b • 40 frames 碻牧蝑ڊ c • 60 frames 碻牧蝑ڊ d • ䷱磪奾๳

Slide 21

Slide 21 text

--a-b-(c|) • 20 frames 碻牧蝑ڊ a • 40 frames 碻牧蝑ڊ b • 50 frames 碻牧蝑ڊ c ޾ complete

Slide 22

Slide 22 text

碪簁౯㮉ݢ犥አ marble diagram 㬵蔭纈 observable

Slide 23

Slide 23 text

ᮎ傶Ջ讕౯㮉犋Ԧ脀አ marble diagram 
 㬵䌃 observable ጱ㻌ز介手珌牫

Slide 24

Slide 24 text

Jerry Hong Front End Engineer | Website: blog.jerry-hong.com Facebook: J.H.MingChen

Slide 25

Slide 25 text

Testing Asynchronous Code is Hard

Slide 26

Slide 26 text

Testing Asynchronous Code is Hard • ࣁ秇硈覍ݶྍԪկ碻覍ଉ蕦褾牧ᘒӬ਻ฃڊ梊
 
 
 
 
 


Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Testing Asynchronous Code is Hard • ࣁ秇硈覍ݶྍԪկ碻覍ଉ蕦褾牧ᘒӬ਻ฃ䌃梊 • ইຎ౯㮉ጱ㻌ز介手๜蛪疰磪梊藮牧ᮎ㻌ز介手疰䷱磪఺嬝 • ؃ই౯㮉犋秇硈碻樌牧ፗ矑狶羊嘦介手牧㳷䨝蝨౮介手虋஑覍ଉ眸 • 疪ٌࣁ౯㮉ᥝ瞱媲瑿᪒介手碻

Slide 31

Slide 31 text

樄ত拻 Marble Testing ԏ獮牧౯㮉஠殾ض啻薹

Slide 32

Slide 32 text

Scheduler

Slide 33

Slide 33 text

Scheduler • Scheduler ฎአ㬵矒ګԪկ咳ኞጱ碻秚 • ইຎ Observable 磪戔ਧ Scheduler 䨝಩䁆ᤈ next, error, complete ጱ ොဩԻ妔 Scheduler 䁆ᤈ • Scheduler ٌ䋿疰蚤 setTimeout, setInterval 狶Ӟ䰬ጱԪ眐 • አ㬵戔ਧ礓կԪ眐ࣁ礓㮆碻樌讨藉咳

Slide 34

Slide 34 text

const sub = Scheduler.async.schedule(() !=> { console.log('123'); }, 100); sub.unsubscribe();

Slide 35

Slide 35 text

RxJS 5 - Scheduler • queue - 䨝ض಩ྯ稞ጱ犨率獊蟂硯ک queue 愊ٚ ݶྍ 蒂ቘ牐 • async - ݶ setInterval牧ಅ磪 timer-base observable ጱ毆戔独 • asap - ݶ setImmediate牧䨝穉 async ๅ盠 
 (Node 絑हӥ犋Ӟਧ牧ਥො෈կฎ梊ጱ牐ݝ磪ࣁ node v0.9 犥獮䨝ฎአ process.nextTick牧v0.9 ԏ盅᮷ฎአ setImmediate牐ԏ盅ݢ胼䨝狕ྋ) • animationFrame - ݶ requestAnimationFrame

Slide 36

Slide 36 text

Observable.of(0, 1, 2, Scheduler.async); Observable.from([0, 1, 2], Scheduler.async); Observable.interval(0, Scheduler.animationFrame); ֵአොୗ

Slide 37

Slide 37 text

TestScheduler

Slide 38

Slide 38 text

TestScheduler • TestScheduler ฎ䌕槹戔懯㬵狶介手አጱ Scheduler • TestScheduler 䨝秇硈碻樌牧㪔ୌ缏 100% ݢ᯿蕦ጱ介手 • ࢩ傶碻樌ฎ蒅硈ڊ㬵ጱ (virtual Time)牧ಅ磪ጱԪ眐䨝缏ܨ䁆ᤈ牧犋 襑ᥝ፥ጱ臺碻樌缛盃

Slide 39

Slide 39 text

let testScheduler = new TestScheduler( (actual, expected) !=> expect(actual).toEqual(expected) ); ୌ缏 Scheduler • 蝚螂 new 橕棎ਁ㬵ୌ缏 Scheduler • 㯽獈Ӟ㮆 callback牧㪔ࣁ callback Ӿ矑硩毆๗ጱ独 膏䋿褬ጱ独牧狶穉䌘 (deepEqual) • ဳ఺物ྯ㮆介手㻌زጱ testScheduler ஠殾ฎ加缏 ጱ䋿ֺ牧玽㳷䨝磪 side effect

Slide 40

Slide 40 text

it('of', () !=> { const actual = Observable .of('Jerry', testScheduler); testScheduler .expectObservable(actual) .toBe('(a|)', { a: 'Jerry' }); testScheduler.flush(); }); 介手 observable • ୌ缏 Observable 㪔戔 ਧ Scheduler 傶 testScheduler • አ testScheduler ጱ expectObservable 狶 䥁᥺ • 䁆ᤈ flush()

Slide 41

Slide 41 text

const obs = testScheduler .createColdObservable( '%%---u|', { u: 'http:%//google.com'} ); mock observable

Slide 42

Slide 42 text

const obs = testScheduler .createColdObservable( '%%---#', null, new Error('test') ); mock observable with error

Slide 43

Slide 43 text

const time = testScheduler .createTime('%%---|'); createTime

Slide 44

Slide 44 text

Demo

Slide 45

Slide 45 text

Redux-Observable

Slide 46

Slide 46 text

export const show = () !=> ({ type: 'SHOW' }); export const close = data !=> ({ type: 'CLOSE' }); export const delayEpic = action$ !=> action$.ofType('SHOW').delay(3000).map(x !=> close()); Action Creator & Epic

Slide 47

Slide 47 text

redux-observable-test-helper

Slide 48

Slide 48 text

import { createExpectedEpic, } from 'redux-observable-test-helper'; const expectedEpic = createExpectedEpic( (actual, expected) !=> { expect(actual).toEqual(expected); } );

Slide 49

Slide 49 text

export const show = () !=> ({ type: 'SHOW' }); export const close = () !=> ({ type: 'CLOSE' }); export const delayEpic = action$ !=> action$.ofType('SHOW') .delay(3000) .map(x !=> close()); test('test delay', () !=> { expectedEpic( delayEpic, { action: ['a', { a: show() }], expect: ['(--a', { a: close() }], }, mockDelay('(--|') ); }); reducer.js reducer.test.js

Slide 50

Slide 50 text

愆獅 • ኧ Promise 旉౮ጱ Observable 犋胼አ marble testing牧ݝ胼 mock ധ牧౲ฎፗ矑 subscribe 介手牐(#701) • ፓ獮蚤 timer ፘ橕ጱ operator (delay, throttle, debounce) 襑ᥝᛔᤈℂ Observable.prototype 狶 mock • 種㺔氂䨝ࣁ v5.5, 5.6 വڊ lettable 粬௔盅薹究 • redux-observable-test-helper 磪൉׀