WACATE2019_summer_BPP

 WACATE2019_summer_BPP

WACATE2019 夏のBPPセッションスライドです。

Aaf94d61dec57d1c3cf2de7c09e472d4?s=128

Daiki Katayama

June 15, 2019
Tweet

Transcript

  1. ։ൃऀ͔ΒݟΔςετ 2019/06/15~16 WACATE2019 Ն BPPηογϣϯ kariad/͔Γ͋Ͳ(@kariad_uu) 1

  2. ࣗݾ঺հ • kariad / @kariad_uu • ยࢁ େथ • ΦΠγοΫεɾϥɾେ஍

    iOS App Developer • / / V / ςετ / ઃܭ / ྉཧ / ήʔϜ 2
  3. ςετͱͷؔΘΓ • ৽ଔ: SIer ͻͨ͢ΒؤுΔखಈςετɺऴΘΒͳ͍ɺؼΕͳ͍ɺਏ͍…. • ҟಈ: ΞδϟΠϧɺTDDɺςετָ͍͠ • స৬:

    ΞδϟΠϧɺUnitςετಋೖɺςετ΍͍͖ͬͯ • QAΤϯδχΞɺςετΤϯδχΞͱݺ͹ΕΔํͱҰॹʹ࢓ࣄΛͨ͜͠ ͱ͸ͳ͍Ͱ͢ 3
  4. ࠓ೔࿩͢͜ͱ • લճͷࢲͷϙδγϣϯϖʔύʔৼΓฦΓ • ։ൃऀ(ࢲ)͸͜͏͍͏෩ʹςετʹ޲͖߹ͬͯ·͢ͱ͍͏࿩
 - ςετ΁ͷϞνϕʔγϣϯ
 - ։ൃऀ͕ςετΛ͠ͳ͍(Ͱ͖ͳ͍)ཧ༝ 4

  5. ஫ҙʂ • ͋͘·Ͱ΋ࢲͷओ؍Ͱ͢ɻશͯͷ։ൃऀ͕͜͏Ͱ͋Δʂͱ͍ ͏࿩Ͱ͸ͳ͍ͷͰྃ͝ঝ͍ͩ͘͞

  6. લճ(WACATE2018 ౙ)ͷ ࢲͷϙδγϣϯϖʔύʔ 6

  7. 7

  8. ౰೔վΊͯݟͨ࣌ͷࢲͷײ૝ • ΈΜͳͱൺ΂ͯϑΥϯτ͕Ͱ͔͍ • †ͱ͔࢖ͬͯதೋප • ͳΜ͔ΤϞ͍͚ͩ • ਖ਼௚ͪΐͬͱஏ͔͔ͣͬͨ͠… 8

  9. ͭ·ΓԿ͕ݴ͍͔ͨͬͨͷ͔ • ։ൃऀ͔Βࢹ఺Ͱͷςετ΁ͷ૝͍
 ςετ͕͋Δ͜ͱͰ৺ཧత҆શੑͷ͋Δ։ൃ͕Ͱ͖Δ
 Ͱ΋΍Δ͔Βʹ͸ޮ཰తʹ΍Γ͍ͨ • ςετ͕޷͖͔ͩΒ஥ྑͯ͘͠Ͷ
 ςετք۾ͷίϛϡχςΟॳࢀՃͩͬͨ 9

  10. • ࠓճ΋஌Γ߹͍ͱ͔΄΅͍ͳ͍ͷͰؾܰʹ࿩͔͚ͯ͘͠ ΕΔͱخ͍͠Ͱ͢ 10

  11. ։ൃऀͷςετ΁ͷ޲͖߹͍ํ

  12. ςετ΁ͷϞνϕʔγϣϯ (ࢲͳΓʹ) 12

  13. • ࢲͨͪͷϛογϣϯ͸ϢʔβʔʹͱͬͯՁ஋͋Δ
 αʔϏεΛఏڙ͢Δ͜ͱ • Ձ஋͕͋Δ = ͓٬༷(Ϣʔβʔ)͕خ͍͔͠ 13

  14. • Ͱ΋࠷ॳ͔Β࠷େԽ͞ΕͨՁ஋Λఏڙ͢Δͷ͸೉͍͠ • ߟ͑ͨ͜ͱ͕ਖ਼͍͠(Ձ஋͕͋Δ)ͱ͸ݶΒͳ͍
 ϦʔϯɾελʔτΞοϓ 14

  15. ϦʔϯɾελʔτΞοϓ 15

  16. ϦʔϯɾελʔτΞοϓ • ݁ہͲΜͳʹ͍͍΋ͷΛߟ͑ͨͱ͜ΖͰͦΕ͸ࢥ͍ࠐΈ΍Ծ આʹ͗͢ͳ͍ • MVP(Minimum Valuable Product)Ͱݕূ͢Δ • Ծઆ

    → Ծઆݕূ → ֶͼ →ҙࢥܾఆͷαΠΫϧΛճ͢ 16
  17. ࠷ۙͷτϨϯυʁ
 (σʔλ෼ੳΛݩʹͨ͠։ൃ) • ԾઆΛݩʹ࣮૷ͯ͠ϦϦʔε • σʔλΛऔಘͯ͠෼ੳ • ෼ੳ݁ՌΛݩʹվળͯ͠ϦϦʔε

  18. • ͲͪΒ΋ͱʹ͔͘ૣ͘αΠΫϧΛճ͍ͨ͠ • ͱ͸͍͑όά͕͋Γਖ਼ৗʹ࢖͑ͳ͚Ε͹ԾઆݕূͰ͖ͳ ͍
 ‎ ࠷௿ݶChecking͸ߦ͍͍ͨ 18

  19. • ΞδϟΠϧ։ൃऀͱͯ͠͸ૣ͘Ձ஋ͷ͋ΔαʔϏεΛఏ ڙ͢ΔͨΊʹCheckingΛ͍ͨ͠
 ʢͦ΋ͦ΋඼࣭͕௿͔ͬͨΒՁ஋΋Լ͕Δ…ʣ 19

  20. ͡Ό͋ͳΜͰChecking(ࠓճ͸Unitςετ) ΍Βͳ͍ͷʁ 20

  21. • ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • ΍Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍

  22. • ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • ΍Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍ ΋ͬͱݴ͏ͱɺ ΍Γͨͯ͘΋Ͱ͖ͳ͍

  23. • ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • ΍Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍ ΋ͬͱݴ͏ͱɺ ΍Γͨͯ͘΋Ͱ͖ͳ͍

    ࢲ͕ߟ͑ΔUnitςετΛ ΍Βͳ͍ཧ༝ͷେ͖ͳҰͭ
  24. Unitςετ࣮ͬͯ͸ͦΜͳʹ ؆୯Ͱ͸ͳ͍ 24

  25. ςετΛॻ͘ͷ͕೉͍͠ཧ༝ • ςετ͕ॻ͖΍͍͢ઃܭ(Testable)ʹͳ͍ͬͯͳ͍ͱॻ͘͜ ͱ͕೉͍͠ • (ແཧ໼ཧ)ॻ͚ͯ΋ځ۶Ͱมߋʹ΋ऑ͘ͳΔ • ޙ͔Βઃܭมߋ͸ຊ౰ʹେม…(ςετ͕ͳ͍ͱঘߋ) 25

  26. • ଟ͘ͷ৔߹͸ઃܭʹ໰୊͕͋Δ • ΋ͪΖΜϑϩʔతͳ໰୊ͷ৔߹΋͋Δ
 UnitςετΛॻ͘ϑϩʔʹͳ͍ͬͯͳ͍ɻ͕࣌ؒͳ͍ɻ 26

  27. ͦ΋ͦ΋ઃܭͱ͸ ”ؔ৺ͷ෼཭ʹΑͬͯ
 ෳࡶͳ໰୊Λ୯७ͳ໰୊ͷ܈ͱͯ͠੾Γ෼͚Δ͜ͱ” -iOSΞϓϦઃܭύλʔϯೖ໳ P23 ΑΓ 27

  28. • ࠷ۙ͸υϝΠϯతʹ΋ٕज़తʹ΋ෳࡶԽ͍ͯ͠Δ • ͦͷͨΊʹઃܭΛߦ͍ෳࡶ͞ʹཱͪ޲͔͏ • ͖ͪΜͱઃܭ͞Ε͍ͯΔ = ໰୊͕୯७Խ͞Ε͍ͯΔ
 ‎ Testable΁ͷୈҰา

    28
  29. ઃܭύλʔϯ(ΞʔΩςΫνϟ) • MVC / MVP / MVVM / Clean Architecture

    / Flux… • ઃܭํ਑ͱͯ͠ͷϕετϓϥΫςΟεू • ͜ΕΒͷଟ͘͸Testable΋ಉ࣌ʹߟ͑ΒΕ͍ͯΔ 29
  30. ςετ͕ॻ͖΍͍͢ઃܭͱ͸ • ໰୊͕୯७Խ͞Ε͍ͯΔ
 Ϟδϡʔϧ͝ͱʹςετ͍ͨ͠੹຿͕γϯϓϧͰ໌֬ • Ϟδϡʔϧؒͷґଘੑ͕ͳ͍
 ςετ͍ͨ͠੹຿͕ଞϞδϡʔϧͷӨڹΛड͚ͳ͍ 30

  31. ෳࡶͳ੹຿Λ࣋ͬͨϞδϡʔϧ • xxઍߦΈ͍ͨͳΫϥε • ௕͗ͯ͢΋͸΍ԿΛ΍͍ͬͯΔͷ͔Θ͔Βͳ͍ϝιου • ΍ͨΒͱίϝϯτͰઆ໌ͯ͋͠Δ(ݸਓతҙݟ) 31

  32. ੹຿աଟΛͲ͏ݟ෼͚Δ͔ʁ 32

  33. “ίʔυͷ੠Λௌ͘” 33

  34. • ςετ͕ॻ͖ͮΒ͍… • ॲཧ͕ෳࡶԽ͖͍ͯͯ͠Δ… • ඞͣͦ͜ʹࠟ੻͸͋Δ • ίʔυͷष͍ͱ΋ 34

  35. ઃܭͷݪଇ • ༗໊ͳ΋ͷͰ͸SOLIDݪଇ • ୯Ұ੹೚ݪଇɺ։์ด࠯ݪଇɺϦείϑͷஔ׵ݪଇɺΠϯ λʔϑΣʔε෼཭ͷݪଇɺґଘؔ܎ٯసͷݪଇ • ઃܭͷݪଇΛ༻͍ͯίʔυͷष͍ΛऔΓআ͘

  36. Ϟδϡʔϧؒͷґଘੑ͕͋Δ • ଞϞδϡʔϧͷ࣮૷͕มΘΔ͜ͱͰͪ͜Βͷॲཧ͕ӨڹΛड ͚ͯ͠·͏͜ͱ 36

  37. func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {

    result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } 37
  38. func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {

    result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ͜͜ͷॲཧΛςετ͍ͨ͠ 38
  39. func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {

    result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } SearchModelͷ࣮૷ʹ ґଘ͍ͯ͠Δ 39
  40. func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {

    result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } SearchModelͷ࣮૷͕มΘΔͱ ͪ͜Βͷ݁Ռ΋มΘͬͯ͠·͏ 40
  41. func didTapSearchButton(text: String?, model: SearchModel) { ~~~ লུ ~~~ model.search(searchWord:

    searchWord) { result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ֎ଆ͔ΒΦϒδΣΫτΛ ౉͢Α͏ʹ 41
  42. func didTapSearchButton(text: String?, model: SearchModelProtocol) { ~~~ লུ ~~~ model.search(searchWord:

    searchWord) { result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ౉͢ܕΛந৅Խ͞Εͨ ܕʹ͢Δ 42
  43. 43 protocol SearchEventModelProtocol { func search(searchWord: String, completion: @escaping ((Result<[ConnpassEvent]>)

    -> ())) } Protocol
  44. class FakeSearchEventModel: SearchEventModelProtocol { var search_successValue = [ConnpassEvent]() func search(searchWord:

    String, completion: @escaping ((Result<[ConnpassEvent]>) -> ())) { search_callCount += 1 search_arguments = searchWord completion(.success(search_successValue)) } } class FakeFailureSearchEventModel: SearchEventModelProtocol { func search(searchWord: String, completion: @escaping ((Result<[ConnpassEvent]>) -> ())) { search_arguments = searchWord completion(.failure) } } ελϒ ґଘ͢ΔΦϒδΣΫτͷ݁ՌΛ ίϯτϩʔϧͰ͖Δ
  45. • ͜ͷґଘ͢ΔΦϒδΣΫτΛ֎ଆ͔Β౉্ͯ͛͠Δ͜ͱ ΛDI(Dependency Injection)ͱ͍͏ • ౉͢ΦϒδΣΫτ͸ந৅Խ͞Ε͍ͯΔͷͰɺςετίʔ υ͔Β͸ελϒΛ౉͢͜ͱ͕Ͱ͖Δ • Modelͷ࣮૷ʹґଘͤͣ੒ޭɺࣦഊͦΕͧΕͷςετ͕ ՄೳͱͳΔ

    45
  46. • ࣮ࡍʹ͸JavaͰ͋Ε͹MockitoΛ࢖͑͹΋͏গָ͠ʹͳͬ ͨΓ͸͋Δ • ͕ɺSwiftͰ͸ϥΠϒϥϦΛ༻͍ͳ͍͜ͷύλʔϯ͕ൺֱ తଟ͍ • ͜ΕΒͷ஌͕ࣝͳ͍ͱॻ͘͜ͱ͕೉͍͠ 46

  47. ઃܭҎ֎ͷཁૉ • ςεςΟϯάϑϨʔϜϫʔΫͷ࢖͍ํ(XCTest, Quick/Nimble) • ඇಉظॲཧͷςετ • ಛʹඇಉظ͸׳Εͳ͍ͱ೉͍͠
 iOSͰ͸ReactiveX(RxSwift)͕ελϯμʔυ(Combine) 47

  48. ReactiveX • FRP(Functional Reactive Programming) • ௒ͬ͘͟Γ͍͏ͱStreamͱ͍͏࣌ؒͷྲྀΕΛ༻͍ͯඇಉظॲཧΛ؆ ܿʹॻ͚ΔΑ͏ʹͨ͠ख๏ • บ͕͋ΔͷͰ׳Εͳ͍ͱগ͠೉͍͠

    • ςετͰ΋ಉظతʹѻͬͯ͋͛ͨΓɺςετ༻ͷStreamͰ؅ཧͨ͠Γ 48
  49. ςετΛॻͨ͘Ίʹ஌Βͳ͖Ό ͍͚ͳ͍͜ͱ͸ଟ͍ 49

  50. • ΍Βͳ͍ͷͰ͸ͳ͘΍ΔεΩϧ͕ແ͔ͬͨ • ΍Γͨͯ͘΋αΫοͱͰ͖ΔઃܭͰ͸ແ͔ͬͨ • Ͱ΋͜ͷลͷ஌ࣝɺͲ͜Ͱֶ΂͹͍͍ͷ…ʁ

  51. ֶͿͨΊͷ໌Δ͍ஹ͠ 51

  52. ίϛϡχςΟͷಇ͖ • ςετʹؔ͢Δษڧձ (TestNight) • Ϋϥ΢υϑΝ΢ϯσΟϯά(PEAKS)ʹΑΔ
 Android / iOSςετશॻץߦ(iOS͸8݄༧ఆ) 52

  53. ٕज़ॻయ લճࢲ΋͜Μͳͷग़͠·ͨ͠

  54. ·ͱΊ • গͳ͘ͱ΋ϞόΠϧΞϓϦ։ൃऀ಺Ͱ΋ςετʹର͢Δҙࣝ ͸ؒҧ͍ͳ͘ߴ·͍ͬͯΔ(ͱࢥ͏) • αʔόɺϑϩϯτͳͲ΋ϑϨʔϜϫʔΫͷൃల΍ΞδϟΠϧ ͷਁಁͱͱ΋ʹҙࣝ͸ߴ·͍ͬͯΔΑ͏ʹݟ͑Δ 54

  55. • ؍ଌൣғͰ͸ςετΛͲ͏ʹ͔͍ͨ͠ͱࢥ͍ͬͯΔ։ൃ ऀ͕ଟ͍ • Ձ஋͋ΔαʔϏεΛಧ͚͍ͨͱ͍͏ࢥ͍͸୭͠΋ಉ͡ͳ ͸ͣ • ։ൃऀ/ςετΤϯδχΞ͕ڠྗͯ͠ςετʹର͢Δ஌ݟ ΛਂΊ͍͚ͯͨΒخ͍͠ 55

  56. • iOSΞϓϦઃܭύλʔϯೖ໳
 ؔ ོٛɾদؗ େًɾླ໦ େوɾਿ্ ༸ฏɾ࢙ ᠳ৽ɾాத ݡ ࣏ɾՃ౻

    ׮ਓ ஶ
 https://peaks.cc/books/iOS_architecture • Clean Architecture ୡਓʹֶͿιϑτ΢ΣΞͷߏ଄ͱઃܭ
 Robert.C.Martinஶ ֯ ੐యɾߴ໦ ਖ਼߂ ༁ ࢀߟॻ੶
  57. • Test Night
 https://testnight.connpass.com/ • Androidςετશॻ
 https://peaks.cc/books/android_testing • iOSςετશॻ
 https://peaks.cc/iOS_testing

  58. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 58