AngularJSã¯ãææ°ã®Webéçºã«é¢ããŠã¯è¥ããŠãããã§ãã HTMLã®ã³ã³ãã€ã«ãšåæ¹åã®ããŒã¿ãã€ã³ãã£ã³ã°ã«å¯Ÿããç¬èªã®ã¢ãããŒãã«ãããã¯ã©ã€ã¢ã³ãåŽã®Webã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®å¹æçãªããŒã«ãšãªããŸãã Quick LeftïŒäœæè
ãåããŠããã¹ã¿ãžãªãçŽPerãïŒã䜿çšããŠã¯ã©ã€ã¢ã³ãã®1ã€ã«ã¢ããªã±ãŒã·ã§ã³ãäœæããããšãããã£ããšããç§ã¯è奮ããã§ããéãè§åºŠã«ã€ããŠèª¿ã¹ãããšããŸããã Googleã§èŠã€ããããšãã§ãããã¹ãŠã®ã¬ãã¹ã³ãšã¬ã€ããã€ã³ã¿ãŒãããã§èª¿ã¹ãŸããã ãã£ã¬ã¯ãã£ãããã³ãã¬ãŒããã³ã³ãã€ã«ãããã³ã€ãã³ãã«ãŒãïŒãã€ãžã§ã¹ãïŒãã©ã®ããã«æ©èœããããçè§£ããã®ã«éåžžã«åœ¹ç«ã¡ãŸãããããã¹ãã«é¢ããŠã¯ããã®ãããã¯ãèŠèœãšãããŠããããšãããããŸããã
TDDïŒãã¹ãã«ããéçºïŒã¢ãããŒããç ç©¶ããŸããããRed-Green-Refactoringã¢ãããŒãããªããŠãå®å¿ã§ããŸãã ç§ãã¡ã¯ãŸã Angularãã¹ãã§äœãèµ·ãã£ãŠããã®ããææ¡ããŠããã®ã§ãããŒã ã¯ãã¹ãåŸã®ã¢ãããŒãã«é Œããªããã°ãªããªãããšããããŸããã ç·åŒµãå§ããã®ã§ããã¹ãã«éäžããããšã«ããŸããã ç§ã¯ããã«æ°é±éãè²»ãããããã«ãã¹ãã«ãã¬ããžã40ïŒ
ãã86ïŒ
ã«äžæããŸããïŒããããŸã è¡ã£ãŠããªãå Žåã¯ãJSã¢ããªã±ãŒã·ã§ã³ã§ã³ãŒãã«ãã¬ããžã確èªããããã«
Istabulã詊ãããšãã§ããŸãïŒã
ã¯ããã«
仿¥ãç§ã¯åŠãã ããšã®ããã€ããå
±æããããšæããŸãã
Angularããã¥ã¡ã³ããšåæ§ã«ãæŠéã¢ããªã±ãŒã·ã§ã³ã®ãã¹ãã¯ã以äžã«ç€ºãäŸã»ã©ç°¡åãªããšã¯ãã£ãã«ãããŸããã äœããæ©èœãããããã«ãç§ãçµéšããªããã°ãªããªãèœãšã穎ããããããããŸãã ç§ã¯äœåºŠã圹ç«ã€ããã€ãã®åé¿çãèŠã€ããŸããã ãã®èšäºã§ã¯ããããã®ããã€ããèŠãŠãããŸãã
- ãšã³ãããŒãšã³ãïŒe2eïŒãã¹ãã§ã®ããŒãžã®åå©çš
- Promiseãè¿ã颿°ã䜿çšãã
- ã³ã³ãããŒã©ãŒã®äŸåé¢ä¿ãšãã£ã¬ã¯ãã£ãã®ã¢ãã¯
- åããã³åé¢ã¹ã³ãŒããžã®ã¢ã¯ã»ã¹
ãã®èšäºã¯ãAngularJSã䜿çšããŠæŠéã¢ããªã±ãŒã·ã§ã³ãäœæããäžçŽããã³äžçŽã®éçºè
ã察象ãšããŠããŸããããã«ããããã¹ãã®èŠçã軜æžã§ããŸãã ãã¹ãã¯ãŒã¯ãããŒã®ã»ãã¥ãªãã£æèŠããèªè
ãTDDã¢ãããŒãã®å®è·µãšããå
ç¢ãªã¢ããªã±ãŒã·ã§ã³ã®éçºãéå§ã§ããããšãé¡ã£ãŠããŸãã
ãã¹ãããŒã«
éçºè
åãã«Angularã§å©çšã§ããå€ãã®ãã¬ãŒã ã¯ãŒã¯ãšãã¹ãããŒã«ããããããããããªãã¯ãã§ã«ããªãã®å¥œã¿ãæã£ãŠããŸãã 以äžã¯ãç§ãã¡ãéžæããèšäºå
šäœã§äœ¿çšããããŒã«ã®ãªã¹ãã§ãã
- Karma ïŒAngularJSããŒã ã®ãã¹ãã©ã³ãã£ãŒã ããã䜿çšããŠãChromeãFirefoxãããã³PhantomJSãèµ·åããŸãã
- AngularMocks ïŒ åäœãã¹ãã§ã®ã€ã³ãžã§ã¯ã·ã§ã³ããã³Mock AngularãµãŒãã¹ã®ãµããŒããæäŸããŸãã
- ååºŠåš ïŒãã©ãŠã¶ã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããSeleniumãä»ããŠã¢ããªã±ãŒã·ã§ã³ãšå¯Ÿè©±ããAngularJSã®æ©èœãã¹ãããŒã«ã
- Mocha ïŒãã¹ãçšã«node.jsçšã«èšè¿°ããããã¬ãŒã ã¯ãŒã¯ã
describe
ãããã¯ãdescribe
ãããã§ãã¯ããããšãã§ããŸãã - Chai ïŒMochaãšçµ±åããBDDã¢ãããŒããžã®ã¢ã¯ã»ã¹ãšã
expect
ã should
ãããã³assert
ãèšè¿°ããæ©èœãæäŸããã¢ãµãŒã·ã§ã³ã©ã€ãã©ãªã äŸã§ã¯ã expect
ã䜿çšexpect
ãŸãã - Chai-as-promised ïŒChaiçšã®ãã©ã°ã€ã³ã¯ãpromiseãè¿ã颿°ãæäœãããšãã«éåžžã«äŸ¿å©ã§ãã æ¬¡ã®ããã«æžãæ©äŒãäžããŸãïŒ
expect(foo).to.be.fulfilled
ãŸãã¯expect(foo).to.eventually.equal(bar)
ã - Sinon ïŒã¹ã¿ãããã³ã¢ãã¯ã©ã€ãã©ãªã ããã䜿çšããŠããã£ã¬ã¯ãã£ããšã³ã³ãããŒã©ãŒã«äŸåé¢ä¿ã¹ã¿ããäœæããæ£ããåŒæ°ã§é¢æ°åŒã³åºããè¡ãããããšã確èªããŸãã
- Browserify ïŒãããžã§ã¯ãå
ã®ãã¡ã€ã«éã§ã¢ãžã¥ãŒã«ãç°¡åã«æ¥ç¶ã§ããŸãã
- éšåå ïŒHTMLãã³ãã¬ãŒããAngularJSãã£ã¬ã¯ãã£ãã«çŽæ¥å«ããããšãã§ããŸãã
- Lodash ïŒæšæºã®JavaScriptæ©èœãæ¡åŒµãããã³ãšç ç³ãå«ãã©ã€ãã©ãªã
ãã¹ãçšã®ãã«ããŒã®ã»ããã¢ãã
ãŸããå¿
èŠãªäŸåé¢ä¿ãæ¥ç¶ãããã«ããŒãäœæããŸãã ããã§ã¯ãAngular MocksãChaiãChai-as-promisedãSinonã䜿çšããŸã
ã¯ããã«ïŒãããããŠã³ãã¹ã
ç§ã¯ããããããŠã³ãã¹ãã¹ã¿ã€ã«ã®å€§æå±è
ã§ãã ãã¹ãŠã¯ãäœæãããæ©èœããå§ãŸããæ©èœã説æããæ¬äŒŒã¹ã¯ãªãããèšè¿°ããŠãæ©èœãã¹ããäœæããŸãã ãã®ãã¹ããå®è¡ãããšããšã©ãŒã§å€±æããŸãã ããã§ãæ©èœãã¹ããæ©èœããããã«å¿
èŠãªã·ã¹ãã ã®ãã¹ãŠã®éšåã®èšèšãéå§ã§ããéäžã§ã¬ã€ããšãªãåäœãã¹ãã䜿çšã§ããŸãã
ããšãã°ãæ¶ç©ºã®ã¢ããªã±ãŒã·ã§ã³ããŠã£ãžã§ããããäœæããŸãããã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããŠã£ãžã§ããã®ãªã¹ãã衚瀺ããããæ°ãããŠã£ãžã§ãããäœæããããçŸåšã®ãŠã£ãžã§ãããç·šéãããã§ããŸãã ããã«è¡šç€ºãããã³ãŒãã¯ãæ¬æ Œçãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã«ã¯ååã§ã¯ãããŸãããããµã³ãã«ãã¹ããçè§£ããã«ã¯ååã§ãã ãŸããæ°ãããŠã£ãžã§ãããäœæããåäœã説æããe2eãã¹ããäœæããŸãã
e2eãã¹ãã§ã®ããŒãžã®åå©çš
1ããŒãžã®ã¢ããªã±ãŒã·ã§ã³ã§äœæ¥ããå Žåãå€ãã®e2eãã¹ãã«æ¥ç¶ã§ããåå©çšå¯èœãªãããŒãžããèšè¿°ããããšã«ãããDRYååãéµå®ããããšã¯çã«ããªã£ãŠããŸãã
Angularãããžã§ã¯ãã§ãã¹ããæ§æããæ¹æ³ã¯å€æ°ãããŸãã 仿¥ã¯ãæ¬¡ã®æ§é ã䜿çšããŸãã
widgets-project |-test | | | |-e2e | | |-pages | | | |-unit
pages
ãã©ã«ããŒå
ã§ãe2eãã¹ãã«æ¥ç¶ã§ãã
WidgetsPage
颿°ãäœæããŸãã 5ã€ã®ãã¹ãããããåç
§ããŸãã
widgetRepeater
ïŒ ng-repeat
å«ãŸãããŠã£ãžã§ããã®ãªã¹ãfirstWidget
ïŒãªã¹ãå
ã®æåã®ãŠã£ãžã§ããwidgetCreateForm
ïŒãŠã£ãžã§ãããäœæããããã®ãã©ãŒã widgetCreateNameField
ïŒãŠã£ãžã§ããã®ååãå
¥åããããã®ãã£ãŒã«ãwidgetCreateSubmit
ïŒãã©ãŒã éä¿¡ãã¿ã³
æçµçã«ã次ã®ãããªãã®ãåŸãããŸãã
e2eãã¹ãå
ããããã®ããŒãžã«æ¥ç¶ããŠããã®èŠçŽ ãšå¯Ÿè©±ã§ããããã«ãªããŸããã äœ¿çšæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
ããã§äœãèµ·ãããèŠãŠã¿ãŸãããã ãŸãããã«ããŒãã¹ããæ¥ç¶ããŠããã
expect
ãš
WidgetsPage
ããŸãã
beforeEach
ããã©ãŠã¶ãŒããŒãžã«èªã¿èŸŒã¿ãŸãã æ¬¡ã«ããã®äŸã§ã¯ã
WidgetsPage
å®çŸ©ãããŠããèŠçŽ ã䜿çšããŠããŒãžãšå¯Ÿè©±ããŸãã ãŠã£ãžã§ããããªãããšã確èªãããã©ãŒã ã«å
¥åããŠããŠã£ãžã§ããã®1ã€ããæ°èŠãŠã£ãžã§ããããšããå€ã§äœæããããŒãžã«è¡šç€ºãããããšã確èªããŸãã
ããã§ããã©ãŒã ã®ããžãã¯ãåå©çšå¯èœãªãããŒãžãã«åå²ãããããç¹°ãè¿ã䜿çšããŠãããšãã°ãã©ãŒã æ€èšŒããã¹ãããããåŸã§ä»ã®ãã£ã¬ã¯ãã£ãã§ãã¹ããããã§ããŸãã
Promiseãè¿ã颿°ã䜿çšãã
äžèšã®ãã¹ãã§å床åšããååŸããã¢ãµãŒãã¡ãœããã¯Promiseãè¿ãã®ã§ãChai-as-promisedã䜿çšããŠã
getText
ãš
getText
æåŸ
ã©ããã®çµæãè¿ãããšã確èªããŸãã
åäœãã¹ãå
ã§promiseãªããžã§ã¯ãã䜿çšããããšãã§ããŸãã æ¢åã®ãŠã£ãžã§ããã®ç·šéã«äœ¿çšã§ããã¢ãŒãã«ãŠã£ã³ããŠããã¹ãããŠããäŸãèŠãŠã¿ãŸãããã UI Bootstrapã®
$modal
ãµãŒãã¹ã䜿çšããŸãã ãŠãŒã¶ãŒãã¢ãŒãã«ãŠã£ã³ããŠãéããšããµãŒãã¹ã¯promiseãè¿ããŸãã ãŠã£ã³ããŠããã£ã³ã»ã«ãŸãã¯ä¿åãããšãpromiseã¯è§£æ±ºãŸãã¯æåŠãããŸãã
Chai-as-promisedã䜿çšããŠ
save
ã¡ãœãããš
cancel
ã¡ãœãããæ£ããæ¥ç¶ãããŠããããšããã¹ãããŠã¿ãŸãããã
ãµãŒãã¹ã¯ããŠã£ãžã§ããç·šéãã³ãã¬ãŒãããã³ãã¬ãŒããã£ãã·ã¥ããŠã£ãžã§ããèªäœã«ããŒããããŠãŒã¶ãŒãç·šéãã©ãŒã ãæåŠãŸãã¯ä¿åãããã©ããã«å¿ããŠãèš±å¯ãŸãã¯æåŠãããé
å»¶ãªããžã§ã¯ããäœæããŸãã
ãã®ãããªãã®ããã¹ãããæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
ãŠã£ãžã§ããç·šéãã¹ãã§ã¢ãŒãã«ãŠã£ã³ããŠãè¿ããããã¹ã®è€éãã«å¯ŸåŠããããã«ãããã€ãã®ããšãã§ããŸãã
beforeEach
颿°ã®
$modal
ãµãŒãã¹ããã¢ãã¯ãäœæãã颿°ã®åºåã空ã®
$scope
ãªããžã§ã¯ãã«çœ®ãæããŠã
destroy
åŒã³åºããã¹ã¿ãåããŸãã
angular.mock.module
ã§ã¯ãAngular Mocksãå®éã®
$modal
ãµãŒãã¹ã®ä»£ããã«ã¢ãŒãã«ãŠã£ã³ããŠã䜿çšã§ããããã«ãã¢ãŒãã«ãŠã£ã³ããŠã®ã³ããŒãæž¡ããŸãã ãã®ã¢ãããŒãã¯ãã¹ã¿ãã®äŸåé¢ä¿ã«éåžžã«åœ¹ç«ã¡ãŸãã
2ã€ã®äŸããããŸãããç·šéãŠã£ãžã§ããããè¿ãããpromiseã®çµæãå®äºãããŸã§èª°ããåŸ
ã€å¿
èŠããããŸãã ãã®ç¹ã§ã
done
ããã©ã¡ãŒã¿ãšããŠãµã³ãã«ã«æž¡ãããã¹ããå®äºããã
done
ãæž¡ãå¿
èŠããããŸãã
ãã¹ãã§ã¯ãAngular Mocksãå床䜿çšããŠããŠã£ãžã§ãããã¢ãŒãã«ãŠã£ã³ããŠãšãAngularJSã®
$rootScope
ãµãŒãã¹ã«æ¿å
¥ããŸãã
$rootScope
ã䜿çšãããšã
$digest
ã«ãŒããåŒã³åºãããšãã§ããŸãã åãã¹ãã§ã¯ãã¢ãŒãã«ãŠã£ã³ããŠãèªã¿èŸŒã¿ããã£ã³ã»ã«ãŸãã¯æå¹ã«ããChai-as-expectedã䜿çšããŠãpromiseã
rejected
ãŸãã¯
resolved
ãšããŠè¿ããããã©ããã確èªããŸãã promiseãš
destroy
ã®å®éã®åŒã³åºãã§ã¯ã
$digest
ãéå§ããå¿
èŠããããããåassertãããã¯ã®çµããã«åŒã³åºãããŸãã
次ã®ã¢ãµãŒãåŒã³åºãã䜿çšããŠãe2eãšåäœãã¹ãã®äž¡æ¹ã®ã±ãŒã¹ã§promiseã䜿çšããæ¹æ³ãæ€èšããŸããã
expect(foo).to.eventually.equal(bar)
expect(foo).to.be.fulfilled
expect(foo).to.be.rejected
ãã£ã¬ã¯ãã£ããšã³ã³ãããŒã©ãŒã®ã¢ãã¯äŸåé¢ä¿
æåŸã®äŸã§ã¯ã$ã¢ãŒãã«ãµãŒãã¹ã«äŸåãããµãŒãã¹ããããããã䜿çšããŠ
destroy
ãå®éã«åŒã³åºãããããšã確èªããŸããã 䜿çšããææ³ã¯éåžžã«äŸ¿å©ã§ãAngularã§åäœãã¹ããããæ£ç¢ºã«åäœãããããšãã§ããŸãã
å
¥å Žã¯æ¬¡ã®ãšããã§ãã
beforeEach
ãããã¯ã§var self = this
å²ãåœãŠãŸãã- ã³ããŒããã³ããŠã³ãã¡ãœãããäœæãããããã
self
ãªããžã§ã¯ãããããã£ã«ããŸãã
self.dependency = { dependencyMethod: self.sinon.stub() }
- ãã¹ã察象ã®ã¢ãžã¥ãŒã«ã«ã³ããŒã転éããŸãã
angular.mock.module('mymodule', { dependency: self.dependecy, otherDependency: self.otherDependency });
- ãã¹ãã±ãŒã¹ã®ããã¯æ¹æ³ã確èªããŸãã ããè¯ãã«ãã¬ããžã®ããã«ã
expect(foo).to.have.been.called.withArgs
䜿çšããŠã expect(foo).to.have.been.called.withArgs
ããåŒæ°ãæž¡ãããšãã§ããŸãã
ãã£ã¬ã¯ãã£ããŸãã¯ã³ã³ãããŒã©ãŒã¯ãå€ãã®å
éšããã³å€éšã®äŸåé¢ä¿ã«äŸåããå Žåãããããããããã¹ãŠããã¯ããå¿
èŠããããŸãã
ããè€éãªäŸãèŠãŠã¿ãŸãããããã®äŸã§ã¯ããã£ã¬ã¯ãã£ãã
widgetStorage
ãµãŒãã¹ãç£èŠããã³ã¬ã¯ã·ã§ã³ã倿Žããããšãã«ç°å¢å
ã®ãŠã£ãžã§ãããæŽæ°ããŸãã ãŸãã
widgetEditor
ã«äœæãã
widgetEditor
ãéã
edit
ã¡ãœããããã
edit
ã
以äžã¯ã
widgetStorage
ããã³
widgetEditor
ããã¯ããŠããã®ãããªãã®ããã¹ãããæ¹æ³ã§ãã
åäŒç€Ÿããã³åé¢ã¹ã³ãŒããžã®ã¢ã¯ã»ã¹
å Žåã«ãã£ãŠã¯ãå
éšã«åé¢ã¹ã³ãŒããŸãã¯åã¹ã³ãŒããæã€ãã£ã¬ã¯ãã£ããäœæããå¿
èŠããããŸãã ããšãã°ã
Angular Strapã® $dropdown
ãµãŒãã¹ã䜿çšãããšãåé¢ãããã¹ã³ãŒããäœæãããŸãã ãã®ã¹ã³ãŒãã«ã¢ã¯ã»ã¹ããã®ã¯éåžžã«éªšã®æããäœæ¥ã§ãã ãã ãã
self.element.isolateScope()
ç¥ã£ãŠ
self.element.isolateScope()
ãããä¿®æ£ã§ããŸãã 以äžã¯ãå€ç«ããã¹ã³ãŒããäœæãã
$dropdown
ã®äœ¿çšäŸã§ãã
ãã£ã¬ã¯ãã£ãããŠã£ãžã§ããã®ã³ã¬ã¯ã·ã§ã³ãæã€èŠªãã£ã¬ã¯ãã£ããããŠã£ãžã§ãããç¶æ¿ãããšä»®å®ãããšãåã¹ã³ãŒããžã®ã¢ã¯ã»ã¹ã¯ãããããã£ãæåŸ
ã©ããã«å€æŽããããã©ããã確èªããã®ãéåžžã«å°é£ã§ãã ããããããã¯ã§ããŸãã èŠãŠã¿ãŸãããïŒ
çæ°ã§ããã ãŸãã
widgetStorage
ãš
widgetEditor
ãåã³ãŠã§ããã«ããŠããã
compile
颿°ã®
compile
ãéå§ããŸãã ãã®é¢æ°ã¯ãã¹ã³ãŒãã®2ã€ã®ã€ã³ã¹ã¿ã³ã¹
parentScope
ãš
childScope
ãäœæãããŠã£ãžã§ãããã¹ãããããŠåã¹ã³ãŒãã«é
眮ããŸãã æ¬¡ã«ã
compile
ã¯ã¹ã³ãŒãèšå®ãšè€éãªãã³ãã¬ãŒããå®è¡ããŸããæåã«ã芪ã¹ã³ãŒããæž¡ããã
widget-organizer
芪èŠçŽ ãã³ã³ãã€ã«ã
widget-organizer
ã ããããã¹ãŠå®äºããããããã«
nested-widget
åèŠçŽ ã远å ããåã¹ã³ãŒããæž¡ããŠãæåŸã«
$digest
å®è¡ããŸãã
çµè«ãšããŠã
compile
颿°ãåŒã³åºãã
self.element.isolateScope()
ä»ããŠãã³ãã¬ãŒãã®ã³ã³ãã€ã«ãããåé¢ã¹ã³ãŒãïŒ
$dropdown
self.element.isolateScope()
ããã®ã¹ã³ãŒãïŒã«ãããã§ããŸãã ãã¹ãã®æåŸã«ãéé¢ãããã¹ã³ãŒãã«å
¥ã£ãŠ
edit
ãåŒã³åºããæåŸã«widgetEditorããŠã£ãžã§ãããšãšãã«åŒã³åºãããããšã確èªããŸãã
ãããã«
ãã¹ãã«ã¯èŠçã䌎ããŸãã ç§ãã¡ã®ãããžã§ã¯ãã§ãã¹ãŠã®æ¹æ³ãçè§£ããã®ãéåžžã«èŠçã§ãã³ãŒãã®äœæã«æ»ãããã¯ãªãã¯ãã¹ãããå®è¡ããŠãã¹ãããèªæã ã£ãããã€ãã®ã±ãŒã¹ãèŠããŠããŸãã æ®å¿µãªããããã®ããã»ã¹ãçµäºãããšãäžç¢ºå®æ§ã®æèŠã¯å¢å€§ããŸãã
è€éãªã±ãŒã¹ã®åŠçæ¹æ³ãçè§£ããããã«æéããããåŸããã®ãããªã±ãŒã¹ãåã³çºçããã¿ã€ãã³ã°ãçè§£ããã®ãã¯ããã«ç°¡åã«ãªããŸããã ãã®èšäºã§èª¬æããææ³ã䜿çšããŠãTDDããã»ã¹ã«åå ããèªä¿¡ãæã£ãŠåé²ããããšãã§ããŸããã
仿¥ç§ãã¡ãèŠããã¯ããã¯ãããªãã®æ¯æ¥ã®ç·Žç¿ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã AngularJSã¯ãŸã è¥ããŠæé·ããŠãããã¬ãŒã ã¯ãŒã¯ã§ãã ã©ã®ãããªãã¯ããã¯ã䜿çšããŠããŸããïŒ