Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WACATE2019_summer_BPP
Search
Daiki Katayama
June 15, 2019
Programming
1
2.3k
WACATE2019_summer_BPP
WACATE2019 夏のBPPセッションスライドです。
Daiki Katayama
June 15, 2019
Tweet
Share
More Decks by Daiki Katayama
See All by Daiki Katayama
iOSアプリのパフォーマンス計測をおさらいする
kariad
2
9.1k
アプリのパフォーマンスを継続的に計測する
kariad
6
16k
Xcodeのカバレッジ計測ではなぜブランチカバレッジが取れないのだろうか?
kariad
3
4.4k
Viewのテストどうしてますか?
kariad
2
1.5k
コードカバレッジとの付き合い方を知ってテストを書く
kariad
2
2.4k
開発者として学ぶソフトウェアテスト
kariad
2
990
Other Decks in Programming
See All in Programming
note の Elasticsearch 更新系を支える技術
tchov
9
3.6k
カウシェで Four Keys の改善を試みた理由
ike002jp
1
140
Road to Ruby for A Linguistics Nerd
hayat01sh1da
PRO
0
360
今話題のMCPサーバーをFastAPIでサッと作ってみた
yuukis
0
140
Duke on CRaC with Jakarta EE
ivargrimstad
1
220
M5UnitUnified 最新動向 2025/05
gob
0
140
AIコーディングの本質は“コード“ではなく“構造“だった / The essence of AI coding is not “code” but "structure
seike460
PRO
2
520
Embracing Ruby magic
vinistock
2
270
OpenTelemetry + LLM = OpenLLMetry!?
yunosukey
2
180
Cloudflare Workersで進めるリモートMCP活用
syumai
12
1.6k
マイコンでもRustのtestがしたい/KernelVM Kansai 11
tnishinaga
1
930
UMAPをざっくりと理解 / Overview of UMAP
kaityo256
PRO
3
1.6k
Featured
See All Featured
We Have a Design System, Now What?
morganepeng
52
7.6k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
137
33k
Designing Experiences People Love
moore
142
24k
The Cult of Friendly URLs
andyhume
78
6.4k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
Become a Pro
speakerdeck
PRO
28
5.3k
Speed Design
sergeychernyshev
29
940
Raft: Consensus for Rubyists
vanstee
137
6.9k
Bash Introduction
62gerente
613
210k
Documentation Writing (for coders)
carmenintech
71
4.8k
Transcript
։ൃऀ͔ΒݟΔςετ 2019/06/15~16 WACATE2019 Ն BPPηογϣϯ kariad/͔Γ͋Ͳ(@kariad_uu) 1
ࣗݾհ • kariad / @kariad_uu • ยࢁ େथ • ΦΠγοΫεɾϥɾେ
iOS App Developer • / / V / ςετ / ઃܭ / ྉཧ / ήʔϜ 2
ςετͱͷؔΘΓ • ৽ଔ: SIer ͻͨ͢ΒؤுΔखಈςετɺऴΘΒͳ͍ɺؼΕͳ͍ɺਏ͍…. • ҟಈ: ΞδϟΠϧɺTDDɺςετָ͍͠ • స৬:
ΞδϟΠϧɺUnitςετಋೖɺςετ͍͖ͬͯ • QAΤϯδχΞɺςετΤϯδχΞͱݺΕΔํͱҰॹʹࣄΛͨ͜͠ ͱͳ͍Ͱ͢ 3
ࠓ͢͜ͱ • લճͷࢲͷϙδγϣϯϖʔύʔৼΓฦΓ • ։ൃऀ(ࢲ)͜͏͍͏෩ʹςετʹ͖߹ͬͯ·͢ͱ͍͏ - ςετͷϞνϕʔγϣϯ - ։ൃऀ͕ςετΛ͠ͳ͍(Ͱ͖ͳ͍)ཧ༝ 4
ҙʂ • ͋͘·Ͱࢲͷओ؍Ͱ͢ɻશͯͷ։ൃऀ͕͜͏Ͱ͋Δʂͱ͍ ͏Ͱͳ͍ͷͰྃ͝ঝ͍ͩ͘͞
લճ(WACATE2018 ౙ)ͷ ࢲͷϙδγϣϯϖʔύʔ 6
7
վΊͯݟͨ࣌ͷࢲͷײ • ΈΜͳͱൺͯϑΥϯτ͕Ͱ͔͍ • †ͱ͔ͬͯதೋප • ͳΜ͔ΤϞ͍͚ͩ • ਖ਼ͪΐͬͱஏ͔͔ͣͬͨ͠… 8
ͭ·ΓԿ͕ݴ͍͔ͨͬͨͷ͔ • ։ൃऀ͔ΒࢹͰͷςετͷ͍ ςετ͕͋Δ͜ͱͰ৺ཧత҆શੑͷ͋Δ։ൃ͕Ͱ͖Δ ͰΔ͔ΒʹޮతʹΓ͍ͨ • ςετ͕͖͔ͩΒྑͯ͘͠Ͷ ςετք۾ͷίϛϡχςΟॳࢀՃͩͬͨ 9
• ࠓճΓ߹͍ͱ͔΄΅͍ͳ͍ͷͰؾܰʹ͔͚ͯ͘͠ ΕΔͱخ͍͠Ͱ͢ 10
։ൃऀͷςετͷ͖߹͍ํ
ςετͷϞνϕʔγϣϯ (ࢲͳΓʹ) 12
• ࢲͨͪͷϛογϣϯϢʔβʔʹͱͬͯՁ͋Δ αʔϏεΛఏڙ͢Δ͜ͱ • Ձ͕͋Δ = ͓٬༷(Ϣʔβʔ)͕خ͍͔͠ 13
• Ͱ࠷ॳ͔Β࠷େԽ͞ΕͨՁΛఏڙ͢Δͷ͍͠ • ߟ͑ͨ͜ͱ͕ਖ਼͍͠(Ձ͕͋Δ)ͱݶΒͳ͍ ϦʔϯɾελʔτΞοϓ 14
ϦʔϯɾελʔτΞοϓ 15
ϦʔϯɾελʔτΞοϓ • ݁ہͲΜͳʹ͍͍ͷΛߟ͑ͨͱ͜ΖͰͦΕࢥ͍ࠐΈԾ આʹ͗͢ͳ͍ • MVP(Minimum Valuable Product)Ͱݕূ͢Δ • Ծઆ
→ Ծઆݕূ → ֶͼ →ҙࢥܾఆͷαΠΫϧΛճ͢ 16
࠷ۙͷτϨϯυʁ (σʔλੳΛݩʹͨ͠։ൃ) • ԾઆΛݩʹ࣮ͯ͠ϦϦʔε • σʔλΛऔಘͯ͠ੳ • ੳ݁ՌΛݩʹվળͯ͠ϦϦʔε
• ͲͪΒͱʹ͔͘ૣ͘αΠΫϧΛճ͍ͨ͠ • ͱ͍͑όά͕͋Γਖ਼ৗʹ͑ͳ͚ΕԾઆݕূͰ͖ͳ ͍ ࠷ݶCheckingߦ͍͍ͨ 18
• ΞδϟΠϧ։ൃऀͱͯ͠ૣ͘Ձͷ͋ΔαʔϏεΛఏ ڙ͢ΔͨΊʹCheckingΛ͍ͨ͠ ʢ࣭͕͔ͦͦͬͨΒՁԼ͕Δ…ʣ 19
͡Ό͋ͳΜͰChecking(ࠓճUnitςετ) Βͳ͍ͷʁ 20
• ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍
• ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍ ͬͱݴ͏ͱɺ Γͨͯ͘Ͱ͖ͳ͍
• ΊΜͲ͍͘͞ • ςετʹڵຯ͕ͳ͍ • Γํ͕Θ͔Βͳ͍ • CheckingͷॏཁੑΛཧղ͍ͯ͠ͳ͍ ͬͱݴ͏ͱɺ Γͨͯ͘Ͱ͖ͳ͍
ࢲ͕ߟ͑ΔUnitςετΛ Βͳ͍ཧ༝ͷେ͖ͳҰͭ
Unitςετ࣮ͬͯͦΜͳʹ ؆୯Ͱͳ͍ 24
ςετΛॻ͘ͷ͕͍͠ཧ༝ • ςετ͕ॻ͖͍͢ઃܭ(Testable)ʹͳ͍ͬͯͳ͍ͱॻ͘͜ ͱ͕͍͠ • (ແཧཧ)ॻ͚ͯځ۶Ͱมߋʹऑ͘ͳΔ • ޙ͔Βઃܭมߋຊʹେม…(ςετ͕ͳ͍ͱঘߋ) 25
• ଟ͘ͷ߹ઃܭʹ͕͋Δ • ͪΖΜϑϩʔతͳͷ߹͋Δ UnitςετΛॻ͘ϑϩʔʹͳ͍ͬͯͳ͍ɻ͕࣌ؒͳ͍ɻ 26
ͦͦઃܭͱ ”ؔ৺ͷʹΑͬͯ ෳࡶͳΛ୯७ͳͷ܈ͱͯ͠Γ͚Δ͜ͱ” -iOSΞϓϦઃܭύλʔϯೖ P23 ΑΓ 27
• ࠷ۙυϝΠϯతʹٕज़తʹෳࡶԽ͍ͯ͠Δ • ͦͷͨΊʹઃܭΛߦ͍ෳࡶ͞ʹཱ͔ͪ͏ • ͖ͪΜͱઃܭ͞Ε͍ͯΔ = ͕୯७Խ͞Ε͍ͯΔ TestableͷୈҰา
28
ઃܭύλʔϯ(ΞʔΩςΫνϟ) • MVC / MVP / MVVM / Clean Architecture
/ Flux… • ઃܭํͱͯ͠ͷϕετϓϥΫςΟεू • ͜ΕΒͷଟ͘Testableಉ࣌ʹߟ͑ΒΕ͍ͯΔ 29
ςετ͕ॻ͖͍͢ઃܭͱ • ͕୯७Խ͞Ε͍ͯΔ Ϟδϡʔϧ͝ͱʹςετ͍͕ͨ͠γϯϓϧͰ໌֬ • Ϟδϡʔϧؒͷґଘੑ͕ͳ͍ ςετ͍͕ͨ͠ଞϞδϡʔϧͷӨڹΛड͚ͳ͍ 30
ෳࡶͳΛ࣋ͬͨϞδϡʔϧ • xxઍߦΈ͍ͨͳΫϥε • ͗ͯ͢ԿΛ͍ͬͯΔͷ͔Θ͔Βͳ͍ϝιου • ͨΒͱίϝϯτͰઆ໌ͯ͋͠Δ(ݸਓతҙݟ) 31
աଟΛͲ͏ݟ͚Δ͔ʁ 32
“ίʔυͷΛௌ͘” 33
• ςετ͕ॻ͖ͮΒ͍… • ॲཧ͕ෳࡶԽ͖͍ͯͯ͠Δ… • ඞͣͦ͜ʹࠟ͋Δ • ίʔυͷष͍ͱ 34
ઃܭͷݪଇ • ༗໊ͳͷͰSOLIDݪଇ • ୯Ұݪଇɺ։์ดݪଇɺϦείϑͷஔݪଇɺΠϯ λʔϑΣʔεͷݪଇɺґଘؔٯసͷݪଇ • ઃܭͷݪଇΛ༻͍ͯίʔυͷष͍ΛऔΓআ͘
Ϟδϡʔϧؒͷґଘੑ͕͋Δ • ଞϞδϡʔϧͷ࣮͕มΘΔ͜ͱͰͪ͜Βͷॲཧ͕ӨڹΛड ͚ͯ͠·͏͜ͱ 36
func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {
result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } 37
func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {
result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ͜͜ͷॲཧΛςετ͍ͨ͠ 38
func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {
result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } SearchModelͷ࣮ʹ ґଘ͍ͯ͠Δ 39
func didTapSearchButton(text: String?) { ~~~ লུ ~~~ SearchModel().search(searchWord: searchWord) {
result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } SearchModelͷ࣮͕มΘΔͱ ͪ͜Βͷ݁ՌมΘͬͯ͠·͏ 40
func didTapSearchButton(text: String?, model: SearchModel) { ~~~ লུ ~~~ model.search(searchWord:
searchWord) { result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ֎ଆ͔ΒΦϒδΣΫτΛ ͢Α͏ʹ 41
func didTapSearchButton(text: String?, model: SearchModelProtocol) { ~~~ লུ ~~~ model.search(searchWord:
searchWord) { result in switch result { case .success(let events): ~~ লུ ~~ case .failure: ~~ লུ ~~ } } } ͢ܕΛநԽ͞Εͨ ܕʹ͢Δ 42
43 protocol SearchEventModelProtocol { func search(searchWord: String, completion: @escaping ((Result<[ConnpassEvent]>)
-> ())) } Protocol
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) } } ελϒ ґଘ͢ΔΦϒδΣΫτͷ݁ՌΛ ίϯτϩʔϧͰ͖Δ
• ͜ͷґଘ͢ΔΦϒδΣΫτΛ֎ଆ͔Β্ͯ͛͠Δ͜ͱ ΛDI(Dependency Injection)ͱ͍͏ • ͢ΦϒδΣΫτநԽ͞Ε͍ͯΔͷͰɺςετίʔ υ͔ΒελϒΛ͢͜ͱ͕Ͱ͖Δ • Modelͷ࣮ʹґଘͤͣޭɺࣦഊͦΕͧΕͷςετ͕ ՄೳͱͳΔ
45
• ࣮ࡍʹJavaͰ͋ΕMockitoΛ͑͏গָ͠ʹͳͬ ͨΓ͋Δ • ͕ɺSwiftͰϥΠϒϥϦΛ༻͍ͳ͍͜ͷύλʔϯ͕ൺֱ తଟ͍ • ͜ΕΒͷ͕ࣝͳ͍ͱॻ͘͜ͱ͕͍͠ 46
ઃܭҎ֎ͷཁૉ • ςεςΟϯάϑϨʔϜϫʔΫͷ͍ํ(XCTest, Quick/Nimble) • ඇಉظॲཧͷςετ • ಛʹඇಉظ׳Εͳ͍ͱ͍͠ iOSͰReactiveX(RxSwift)͕ελϯμʔυ(Combine) 47
ReactiveX • FRP(Functional Reactive Programming) • ͬ͘͟Γ͍͏ͱStreamͱ͍͏࣌ؒͷྲྀΕΛ༻͍ͯඇಉظॲཧΛ؆ ܿʹॻ͚ΔΑ͏ʹͨ͠ख๏ • บ͕͋ΔͷͰ׳Εͳ͍ͱগ͍͠͠
• ςετͰಉظతʹѻͬͯ͋͛ͨΓɺςετ༻ͷStreamͰཧͨ͠Γ 48
ςετΛॻͨ͘ΊʹΒͳ͖Ό ͍͚ͳ͍͜ͱଟ͍ 49
• Βͳ͍ͷͰͳ͘ΔεΩϧ͕ແ͔ͬͨ • Γͨͯ͘αΫοͱͰ͖ΔઃܭͰແ͔ͬͨ • Ͱ͜ͷลͷࣝɺͲ͜Ͱֶ͍͍ͷ…ʁ
ֶͿͨΊͷ໌Δ͍ஹ͠ 51
ίϛϡχςΟͷಇ͖ • ςετʹؔ͢Δษڧձ (TestNight) • ΫϥυϑΝϯσΟϯά(PEAKS)ʹΑΔ Android / iOSςετશॻץߦ(iOS8݄༧ఆ) 52
ٕज़ॻయ લճࢲ͜Μͳͷग़͠·ͨ͠
·ͱΊ • গͳ͘ͱϞόΠϧΞϓϦ։ൃऀͰςετʹର͢Δҙࣝ ؒҧ͍ͳ͘ߴ·͍ͬͯΔ(ͱࢥ͏) • αʔόɺϑϩϯτͳͲϑϨʔϜϫʔΫͷൃలΞδϟΠϧ ͷਁಁͱͱʹҙࣝߴ·͍ͬͯΔΑ͏ʹݟ͑Δ 54
• ؍ଌൣғͰςετΛͲ͏ʹ͔͍ͨ͠ͱࢥ͍ͬͯΔ։ൃ ऀ͕ଟ͍ • Ձ͋ΔαʔϏεΛಧ͚͍ͨͱ͍͏ࢥ͍୭͠ಉ͡ͳ ͣ • ։ൃऀ/ςετΤϯδχΞ͕ڠྗͯ͠ςετʹର͢Δݟ ΛਂΊ͍͚ͯͨΒخ͍͠ 55
• iOSΞϓϦઃܭύλʔϯೖ ؔ ོٛɾদؗ େًɾླ େوɾਿ্ ༸ฏɾ࢙ ᠳ৽ɾాத ݡ ࣏ɾՃ౻
ਓ ஶ https://peaks.cc/books/iOS_architecture • Clean Architecture ୡਓʹֶͿιϑτΣΞͷߏͱઃܭ Robert.C.Martinஶ ֯ యɾߴ ਖ਼߂ ༁ ࢀߟॻ੶
• Test Night https://testnight.connpass.com/ • Androidςετશॻ https://peaks.cc/books/android_testing • iOSςετશॻ https://peaks.cc/iOS_testing
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 58