Slide 1

Slide 1 text

ςετ͕ਏ͍Λղܾ͢Δ ςετۦಈ։ൃ ͷΞϓϩʔν ,B[VLJ)JHBTIJHVDIJ !IHTHUL 1)1ΧϯϑΝϨϯεઋ୆

Slide 2

Slide 2 text

"CPVUUIJTUBML ࢿྉެ։͋Γ !IHTHULΑΓ5XJUUFS ʹͯγΣΞ

Slide 3

Slide 3 text

2VFTUJPO ϢχοτςετΛ ॻ͍͍ͯΔʁ

Slide 4

Slide 4 text

2VFTUJPO ͿͬͪΌ͚ ςετΛॻ͘ͷ͕ਏ ͍ʁ

Slide 5

Slide 5 text

8IBUUIJTUBMLJT BCPVU w ʮϢχοτςετΛॻ͘ͷ͕ ਏ͍ʯͱ͍͏՝୊ΛݴޠԽ͢ ΔࢼΈ w ՝୊ʹର͢Δղ๏ͱͯ͠ʮς ετۦಈ։ൃʯΛ׆༻͢Δ

Slide 6

Slide 6 text

8IBUUIJTUBMLJTOPU BCPVU w ΤϯυπʔΤϯυςετ w 1)16OJUͷ࢖͍ํ w ςετ࣮ߦ؀ڥͷ੔උ

Slide 7

Slide 7 text

WBS@EVNQ NF w ౦ޱ࿨ᏻ ,B[VLJ)JHBTIJHVDIJ w !IHTHUL (JU)VC 5XJUUFS w 4FSWFSTJEF&OHJOFFS (P 1)1 FUD w ॴଐɿ#"4&#"/,גࣜձࣾ w #"4&גࣜձࣾࢠձࣾ

Slide 8

Slide 8 text

"HFOEB Ϣχοτςετ͕ਏ͍ཁҼ ςετۦಈ։ൃͱ͸ ςετۦಈ։ൃΛ׆༻͢Δ ςετۦಈ։ൃ΁ͷো֐Λ औΓআ͘ ·ͱΊ

Slide 9

Slide 9 text

̍Ϣχοτςετ͕ ਏ͍ཁҼ

Slide 10

Slide 10 text

Ϣχοτςετͱ͸ w ୯ମςετͱ΋ݺ͹ΕΔ w ϓϩάϥϜΛߏ੒͢Δൺֱతখ͞ͳ୯ҐʢϢχο τʣ͕ݸʑͷػೳΛਖ਼͘͠Ռ͍ͨͯ͠Δ͔Ͳ ͏͔Λݕূ͢Δ w 1)16OJUͳͲͷςετϑϨʔϜϫʔΫΛ༻͍ͯ ࣮ߦ͢Δ

Slide 11

Slide 11 text

Ϣχοτςετ͕ ਏ͍༷ʑͳཁҼ w ςετͷॻ͖ํ͕Θ͔Βͳ͍ w ৗʹҰࠁҰඵΛ૪͍ͬͯΔ w طଘίʔυʹςετ͕ͳ͍ w ςετΛॻ͘ͷ͕ԯ߷ w ςετΛॻ͘ͷ͕೉͍͠ίʔ υʹͳΔ w طଘςετ͕։ൃΛ๦͍͛ͯ Δ

Slide 12

Slide 12 text

w ςετͷॻ͖ํ͕Θ͔Βͳ͍ w ৗʹҰࠁҰඵΛ૪͍ͬͯΔ w طଘίʔυʹςετ͕ͳ͍ w ςετΛॻ͘ͷ͕ԯ߷ w ςετΛॻ͘ͷ͕೉͍͠ίʔ υʹͳΔ w طଘςετ͕։ൃΛ๦͍͛ͯ Δ w ςετͷॻ͖ํͷशಘ d$BVTFd d1PTTJCMZ4PMVUJPOd w ϓϩδΣΫτ؅ཧ w ϨΨγʔίʔυվળ w ςετͷॻ͖΍͍͢ઃܭ w Մಡੑɾϝϯςφϯεੑ ͷߴ͍Ϣχοτςετ w ࣮૷தͷςετͷҐஔͮ ͚ͷݟ௚͠

Slide 13

Slide 13 text

w ςετͷॻ͖ํ͕Θ͔Βͳ͍ w ৗʹҰࠁҰඵΛ૪͍ͬͯΔ w طଘίʔυʹςετ͕ͳ͍ w ςετΛॻ͘ͷ͕ԯ߷ w ςετΛॻ͘ͷ͕೉͍͠ίʔ υʹͳΔ w طଘςετ͕։ൃΛ๦͍͛ͯ Δ d$BVTFd d1PTTJCMZ4PMVUJPOd w ςετͷॻ͖ํͷशಘ w ϓϩδΣΫτ؅ཧ w ϨΨγʔίʔυվળ w ςετͷॻ͖΍͍͢ઃܭ w Մಡੑɾϝϯςφϯεੑ ͷߴ͍Ϣχοτςετ w ࣮૷தͷςετͷҐஔͮ ͚ͷݟ௚͠ Focus points

Slide 14

Slide 14 text

ςετΛॻ͘ͷ͕ԯ߷ w ʮςετΛॻ͘ͷ͕ԯ߷ʯͱ͍͏੠Λฉ͘ࡍɺ ಈ࡞ίʔυΛॻ͍ͨޙʹςετΛॻ͘έʔε ͕ଟ͍ w ಈ࡞ίʔυΛॻ͍͔ͯΒɺςετΛॻ͘ͷ͕ ໘౗ w ࣮૷ͷϦζϜͷதʹϢχοτςετ͕͍ͳ͍

Slide 15

Slide 15 text

ςετΛॻ͘ͷ͕೉͍͠ίʔυʹͳΔ w ಈ࡞ίʔυ࣮૷ޙɺ͍͟ςετΛॻ͜͏ͱ͠ ͨΒςετ͕ॻ͖ͮΒ͔ͬͨͱ͍͏έʔε͕ ͋Δ w ςετΛॻ͍͍ͯͳ͍ίʔυ͸ɺςετ͕ॻ ͖ͮΒ͍έʔε͕ଟ͍

Slide 16

Slide 16 text

4VNNBSZ wϢχοτςετ͕ਏ͍ঢ়گ ʹ͸༷ʑͳཁҼ͕͋Δ wʮϢχοτςετͱ࣮૷ͷ ϦζϜͷ్੾Εʯ͕ɺςε τΛॻ͘ԯ߷͞ΛੜΉ wʮςετΛॻ͖ͮΒ͍ίʔ υʯ͕ɺϢχοτςετΛ ਏ͘͢Δ

Slide 17

Slide 17 text

ςετۦಈ։ൃͱ͸

Slide 18

Slide 18 text

ςετۦಈ։ൃͱ͸ w ϓϩάϥϜ։ൃख๏ͷҰछ w ʮಈ࡞͢Δ͖Ε͍ͳίʔυʯΛΰʔϧͱ͢Δ w ϓϩάϥϛϯάதͷෆ҆Λίϯτϩʔϧ͢Δख ๏ w ࣗಈԽ͞ΕͨςετʹΑͬͯ։ൃΛਪ͠ਐΊ Δ

Slide 19

Slide 19 text

3FE(SFFO3FGBDUPS 3FE Green Refactor 'BJMFEUFTU 1BTTFE 3FGBDUPS

Slide 20

Slide 20 text

ςετۦಈ։ൃͷαΠΫϧ w ·ͣ͸ςετΛҰͭॻ͘ w ͢΂ͯͷςετΛ૸Βͤɺ৽͍͠ςετͷࣦഊ Λ֬ೝ͢Δ 3FE w খ͞ͳมߋΛߦ͏ w ͢΂ͯͷςετΛ૸Βͤɺ͢΂ͯ੒ޭ͢Δ͜ͱ Λ֬ೝ͢Δ (SFFO w ϦϑΝΫλϦϯάΛߦͬͯॏෳΛআڈ͢Δ 3FGBDUPS

Slide 21

Slide 21 text

ςετۦಈ։ൃͷਐΊํ w 50%0ϦετΛ࡞੒͢Δ w ඞཁʹͳΓͦ͏ͳςετΛॻ͖ग़͍ͯ͘͠ w ్தͰؾ͕͍ͭͨ՝୊Λ௥ه͍ͯ͘͠ w ςετۦಈ։ൃͷαΠΫϧʢ3FE(SFFO 3FGBDUPS Λճ͍ͯ͘͠ w 3FE͔Β(SFFOʹ͢ΔͨΊͷzԾ࣮૷zΛ͠ɺ ૉૣ͘αΠΫϧΛճ͢

Slide 22

Slide 22 text

%FNPOTUSBUJPO wྫɿ$.4ΞϓϦέʔ γϣϯ wهࣄৄࡉऔಘ"1*Λ࣮ ૷͢Δ

Slide 23

Slide 23 text

50%0Ϧετ <>هࣄৄࡉऔಘʹͯ੒ޭϨεϙϯε͕ฦ٫͞ ΕΔ <>هࣄৄࡉऔಘʹͯଘࡏ͢ΔϨίʔυͷ৔߹ɺ هࣄ৘ใ͕ฦ٫͞ΕΔ DEMO ʢࢿྉެ։༻ʣ

Slide 24

Slide 24 text

ςετΛॻ͘ /** * @test */ public function هࣄৄࡉऔಘʹͯ੒ޭϨεϙϯε͕ฦ٫͞ΕΔ() { $this->configRequest([ 'headers' => [ 'Accept' => 'application/json', ], ]); $this->get('/api/articles/view/first'); $this->assertResponseSuccess(); } DEMO ʢࢿྉެ։༻ʣ

Slide 25

Slide 25 text

1PTTJCMZSFMBUFEUP $BLFa$POUSPMMFSa&YDFQUJPOa.JTTJOH"DUJPO& YDFQUJPO"DUJPO"SUJDMFT$POUSPMMFSWJFX DPVMEOPUCFGPVOE PSJTOPUBDDFTTJCMF 'BJMFEBTTFSUJOHUIBUJTCFUXFFO BOE DEMO ʢࢿྉެ։༻ʣ

Slide 26

Slide 26 text

খ͞ͳมߋΛߦ͏ class ArticlesController extends AppController { public function view($slug = null) { } } DEMO ʢࢿྉެ։༻ʣ

Slide 27

Slide 27 text

1PTTJCMZSFMBUFEUP $BLFa7JFXa&YDFQUJPOa.JTTJOH5FNQMBUF&YDF QUJPO5FNQMBUFpMF"QJ"SUJDMFTKTPO WJFXDUQJTNJTTJOH 'BJMFEBTTFSUJOHUIBUJTCFUXFFO BOE DEMO ʢࢿྉެ։༻ʣ

Slide 28

Slide 28 text

খ͞ͳมߋΛߦ͏ class ArticlesController extends AppController { public function initialize() { parent::initialize(); $this->loadComponent('RequestHandler'); } public function view($slug = null) { $this->set([ '_serialize' => ['article'], 'article' => [], ]); } } DEMO ʢࢿྉެ։༻ʣ

Slide 29

Slide 29 text

0, UFTUT BTTFSUJPOT DEMO ʢࢿྉެ։༻ʣ

Slide 30

Slide 30 text

50%0Ϧετ هࣄৄࡉऔಘʹͯ੒ޭϨεϙϯε͕ฦ٫͞ ΕΔ <>هࣄৄࡉऔಘʹͯଘࡏ͢ΔϨίʔυͷ৔߹ɺ هࣄ৘ใ͕ฦ٫͞ΕΔ DEMO ʢࢿྉެ։༻ʣ

Slide 31

Slide 31 text

ςετΛॻ͘ /** * @test */ public function هࣄৄࡉऔಘʹͯଘࡏ͢ΔϨίʔυͷ৔߹ɺهࣄ৘ใ͕ฦ٫͞ΕΔ() { $this->configRequest([ 'headers' => [ 'Accept' => 'application/json', ], ]); $this->get('/api/articles/view/first'); $expected = [ 'article' => [ 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'slug' => 'first', 'body' => 'First Article Body', 'published' => 1, 'created' => '2018-01-07T15:47:01+00:00', 'modified' => '2018-01-07T15:47:02+00:00', ], ]; $expected = json_encode($expected, JSON_PRETTY_PRINT); $this->assertSame($expected, (string)$this->_response->getBody()); } DEMO ʢࢿྉެ։༻ʣ

Slide 32

Slide 32 text

DEMO ʢࢿྉެ։༻ʣ 'BJMFEBTTFSUJOHUIBUUXPTUSJOHTBSFJEFOUJDBM

Slide 33

Slide 33 text

Ծ࣮૷ public function view($slug = null) { // TODO temporary implement $article = [ 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'slug' => 'first', 'body' => 'First Article Body', 'published' => 1, 'created' => '2018-01-07T15:47:01+00:00', 'modified' => '2018-01-07T15:47:02+00:00', ]; $this->set([ '_serialize' => ['article'], 'article' => $article, ]); } DEMO ʢࢿྉެ։༻ʣ

Slide 34

Slide 34 text

0, UFTUT BTTFSUJPOT DEMO ʢࢿྉެ։༻ʣ

Slide 35

Slide 35 text

ϦϑΝΫλϦϯά public function view($slug = null) { $article = $this->Articles->findBySlug($slug)- >firstOrFail(); $this->set([ '_serialize' => ['article'], 'article' => $article, ]); } DEMO ʢࢿྉެ։༻ʣ

Slide 36

Slide 36 text

0, UFTUT BTTFSUJPOT DEMO ʢࢿྉެ։༻ʣ

Slide 37

Slide 37 text

50%0Ϧετ هࣄৄࡉऔಘʹͯ੒ޭϨεϙϯε͕ฦ٫͞ ΕΔ هࣄৄࡉऔಘʹͯଘࡏ͢ΔϨίʔυͷ৔߹ɺ هࣄ৘ใ͕ฦ٫͞ΕΔ DEMO ʢࢿྉެ։༻ʣ

Slide 38

Slide 38 text

w ςετͷॻ͖ํ͕Θ͔Βͳ͍ w ৗʹҰࠁҰඵΛ૪͍ͬͯΔ w طଘίʔυʹςετ͕ͳ͍ w ςετΛॻ͘ͷ͕ԯ߷ w ςετΛॻ͘ͷ͕೉͍͠ίʔ υʹͳΔ w طଘςετ͕։ൃΛ๦͍͛ͯ Δ d$BVTFd d1PTTJCMZ4PMVUJPOd w ςετͷॻ͖ํͷशಘ w ϓϩδΣΫτ؅ཧ w ϨΨγʔίʔυվળ w ςετͷॻ͖΍͍͢ઃܭ w Մಡੑɾϝϯςφϯεੑ ͷߴ͍Ϣχοτςετ w ࣮૷தͷςετͷҐஔͮ ͚ͷݟ௚͠ Focus points ৼΓฦΓ

Slide 39

Slide 39 text

ςετۦಈ։ൃ׆༻ͷํ਑ w ςετۦಈ։ൃͷ͍͔ͭ͘ͷଆ໘Λ༗ޮ׆༻ ͢Δ w ςετΛ࠷ॳʹॻ͘ʢςετϑΝʔετʣ͜ ͱʹΑΓɺʮςετ͕ॻ͖ͮΒ͍ʯίʔυΛ ճආ͢Δ w ςετۦಈ։ൃͷϦζϜΛऔΓೖΕΔ͜ͱͰɺ ಈ࡞ίʔυͱςετΛҰͭͷϦζϜͰਐΊΔ

Slide 40

Slide 40 text

4VNNBSZ w3FE(SFFO3FGBDUPS ͷϦζϜΛ΋ͬͯਐΊ Δςετۦಈ։ൃ wςετۦಈ։ൃʹΑͬ ͯɺςετ͕ॻ͖ͮΒ ͍ɾԯ߷ͳঢ়گΛճ ආ͢Δ

Slide 41

Slide 41 text

ςετۦಈ։ൃΛ ׆༻͢Δ

Slide 42

Slide 42 text

ϢχοτςετΛҙຯ͚ͮΔ w ܽؕͷ͋Δίʔυͷࠞೖ཰ΛԼ͛Δ w ৺ཧతෆ҆ΛԼ͛Δ w lςετ͕௨͍ͬͯΔ͔Βյ͍ͯ͠ͳ͍͸ͣz w ༐׶ͳϦϑΝΫλϦϯά w ઃܭͷิॿಓ۩

Slide 43

Slide 43 text

ઃܭͷิॿಓ۩ͱͯ͠ͷςετ w Ϣχοτςετ͔Βɺಈ࡞ίʔυͷઃܭʹͭ ͍ͯɺϑΟʔυόοΫΛಘΔ w ςετΛઌʹॻ͘͜ͱͰɺʮςετͷ͠΍͢ ͍ίʔυʯΛॻ͘ΪϒεΛ෇͚Δ w ʮςετͷॻ͖ʹ͘͞ʯ͔Βઃܭʹର͢Δҧ ࿨ײΛټΈऔΔ

Slide 44

Slide 44 text

$BTF4UVEZ ઃܭͷ ϑΟʔυόοΫΛ ςετέʔε͔Β ಘΔ

Slide 45

Slide 45 text

$BTF4UVEZ w ໰͍߹ΘͤอଘػೳΛ࣮૷͢Δ w ʮλΠτϧʯɾʮຊจʯɾʮϝʔϧΞυϨεʯɾ ʮΫϥΠΞϯτͷ*1ΞυϨεʯΛอଘ͓ͯ͘͠

Slide 46

Slide 46 text

50%0Ϧετ ໰͍߹ΘͤϖʔδʹΞΫηεͰ͖Δ ໰͍߹Θͤอଘ੒ޭ࣌Ұཡϖʔδ΁ϦμΠ ϨΫτ͢Δ <>໰͍߹Θͤͨ͠಺༰͕JORVJSJFTςʔϒϧʹ อଘ͞ΕΔ

Slide 47

Slide 47 text

ݱ࣌఺ͷςετ /** * @test */ public function ໰͍߹ΘͤϖʔδʹΞΫηεͰ͖Δ() { $this->get('/inquiries/add'); $this->assertResponseOk(); } /** * @test */ public function ໰͍߹Θͤอଘ੒ޭ࣌Ұཡϖʔδ΁ϦμΠϨΫτ͢Δ() { $this->enableCsrfToken(); $this->enableSecurityToken(); $data = [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ]; $this->post('/inquiries/add', $data); $this->assertResponseSuccess(); $this->assertRedirect('/inquiries'); }

Slide 48

Slide 48 text

ݱ࣌఺ͷ࣮૷ public function add() { $inquiry = $this->Inquiries->newEntity(); if ($this->request->is('post')) { // TODO save inquiry data return $this->redirect(['action' => 'index']); } $this->set(compact('inquiry')); }

Slide 49

Slide 49 text

50%0Ϧετ ໰͍߹ΘͤϖʔδʹΞΫηεͰ͖Δ ໰͍߹Θͤอଘ੒ޭ࣌Ұཡϖʔδ΁ϦμΠ ϨΫτ͢Δ <>໰͍߹Θͤͨ͠಺༰͕JORVJSJFTςʔϒϧʹ อଘ͞ΕΔ

Slide 50

Slide 50 text

·ͣ͸ςετΛॻ͘ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $this->enableCsrfToken(); $this->enableSecurityToken(); $this->configRequest([ 'environment' => ['REMOTE_ADDR' => '12.34.56.78'], ]); $data = [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ]; $this->post('/inquiries/add', $data); /** @var Inquiry $saved_inquiry */ $saved_inquiry = TableRegistry::getTableLocator() ->get('inquiries')->find() ->where(['title' => 'sample'])->first(); $this->assertInstanceOf('\App\Model\Entity\Inquiry', $saved_inquiry); }

Slide 51

Slide 51 text

'BJMFEBTTFSUJOHUIBUOVMMJTBOJOTUBODFPGDMBTT la"QQa.PEFMa&OUJUZa*ORVJSZ 5FTUT "TTFSUJPOT 'BJMVSFT

Slide 52

Slide 52 text

ςετΛ௨ͨ͢ΊͷԾ࣮૷ public function add() { $inquiry = $this->Inquiries->newEntity(); if ($this->request->is('post')) { // FIXME temporary $inquiry->title = 'sample'; $inquiry->body = 'sample'; $inquiry->email = '[email protected]'; $inquiry->client_ip = ’12.34.56.78'; $this->Inquiries->save($inquiry); return $this->redirect(['action' => 'index']); } $this->set(compact('inquiry')); }

Slide 53

Slide 53 text

0, UFTUT BTTFSUJPOT

Slide 54

Slide 54 text

3FGBDUPSJOH w ظ଴஋ͷςετΛ࡞੒͠ɺςετ͕௨ΔԾ࣮૷Λͨ͠ w Ծ࣮૷ΛϦϑΝΫλϦϯά͢Δ

Slide 55

Slide 55 text

࣮૷ऀ͕಄ʹු͔Μ࣮ͩ૷ public function saveWithIp(Inquiry $entity, \Cake\Http\ServerRequest $request) { $entity->client_ip = $request->clientIp(); return $this->save($entity); } w .PEFM૚ʹϝιουΛ࡞੒ w ϦΫΤετΦϒδΣΫτΛड͚औͬͯอଘ

Slide 56

Slide 56 text

ςετΛॻ͘ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $inquiry = $this->Inquiries->newEntity( [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ] ); $request = new \Cake\Http\ServerRequest('/inquiries/ add'); $actual = $this->Inquiries->saveWithIp($inquiry, $request); // Assert something } w ϝιου࡞੒Λ૝ఆ͍ͯ͠Δ.PEFMʹςετΛॻ͘

Slide 57

Slide 57 text

ςετ͔Βҧ࿨ײΛټΈऔΔ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $inquiry = $this->Inquiries->newEntity( [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ] ); $request = new \Cake\Http\ServerRequest('/inquiries/ add'); $actual = $this->Inquiries->saveWithIp($inquiry, $request); // Assert something } ϢχοτςετΛॻͨ͘Ίʹɺ ςετ༻ͷϦΫΤετΛੜ੒͢Δख͕ؒൃੜ ͍ͯ͠Δ

Slide 58

Slide 58 text

ҧ࿨ײ͔Βઃܭ൑அ͢Δ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $inquiry = $this->Inquiries->newEntity( [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ] ); $request = new \Cake\Http\ServerRequest('/inquiries/ add'); $actual = $this->Inquiries->saveWithIp($inquiry, $request); // Assert something } ϞσϧΫϥε͕ɺ ϦΫΤετΫϥεʹґଘ͍ͯ͠Δઃܭ͸ɺ ΍Ίͨ΄͏͕ྑͦ͞͏ͩ

Slide 59

Slide 59 text

ςετΛม͑ͯΈΔ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $inquiry = $this->Inquiries->newEntity( [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ‘client_ip' => ‘171.0.0.1’, ] ); $actual = $this->Inquiries->saveWithIp($inquiry); // Assert something } ϦΫΤετΫϥε΁ͷґଘΛɺ ςετίʔυͷஈ֊Ͱഉআͨ͠ɻ

Slide 60

Slide 60 text

ςετΛม͑ͯΈΔ /** * @test */ public function ໰͍߹Θͤͨ͠಺༰͕inquiriesςʔϒϧʹอଘ͞ΕΔ() { $inquiry = $this->Inquiries->newEntity( [ 'title' => 'sample', 'body' => 'sample', 'email' => '[email protected]', ‘client_ip' => ‘171.0.0.1’, ] ); $actual = $this->Inquiries->saveWithIp($inquiry); // Assert something } ݁ՌతʹɺΤϯςΟςΟΛอଘ͢Δ͚ͩʹ ͳͬͨɻ ϝιουΛ࡞੒͢Δ͜ͱ͕ͦ΋ͦ΋ෆཁ ͱ൑அɻ

Slide 61

Slide 61 text

Ծ࣮૷Λॻ͖׵͑Δ public function add() { $inquiry = $this->Inquiries->newEntity(); if ($this->request->is('post')) { $inquiry = $this->Inquiries->patchEntity($inquiry, $this- >request->getData()); $inquiry->client_ip = $this->request->clientIp(); if (!$this->Inquiries->save($inquiry)) { // TODO error handling } return $this->redirect(['action' => 'index']); } $this->set(compact('inquiry')); }

Slide 62

Slide 62 text

0, UFTUT BTTFSUJPOT

Slide 63

Slide 63 text

50%0Ϧετ ໰͍߹ΘͤϖʔδʹΞΫηεͰ͖Δ ໰͍߹Θͤอଘ੒ޭ࣌Ұཡϖʔδ΁ϦμΠ ϨΫτ͢Δ ໰͍߹Θͤͨ͠಺༰͕JORVJSJFTςʔϒϧʹ อଘ͞ΕΔ

Slide 64

Slide 64 text

$BTF4UVEZ͔ΒֶͿ w ςετۦಈ։ൃͰਐΊΔதͰɺʮςετͷॻ ͖ʹ͘͞ʯΛᄿ͚͗ͭͨ w ಘͨϑΟʔυόοΫʹΑͬͯɺʮςετ͕ਏ͍ ίʔυʯΛճආͨ͠

Slide 65

Slide 65 text

ҧ࿨ײʹର͢Δײ౓Λ্͛Δ w ʮҧ࿨ײΛײ͡Δʯʹ͋ͨΓײ౓Λ͍͔͋͛ͯ ͳ͍ͱ͍͚ͳ͍ w ʮςετ͕͔͚Δʯίʔυ͕ɺʮςετͷॻ͖΍ ͍͢ʯίʔυʹͳΔΘ͚Ͱ͸ͳ͍ w ઃܭࢥ૝ɾٕ๏ͳͲΛซͤͯҙ͓ࣝͯ͘͠ඞཁੑ w ҙࣝ͠΍͍͢ͱ͜Ζ͔Β࢝ΊͯΈΔ

Slide 66

Slide 66 text

ςετͷॻ͖΍͍͢ίʔυ w Ϋϥεͷґଘؔ܎͕໌ࣔతͰஔ͖׵͑΍͍͢ w ੹຿͕໌֬Ͱɺݺͼग़͠ɾݕূ͕؆୯ʹͰ͖ Δ w ͍ΘΏΔʮૄ݁߹͔ͭߴڽूʯ

Slide 67

Slide 67 text

ҧ࿨ײΛײ͡ΔͨΊʹҙࣝ͢Δ͜ͱ Ұͭͷ͜ͱΛ͏·͘΍Ε͍ͯΔ͔

Slide 68

Slide 68 text

rμάϥεɾϚΩϧϩΠ6/*9ͷ࢛൒ੈل l͜Ε͕6/*9ͷ఩ֶͰ͋Δɻ Ұͭͷ͜ͱΛߦ͍ɺ·ͨͦΕΛ͏·͘΍ΔϓϩάϥϜ Λॻ͚ɻ ڠௐͯ͠ಈ͘ϓϩάϥϜΛॻ͚ɻz https://ja.wikipedia.org/wiki/UNIX఩ֶ

Slide 69

Slide 69 text

ҧ࿨ײΛײ͡ΔͨΊʹҙࣝ͢Δ͜ͱ ҰจͰΫϥεΛઆ໌Ͱ͖Δ͔

Slide 70

Slide 70 text

ҰจͰΫϥεΛઆ໌Ͱ͖Δ͔ w ʮΫϥε͕࣮ࡍʹԿΛ͍ͯ͠Δͷ͔͕໌֬Ͱ ͋Δ͔ʯΛਤΔ w "/%ɾ03ɾ#65Λ࢖Θͣʹઆ໌Ͱ͖Δ͔ w ࢖ͬͯ͠·ͬͨ৔߹ɺෳ਺ͷ੹຿͕ࠞࡏͯ͠ ͍ΔՄೳੑ͕͋Δ

Slide 71

Slide 71 text

$BTF4UVEZ ΞΧ΢ϯτొ࿥

Slide 72

Slide 72 text

50%0Ϧετ w <>ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞Ε Δ w <>ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ

Slide 73

Slide 73 text

ࣦഊ͢ΔςετΛॻ͘ /** * @test */ public function ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞ΕΔ() { $result = $this->AccountService->register(); // σʔλϕʔεʹอଘ͞Εͨ஋ΛΞαʔτ͢Δ }

Slide 74

Slide 74 text

ςετΛ௨࣮͢૷Λ͢Δ class AccountService { public function register() { // ΞΧ΢ϯτ৘ใอଘॲཧ } }

Slide 75

Slide 75 text

50%0Ϧετ w ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞Ε Δ w <>ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ

Slide 76

Slide 76 text

͞ΒʹςετΛ௥Ճ͢Δ /** * @test */ public function ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞ΕΔ() { $result = $this->AccountService->register(); // σʔλϕʔεʹอଘ͞Εͨ஋ΛΞαʔτ͢Δ } /** * @test */ public function ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ() { $result = $this->AccountService->register(); // ొ࿥׬ྃϝʔϧ͕ૹ৴͞Εͨ͜ͱΛΞαʔτ͢Δ }

Slide 77

Slide 77 text

SFHJTUFS ͕ԿΛ΍Ζ͏ͱ͍ͯ͠Δ͔Λҙࣝ͢Δ w SFHJTUFS ϝιου͸ɺҰͭͷ͜ͱΛ͏·͘΍ Ε͍ͯΔ͔ʁ w ʮΞΧ΢ϯτ৘ใΛσʔλϕʔεʹอଘ͠ɺ ͦͯ͠ొ࿥׬ྃϝʔϧΛૹ৴͢Δʯ w ̎ͭͷॲཧΛಉ࣌ʹ΍Ζ͏ͱ͍ͯ͠Δ

Slide 78

Slide 78 text

SFHJTUFS ͷςετͷॻ͖ͮΒ͞ w ϝʔϧૹ৴ॲཧΛςετ͍ͨ͠৔߹ɺΞΧ΢ ϯτͷσʔλϕʔεอଘॲཧͱҰॹʹςετ ͠ͳ͚Ε͹ͳΒͳ͍ w ҟͳΔଐੑͷৼΔ෣͍͕ີʹ݁߹ͯ͠͠·͏ ͱɺಛఆͷৼΔ෣͍ʹରͯ͠ςετ͕ॻ͖ͮ Β͘ͳΔ

Slide 79

Slide 79 text

50%0Ϧετ΁ୀආ͢Δ w ςετίʔυ͔ΒɺSFHJTUFS ͸΍Γ͍͗ͯ͢ Δ͜ͱ͕Θ͔ͬͨ w ͔͠͠ɺ·ͣ͸໨ͷલͷ3FEΛ(SFFOʹ͢Δ w Ծ࣮૷ͱͯ͢͢͠Ίɺղܾ͢΂͖ߏ଄্ͷ໰ ୊Λ50%0Ϧετʹ௥Ճ͢Δ

Slide 80

Slide 80 text

50%0Ϧετ w ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞Ε Δ w <>ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ w <>ొ࿥׬ྃϝʔϧૹ৴͸ɺ"DDPVOU4FSWJDFΫ ϥεͷ੹຿͔Β௥͍ग़͢

Slide 81

Slide 81 text

ςετΛ௨࣮͢૷Λ͢Δ class AccountService { public function register() { // ΞΧ΢ϯτ৘ใอଘॲཧ ɹɹɹɹ // ϝʔϧૹ৴ॲཧ } }

Slide 82

Slide 82 text

50%0Ϧετ w ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞Ε Δ w ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ w <>ొ࿥׬ྃϝʔϧૹ৴͸ɺSFHJTUFS ͷ੹຿͔ Β௥͍ग़͢

Slide 83

Slide 83 text

ࣦഊ͢ΔςετΛॻ͘ /** * @test */ public function ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ() { $result = $this->AccountMailer->send(); // ొ࿥׬ྃϝʔϧ͕ૹ৴͞Εͨ͜ͱΛΞαʔτ͢Δ } w ϝʔϧૹ৴Λߦ͏"DDPVOU.BJMFSΫϥεͷςε τΛ࡞੒ɺ"DDPVOU4FSWJDF5FTU͔Βςετϝιο υΛҠಈ͢Δ

Slide 84

Slide 84 text

ςετΛ௨࣮͢૷Λ͢Δ class AccountMailer { public function send(Account $account): bool { // ϝʔϧૹ৴ } }

Slide 85

Slide 85 text

50%0Ϧετ w ΞΧ΢ϯτ৘ใ͕σʔλϕʔεʹอଘ͞Ε Δ w ొ࿥׬ྃϝʔϧΛૹ৴͞ΕΔ w ొ࿥׬ྃϝʔϧૹ৴͸ɺSFHJTUFS ͷ੹຿ ͔Β௥͍ग़͢

Slide 86

Slide 86 text

$BTF4UVEZ͔ΒֶͿ w ςετίʔυɾಈ࡞ίʔυΛॻ͖ͳ͕ΒɺʮҰ ͭͷ͜ͱΛ͏·͘΍Ε͍ͯΔ͔ʯΛҙࣝͨ͠ w ్தͰ΍Γ͍͗ͯ͢ΔϝιουΛ՝୊ͱͯ͠ ೝࣝ͠ɺ50%0ʹͨ͠ w ΍Γ͗ͨ͢ϝιουΛϦϑΝΫλϦϯάͨ͠

Slide 87

Slide 87 text

4VNNBSZ wઃܭͷิॿಓ۩ͱͯ͠Ϣ χοτςετΛ༻͍Δ wςετίʔυͷॻ͖ʹ͘ ͔͞Βɺઃܭʹର͢Δҧ ࿨ײΛټΈऔΔ wټΈऔͬͨҧ࿨ײΛϦ ϑΝΫλϦϯάͰղফ͢ Δ

Slide 88

Slide 88 text

ςετۦಈ։ൃ΁ͷ ো֐ΛऔΓআ͘

Slide 89

Slide 89 text

ςετۦಈ։ൃ΁ͷো֐ w ςετۦಈ։ൃΛ࣮ફ͢ΔͨΊͷো֐ΛऔΓ আ͘ w Ұͭͷέʔεͱͯ͠ɺςετ͕ͳ͍ίʔυʹͭ ͍ͯऔΓѻ͏

Slide 90

Slide 90 text

$BTF4UVEZ ςετ͕ͳ͍ίʔυ

Slide 91

Slide 91 text

ςετ͕ͳ͍ίʔυ public function index() { $articles = $this->Articles->find('all'); $this->set([ '_serialize' => ['articles'], 'articles' => $articles, ]); } w هࣄҰཡΛKTPOͰฦ٫͢Δγϯϓϧͳ"1* w lެ։͍ͯ͠Δ QVCMJTIFE zهࣄͷΈฦ٫͢ΔมߋΛ૝ఆ w ͔͠͠ɺલ೚ऀʹΑΔςετίʔυ͸ॻ͔Ε͍ͯͳ͔ͬͨ

Slide 92

Slide 92 text

ςετۦಈ։ൃͷ౔ඨʹ্͛Δ w ·ͣ͸ɺطଘͷৼΔ෣͍Λอޢ͢Δςετίʔ υΛॻ͘ʢ࢓༷Խςετʣ w อޢͨ͠ޙʹςετۦಈ։ൃͷαΠΫϧΛ࣮ફ ͢Δ

Slide 93

Slide 93 text

࢓༷Խςετ wl$IBSBDUFSJ[BUJPOUFTUz wίʔυͷৼΔ෣͍Λ໌Β͔ʹ͢Δςετ

Slide 94

Slide 94 text

࢓༷Խςετͷखॱ ςετίʔυͷதͰର৅ͷίʔυΛݺͼग़͢ ࣦഊ͢ΔͱΘ͔͍ͬͯΔද໌Λॻ͘ ࣦഊͨ݁͠Ռ͔Β࣮ࡍͷৼΔ෣͍Λ֬ೝ͢Δ ίʔυ͕࣮ݱ͢ΔৼΔ෣͍Λظ଴͢ΔΑ͏ʹɺ ςετΛมߋ͢Δ ʙΛ܁Γฦ͢

Slide 95

Slide 95 text

ର৅ίʔυΛݺͼग़͢ /** * @test */ public function هࣄҰཡऔಘʹͯهࣄҰཡ͕ฦ٫͞ΕΔ() { $this->configRequest([ 'headers' => [ 'Accept' => 'application/json', ], ]); $this->get('/api/articles/index'); }

Slide 96

Slide 96 text

ࣦഊ͢Δද໌Λߦ͏ /** * @test */ public function هࣄҰཡऔಘʹͯهࣄҰཡ͕ฦ٫͞ΕΔ() { $this->configRequest([ 'headers' => [ 'Accept' => 'application/json', ], ]); $this->get('/api/articles/index'); $expected = json_encode([], JSON_PRETTY_PRINT); $this->assertSame($expected, (string)$this- >_response->getBody()); }

Slide 97

Slide 97 text

ࣦഊͨ݁͠Ռ͔Β࣮ࡍͷৼΔ෣͍Λ֬ೝ͢Δ 'BJMFEBTTFSUJOHUIBUUXPTUSJOHTBSFJEFOUJDBM

Slide 98

Slide 98 text

ςετΛมߋ͢Δ $expected = [ 'articles' => [ [ 'id' => 1, 'user_id' => 1, 'title' => 'First Published Article', 'slug' => 'first-published-article', 'body' => 'First Published Body', 'published' => 1, 'created' => '2018-01-07T15:47:01+00:00', 'modified' => '2018-01-07T15:47:02+00:00', ], [ 'id' => 2, 'user_id' => 1, 'title' => 'Unpublished Article', 'slug' => 'unpublished-article', 'body' => 'Unpublished Article Body', 'published' => 0, 'created' => '2018-01-07T15:47:01+00:00', 'modified' => '2018-01-07T15:47:02+00:00', ], ], ]; $expected = json_encode($expected, JSON_PRETTY_PRINT); $this->assertSame($expected, (string)$this->_response->getBody());

Slide 99

Slide 99 text

0, UFTU BTTFSUJPO

Slide 100

Slide 100 text

มߋ͍ͨ͠ৼΔ෣͍Λςετʹॻ͘ $expected = [ 'articles' => [ [ 'id' => 1, 'user_id' => 1, 'title' => 'First Published Article', 'slug' => 'first-published-article', 'body' => 'First Published Body', 'published' => 1, 'created' => '2018-01-07T15:47:01+00:00', 'modified' => '2018-01-07T15:47:02+00:00', ], ], ]; $expected = json_encode($expected, JSON_PRETTY_PRINT); $this->assertSame($expected, (string)$this->_response->getBody()); w ެ։த QVCMJTIFE ͷΈฦ٫͞ΕΔৼΔ෣͍ Λظ଴஋ͱͯ͠ઃఆ͢Δ

Slide 101

Slide 101 text

ςετ͕ࣦഊ͢Δ 'BJMFEBTTFSUJOHUIBUUXPTUSJOHTBSFJEFOUJDBM

Slide 102

Slide 102 text

ςετΛ௨࣮͢૷Λߦ͏ public function index() { $articles = $this->Articles ->find() ->where(['published' => 1]) ->all(); $this->set([ '_serialize' => ['articles'], 'articles' => $articles, ]); }

Slide 103

Slide 103 text

0, UFTU BTTFSUJPO

Slide 104

Slide 104 text

4VNNBSZ wςετ͕ͳ͍ͱ͍͏ো ֐ʹରͯ͠͸ɺ࢓༷Խ ςετʹΑͬͯอޢ͢ Δ wͦͷޙɺςετۦಈ։ ൃͷαΠΫϧ΁ਐΊΔ

Slide 105

Slide 105 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ 5BML4VNNBSZ w ʮςετ͕ਏ͍ʯʹର͢Δ༷ʑͳཁҼ͔Βɺ ʮςετΛॻ͘ԯ߷͞ʯɾʮςετ͕ॻ͖ͮ Β͍ίʔυʹͳΔέʔεʯʹϑΥʔΧεͨ͠ w ςετۦಈ։ൃͷϦζϜʹΑͬͯɺςετͱಈ ࡞ίʔυΛҰͭͷϦζϜͰਐΊΔ w ઃܭͷิॿಓ۩ͱͯ͠ϢχοτςετΛ׆༻ ͢Δ͜ͱͰɺςετ͕ॻ͖ͮΒ͍ίʔυΛճ ආ͢Δ