Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
FragmentScenarioとFragmentFactoryで楽しくUIテスト / Fr...
Search
tkmnzm
June 28, 2019
Programming
2.1k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FragmentScenarioとFragmentFactoryで楽しくUIテスト / FragmentScenario x FragmentFactory UI Test
tkmnzm
June 28, 2019
More Decks by tkmnzm
See All by tkmnzm
AndroidアプリのUIバリエーションをあの手この手で確認する / Check UI variations of Android apps by various means
tkmnzm
1
1.7k
Androidアプリの良いユニットテストを考える / Thinking about good unit tests for Android apps
tkmnzm
5
10k
Google I:O 2023 Androidの自動テストアップデートまとめ / Google I:O 2023 Android Testing Update Recap
tkmnzm
0
710
コルーチンのエラーをテストするためのTips / Tips for testing Kotlin Coroutine errors
tkmnzm
0
1.3k
Androidのモダンな技術選択にあわせて自動テストも アップデートしよう / Update your automated tests to match Android's modern technology choices
tkmnzm
3
2.6k
SWET dev-vitalチームによるプロジェクトの健康状態可視化の取り組み / SWET dev-vital team's efforts to visualize the health of the project
tkmnzm
1
1.4k
モバイルアプリテスト入門 / Getting Started with Mobile App Testing
tkmnzm
1
660
25分で作るAndroid Lint / Android Lint made in 25 minutes
tkmnzm
0
1.1k
2年半ぶりのプロダクト開発であらためて感じた自動テストの大切さ / realized the importance of automatic testing with product development for the first time in two and a half years
tkmnzm
1
890
Other Decks in Programming
See All in Programming
Family mrubyの進捗
kishima
1
130
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.2k
一人だけ、Kiroが静止する日
hideg
0
130
新卒PdEのリアル
ryu1013
1
510
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
8.3k
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
300
アクセシビリティから考える情報設計
high_g_engineer
0
390
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
330
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
190
FreeBSDでZabbixを動かす
kenkino
0
320
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
200
Featured
See All Featured
Google's AI Overviews - The New Search
badams
0
1.6k
New Earth Scene 8
popppiees
4
2.6k
The Language of Interfaces
destraynor
162
27k
Bash Introduction
62gerente
615
220k
Believing is Seeing
oripsolob
1
220
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
250
How STYLIGHT went responsive
nonsquared
100
6.3k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Agile that works and the tools we love
rasmusluckow
331
22k
Unsuck your backbone
ammeep
672
58k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Transcript
FragmentSenarioͱ FragmentFactoryͰ ָ͘͠UIςετ DeNA, SWET Nozomi Takuma
ࣗݾհ Nozomi Takuma DeNAͷSWETάϧʔϓ Androidͱςετ͕͖
Outline FragmentScenario Usage FragmentFactory Usage FragmentScenario x FragmentFactory
UIςετ είʔϓ͕େ͖͘ͳΓ͗͢Δͱ ࣮࣮ߦେม ·ͣݱ࣮తʹςετΛӡ༻Ͱ͖Δ είʔϓΛઃఆ͍ͨ͠ͱ͜Ζ
Fragmentςετ είʔϓΛ୯ҰͷFragmentʹઃఆ͢Δ ґଘΛςετμϒϧʹ͢Δ͜ͱͰ ͞ΒʹείʔϓΛখ͘͞Ͱ͖Δ
είʔϓΛখ͘͞(ྫ) Fragment ViewModel Test Double
είʔϓΛখ͘͞(ྫ) Fragment ViewModel Test Double είʔϓ͜͜
ςετͰ͖Δ͜ͱ FragmentͷUIςετ Fragment ͱViewModelͷͭͳ͗͜Έ LiveDataͷObserveͱUIߋ৽ DataBindingͰͷ࿈ܞ
FragmentScenario Fragmentͷςετ༻API EspressoΛͬͨUIςετ Fragmentͷঢ়ଶΛίϯτϩʔϧ androidx.fragment.fragment-tesNng
FragmentScenario @Test fun test() { // FragmentΛAcNvityͷRootʹΞλονͯ͠ىಈ launchFragmentInContainer<MyFragment>() }
FragmentScenario @Test fun test() { launchFragmentInContainer<MyFragment>() // EspressoͰUIͷݕূ onView(withId(R.id.text_view)).check(matches(withText("Hello"))) }
FragmentScenario @Test fun test() { val scenario = launchFragmentInContainer<MyFragment>() //
Fragmentͷ࠶ੜ scenario.recreate() onView(withId(R.id.stored_text)).check(matches(withText("Stored"))) }
FragmentScenario @Test fun test() { val scenario = launchFragmentInContainer<MyFragment>() //
FragmentʹΞΫηε͍ͨ͠ͱ͖ scenario.onFragment { fragment -> fragment.clearText() } // EspressoͰͷૢ࡞onFragmentϒϩοΫʹॻ͔ͳ͍ onView(withId(R.id.text)).check(matches(withText(""))) }
FragmentScenario Doc Test your app’s fragments h]ps://developer.android.com/ training/basics/fragments/tesNng
ґଘΛΓ͍ͨ͠ DI Dagger x FragmentScenario? DI LibraryΛಋೖ͍ͯ͠ͳ͍ͱ͜Ζ͋Δ
ґଘΛΓ͍ͨ͠ launchFragmentInContainer(fragmentArgs: Bundle? = null, @StyleRes themeResId: Int = ..,
factory: FragmentFactory? = null)
launchFragmentInContainer(fragmentArgs: Bundle? = null, @StyleRes themeResId: Int = .., factory:
FragmentFactory? = null) FragmentFactory!!! ґଘΛΓ͍ͨ͠
FragmentFactory FragmentΠϯελϯεੜΛίϯτ ϩʔϧ ҙͷίϯετϥΫλΛ࣋ͭ FragmentΛੜ͢ΔΑ͏ઃఆͰ͖Δ androidx.fragment.fragment:1.1.0+
FragmentFactory class MyFragmentFactory() : FragmentFactory() { override fun instanNate(classLoader: ClassLoader,
className: String): Fragment { // classʹରͯ͠ͲͷFragmentΛੜ͢Δ͔Λ͜͜ʹॻ͍͍ͯ͘ if (className == MyFragment::class.java.name) { return MyFragment() } return super.instanNate(classLoader, className) } }
Custom Constructor class MyFragment(private val viewModelFactory: .. ) : Fragment()
{ private lateinit var viewModel: MyViewModel override fun onAcNvityCreated(savedInstanceState: Bundle?) { super.onAcNvityCreated(savedInstanceState) viewModel = ViewModelProviders.of(this, viewModelFactory).get(MyViewModel::class.java) } }
Custom Constructor class MyFragment(private val viewModelFactory: .. ) : Fragment()
{ private lateinit var viewModel: MyViewModel override fun onAcNvityCreated(savedInstanceState: Bundle?) { super.onAcNvityCreated(savedInstanceState) viewModel = ViewModelProviders.of(this, viewModelFactory).get(MyViewModel::class.java) } } ViewModelFactoryΛ ίϯετϥΫλͰड͚औΔFragment
Custom Constructor class MyFragmentFactory() : FragmentFactory() { override fun instanNate(classLoader:
ClassLoader, className: String): Fragment { if (className == MyFragment::class.java.name) { // ґଘΛίϯετϥΫλͰͯ͠Fragment Λੜ val viewModelFactory = MyViewModelFactory(MyDataSource()) return MyFragment(viewModelFactory) } return super.instanNate(classLoader, className) } }
FragmentFactoryΛ͏ FragmentManager#setFragmentFactory ઃఆͨ͠FragmentFactoryΛͬͯ FragmentͷੜΛͯ͘͠ΕΔ androidx.appcompat:appcompat:1.1.0+
FragmentFactoryΛ͏ class MyAcNvity : AppCompatAcNvity() { override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState) // setContentViewͷલʹFragmentFactoryΛઃఆ͢Δ // AcNvity͔ΒFragmentFactoryܦ༝ͰґଘΛ͢ͷՄ supportFragmentManager.fragmentFactory = MyFragmentFactory(applicaNon) setContentView(R.layout.acNvity_my) } }
with NavigaNon FragmentManagerʹFragmentFactoryΛ ઃఆ͍ͯ͠ΕɺNavigaNonભҠ࣌ ઃఆͨ͠FragmentFactory͕ΘΕΔ
with Dagger(ࢀߟURL) h]ps://satoshun.github.io/2018/11/ android_all_inject_ctor/ h]ps://github.com/satoshun-android- example/ConstructorInjecNonExample
FragmentFactory x UIςετ @Test fun test() { launchFragmentInContainer<MyFragment>(factory = object
: FragmentFactory() { override fun instanNate(classLoader: ClassLoader, className: String): Fragment { val viewModelFactory = ViewModelFactory(ApplicaNonProvider.getApplicaNonContext(), TestDataSource()) return MyFragment(viewModelFactory) } }) } FragmentFactory x UIςετ
FragmentFactory x UIςετ @Test fun test() { launchFragmentInContainer<MyFragment>(factory = object
: FragmentFactory() { override fun instanNate(classLoader: ClassLoader, className: String): Fragment { val viewModelFactory = ViewModelFactory(ApplicaNonProvider.getApplicaNonContext(), TestDataSource()) return MyFragment(viewModelFactory) } }) } FragmentFactory x UIςετ Ұ෦Λελϒʹஔ͖͑
FragmentFactory x UIςετ Fragment ViewModel Test Double Ͱ͖ͨ
FragmentFactory x UIςετ @Test fun test() { launchFragmentInContainer<MyFragment>(factory = object
: FragmentFactory() { override fun instanNate(classLoader: ClassLoader, className: String): Fragment { val viewModelFactory = ViewModelFactory(ApplicaNonProvider.getApplicaNonContext(), TestDataSource()) return MyFragment(viewModelFactory) } }) } FragmentFactory x UIςετ ͬ͞͞ͱґଘΛίϯτϩʔϧͰ͖ͯ ͨͷ͍͠
Summary FragmentScenarioͱFragmentFactoryΛ ͑είʔϓΛݶఆͨ͠UIςετΛ ൺֱత؆୯ʹ࣮Ͱ͖Δ
͝ਗ਼ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠ʂ