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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
200
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
330
Are APIs Still Relevant in the AI Era?
soyuka
0
290
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
550
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
What We Talk About When We Talk About XP
m_seki
2
670
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
130
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.1k
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
200
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
8k
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
320
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
2k
Product Roadmaps are Hard
iamctodd
55
13k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
ラッコキーワード サービス紹介資料
rakko
1
5M
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Documentation Writing (for coders)
carmenintech
77
5.5k
Evolving SEO for Evolving Search Engines
ryanjones
0
300
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
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ςετΛ ൺֱత؆୯ʹ࣮Ͱ͖Δ
͝ਗ਼ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠ʂ