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
Write tests for Provider
Search
Hiroki Matsue
May 22, 2019
Technology
880
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Write tests for Provider
"Flutter Meetup Tokyo #9"でのLT資料です。
https://flutter-jp.connpass.com/event/126419/
Hiroki Matsue
May 22, 2019
More Decks by Hiroki Matsue
See All by Hiroki Matsue
Getting Screenshots Automatically in Flutter
matsue
2
590
Optimize Flutter Workflow on Bitrise
matsue
2
1.4k
ややcomplexなBLoCへの対応
matsue
2
840
Flutterアプリの難読化とエラーレポート(iOS)
matsue
2
2.2k
いまさらだけど「良い通知」について考えてみた
matsue
4
11k
リテンション率を2倍にするための2つの視点
matsue
0
3.6k
リソースを効率的に使うためのバックログ活用事例
matsue
1
530
ローディング時のより良いUIの実装
matsue
2
2.1k
カウルにおけるElasiticsearchの導入と実例
matsue
0
970
Other Decks in Technology
See All in Technology
AIエージェント時代のPlatform as a Product —— テックリードがPdMとして回す発見・導入・計測 / Platform as a Product in the AI Agent Era
toshi0607
1
530
Oracle Cloud Infrastructure(OCI):Onboarding Session(はじめてのOCI/Oracle Supportご利⽤ガイド)
oracle4engineer
PRO
3
21k
「大丈夫そう?」をObservabilityで確かめる
mrmtsu
0
240
Coil3を内部実装から読み解く~キャッシュ戦略とAVIF画像の描画〜/nikkei-tech-talk50
nikkei_engineer_recruiting
0
180
【ゲームメーカーズスクランブル2026】『Shadowverse: Worlds Beyond』UIとアニメーションで実現する最高のユーザー体験を叶えるプロトタイピング
cygames
PRO
1
700
AI臭い文章とは何なのか
nasuvitz
36
75k
The seven pitfalls of AI (revised version)
ufried
0
140
大阪オフィスに Unitree Go2 がやってきたので Physical AI やってみた
dafujii
0
150
あなたの知らないAmazon VPC Route Server/Amazon VPC Route Server you don't know about
masakiokuda
0
160
VS Code × GitHub Copilot での Fabric 開発
ryomaru0825
1
200
スキルを作る、その前に!複数人で使われるスキルを 作るためのプロセス
junkifurukawa
1
120
AWS DevOps Agent スキルをつかいこなそう / Master AWS DevOps Agent Skills
kinunori
2
640
Featured
See All Featured
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
380
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
550
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
510
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
420
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
Unsuck your backbone
ammeep
672
58k
GitHub's CSS Performance
jonrohan
1033
470k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
340
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Transcript
Write tests for Provider Hiroki Matsue (@macs_6) May 22th, 2019
Flutter Meetup Tokyo #9
This talk is about How to test Provider classes
What is Provider Google I/O 2019ͷFlutterʹ͓͚Δ࣮ફతͳstateཧͷൃදͰ հ͞Εͨύοέʔδ Pragmatic State Management
in Flutter (Google I/O'19) https://youtu.be/d_m5csmrf7I
A dependency injection system built with widgets for widgets. provider
is mostly syntax sugar for InheritedWidget, to make common use-cases straightforward. https://github.com/rrousselGit/provider • ΄΅InheritedWidgetͷγϯλοΫεγϡΨʔ • BLoCΛ͏࣌ʹࣗલͰProvider૬ͷͷΛ࣮͍ͯͨ͠ ͣ
BLoC͚ʹॻ͍͍ͯͨInheritedWidgetΛͬͨProvider class CartProvider extends InheritedWidget { final CartBloc cartBloc; CartProvider({
Key key, CartBloc cartBloc, Widget child, }) : cartBloc = cartBloc ?? CartBloc(), super(key: key, child: child); @override bool updateShouldNotify(InheritedWidget oldWidget) => true; static CartBloc of(BuildContext context) => (context.inheritFromWidgetOfExactType(CartProvider) as CartProvider) .cartBloc; } final cartBloc = CartProvider.of(context); https://github.com/filiph/stateexperiments/blob/19c321bbc62ac10855751124e3ea9701e583d6ea/shared/lib/src/bloc/cartprovider.dart
ProviderύοέʔδΛ͏ͱ͜͏ͳΔ Provider<ExampleBloc>( builder: (_) => ExampleBloc(), dispose: (_, value) =>
value.dispose(), child: ExampleBloc(), ); final bloc = Provider.of<ExampleBloc>(context)
શ෦BLoCͰॻͭ͘ΓͳΒbloc_providerύοέʔδ bloc is disposed automatically https://pub.dev/packages/bloc_provider BlocProvider<ExampleBloc>( creator: (_context, _bag)
=> ExampleBloc(), child: Example(), )
ProviderΛ͏ͱ • streamRxDartΛΘͣʹෳWidgetؒͷstateΛཧͰ͖ ֶͯशίετ͕͍ • ඞཁʹԠͯ͡BLoCಋೖͰ͖Δ
How to write tests?
class Counter with ChangeNotifier { Counter( this._number, ); factory Counter.withInitialValues({
int number = 0, }) { return Counter(number); } int _number; int get number => _number; void increment() { _number++; notifyListeners(); } }
notifyListeners()Λແࢹ͢ΔͳΒ test('increment', () { final counter = Counter.withInitialValues(); expect(counter.number, 0);
counter.increment(); expect(counter.number, 1); });
֤छύοέʔδͷςετͰtestWidgetsΛ͍ͬͯΔ
UIςετͱͯ͠ widgetΛςετ͚ʹॳظԽ͢Δ
testWidgets("increment", (tester) async { final key = GlobalKey(); await tester.pumpWidget(
ChangeNotifierProvider( builder: (context) => Counter.withInitialValues(), child: MaterialApp( home: Consumer<Counter>( builder: (context, counter, child) => FlatButton( key: key, onPressed: () => counter.increment(), child: Text(counter.number.toString())), ), ), ), ); expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); await tester.tap(find.byKey(key)); await tester.pumpAndSettle(); expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); });
֤छύοέʔδͷςετͰݟΒΕΔ
͍ճ͢widgetΛอଘ͓ͯ͘͠ final tree = ChangeNotifierProvider( builder: (context) => Counter.withInitialValues(), child:
MaterialApp( home: Consumer<Counter>( builder: (context, counter, child) => FlatButton( key: key, onPressed: () => counter.increment(), child: Text(counter.number.toString())), ), ), );
ʹରͯ͠ݕূΛߦ͏ testWidgets("increment", (tester) async { final key = GlobalKey(); int
number; await tester.pumpWidget( ChangeNotifierProvider( builder: (context) => Counter.withInitialValues(), child: MaterialApp( home: Consumer<Counter>(builder: (context, counter, child) { number = counter.number; return FlatButton( key: key, onPressed: () => counter.increment(), child: Container(), ); }), ), ), ); });
notifierΛcontext͔Βऔಘͯ͠ݕূ͢Δ testWidgets('works with MultiProvider', (tester) async { final key =
GlobalKey(); var notifier = ChangeNotifier(); await tester.pumpWidget(MultiProvider( providers: [ ChangeNotifierProvider.value(notifier: notifier), ], child: Container(key: key), )); expect(Provider.of<ChangeNotifier>(key.currentContext), notifier); }); https://github.com/rrousselGit/provider/blob/fe778651565f7563dc4a1b2afb513119c5424761/test/changenotifierprovider_test.dart#L11-
·ͱΊ • testWidgets Λͬͯςετॻ͘ • ֤छύοέʔδΛݟΔͱςετͷهड़ΛݮΒ͕͢৭ʑݟ ΒΕΔ • ରͷwidgetΛ͍ճ͢ •
มʹೖΕͯݕূ͢Δ • notifierΛऔಘ͢Δ
References • Developer Questͷςετ: https://github.com/2d-inc/ developerquest/blob/master/test/worldtest.dart • Providerύοέʔδͷςετ: https://github.com/ rrousselGit/provider/blob/
fe778651565f7563dc4a1b2afb513119c5424761/test/ changenotifierprovider_test.dart • FlutterຊମͷChangeNotifierςετ: https://github.com/ flutter/flutter/blob/
Thanks