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
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
700
コルーチンのエラーをテストするための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
650
25分で作るAndroid Lint / Android Lint made in 25 minutes
tkmnzm
0
1k
2年半ぶりのプロダクト開発であらためて感じた自動テストの大切さ / realized the importance of automatic testing with product development for the first time in two and a half years
tkmnzm
1
880
Other Decks in Programming
See All in Programming
プロポーザルを書いてもらう
pvcresin
0
310
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.6k
Built Our Own Background Agent at LayerX
layerx
PRO
10
5.2k
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
880
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
180
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
360
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
160
Android CLI
fornewid
0
220
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
640
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
190
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
390
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
130
Featured
See All Featured
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.1k
Building Adaptive Systems
keathley
44
3.2k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
260
The Spectacular Lies of Maps
axbom
PRO
1
900
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
210
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Technical Leadership for Architectural Decision Making
baasie
3
470
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
350
Designing for Performance
lara
611
70k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
Bash Introduction
62gerente
615
220k
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ςετΛ ൺֱత؆୯ʹ࣮Ͱ͖Δ
͝ਗ਼ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠ʂ