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
雪かき部 #7 もう怖くない!SELECT文!
foursue
0
220
10年欲しかった音楽管理アプリを、AIと一緒に作りはじめた
judau
1
190
データ品質を壊しながらSnowflakeのAIに分析させてみた
kawanago
0
320
Claude Designがめちゃくちゃ便利なので使ってほしい
diggymo
0
170
2026-09-26 Platform Engineering Kaigi 2026 インフラとアプリの境界線と委譲の設計 / Drawing the Infra and App Line
masasuzu
0
500
BedrockとLambdaで作る リアルタイム進行型推理ゲーム
kawametho
0
120
AIに賢く動いてもらうためのコンテキスト〜Snowflake女子会 vol.8
snowwmn0824
0
200
営業オントロジーの作り方と、エージェントからの辿り方 ── ナレッジワークの現場から
kworkdev
PRO
1
200
3人で1000GPU超を統合運用する?マルチクラウド&オンプレを跨ぐ、構築と運用のリアル!
kazukun0716
2
770
AIに書かせて、プラットフォームで縛る ― EKSプラットフォームで実践した責任境界と権限設計
elmodev09
1
1.1k
DORA_Metrics.pdf
wagnerfusca
1
140
1人アドミンな私はAWSアカウント申請をSlackで完結したい!
ysuzuki
0
100
Featured
See All Featured
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
850
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
290
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1k
From π to Pie charts
rasagy
1
380
Technical Leadership for Architectural Decision Making
baasie
3
580
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
The Limits of Empathy - UXLibs8
cassininazir
1
690
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
530
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
960
The Cult of Friendly URLs
andyhume
79
7k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
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