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
11k
Google I:O 2023 Androidの自動テストアップデートまとめ / Google I:O 2023 Android Testing Update Recap
tkmnzm
0
730
コルーチンのエラーをテストするための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.5k
モバイルアプリテスト入門 / Getting Started with Mobile App Testing
tkmnzm
1
670
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
900
Other Decks in Programming
See All in Programming
GraphQL の onError と Nullability のこれから
quramy
0
200
オーケストレーション記述言語 Katari
yukikurage
0
220
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
290
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
410
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.5k
まずはコードより業務と向き合う:テーブル解体のためにPdMを呼んだ話
sakawe_ee
0
150
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
5
770
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
360
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
2.2k
Materialが消えた日 〜真っ白なFlutterキャンバスにRenderObjectで絵を描く〜
umigishiaoi
0
150
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
3
1.4k
Inertia Rails: The One-Person Framework with React & Friends
skryukov
0
380
Featured
See All Featured
Navigating Team Friction
lara
192
16k
Designing for Performance
lara
612
70k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
How to Ace a Technical Interview
jacobian
280
24k
Done Done
chrislema
187
17k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2.1k
Marketing to machines
jonoalderson
1
6k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
450
The SEO Collaboration Effect
kristinabergwall1
1
620
Large-scale JavaScript Application Architecture
addyosmani
516
110k
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ςετΛ ൺֱత؆୯ʹ࣮Ͱ͖Δ
͝ਗ਼ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠ʂ