Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Flutter+Providerでウィジェットのテストを書く/widget-test-with-provider
Osamtimizer
August 07, 2020
Programming
0
1.2k
Flutter+Providerでウィジェットのテストを書く/widget-test-with-provider
Osamtimizer
August 07, 2020
Tweet
Share
More Decks by Osamtimizer
See All by Osamtimizer
SUZURIにおけるSREの取り組み/SRE-and-SUZURI
osamtimizer
0
830
suzuri-data-driven-2020
osamtimizer
1
1.2k
pepabo-with-flutter-2020
osamtimizer
1
1.6k
SUZURIのAndroidアプリをFlutterで作っている話 / SUZURI-meets-Flutter
osamtimizer
2
20k
RubyのOSSコードリーディング / ruby-oss-code-reading
osamtimizer
4
2k
Other Decks in Programming
See All in Programming
低レイヤーから始める GUI
fadis
18
9.2k
Rによる大規模データの処理
s_uryu
2
610
Enumを自動で網羅的にテストしてみた
estie
0
1.2k
Cloudflare WorkersでGoを動かすライブラリを作っている話
syumai
1
290
Excelの助けを借りて楽にシナリオを作ろう
rpa_niiyama
0
190
状態ってなに?🙃
taro28
0
260
中小企業開発事例から見るサーバーレス
seike460
PRO
4
1.5k
Azure Functionsをサクッと開発、サクッとデプロイ/vscodeconf2023-baba
nina01
1
320
あなたと 「|」 したい・・・
track3jyo
PRO
2
1k
Writing Greener Java Applications
hollycummins
0
330
%q is for Quine
koic
0
390
23年のJavaトレンドは?Quarkusで理解するコンテナネイティブJava
tatsuya1bm
1
110
Featured
See All Featured
The Cult of Friendly URLs
andyhume
68
5.1k
Stop Working from a Prison Cell
hatefulcrawdad
263
18k
It's Worth the Effort
3n
177
26k
WebSockets: Embracing the real-time Web
robhawkes
58
6k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
349
27k
A Modern Web Designer's Workflow
chriscoyier
690
180k
In The Pink: A Labor of Love
frogandcode
132
21k
Bash Introduction
62gerente
601
210k
The Language of Interfaces
destraynor
149
21k
StorybookのUI Testing Handbookを読んだ
zakiyama
8
3.2k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
351
21k
Designing Experiences People Love
moore
130
22k
Transcript
࣌ాཧ(.01FQBCP *OD %BSU.FFUVQ0TBLB 'MVUUFS 1SPWJEFSͰ ΟδΣοτͷςετΛॻ͘
ϞόΠϧ8FCΞϓϦέʔγϣϯΤϯδχΞ ࣌ాཧ!PTBNUJNJ[FS 46;63*ࣄۀ෦ϓϩμΫτνʔϜ IUUQTPTBNUJNJ[FSIBUFOBCMPHDPN
None
ΦϦδφϧάοζ͕࡞ΕΔɺചΕΔɺങ͑Δɻ ը૾Λ1ຕΞοϓ ͢Δ͚ͩ ࣗಈతʹ͕ Ͱ͖·͢ ࣗͰങ͑Δ͠ ചΔ͜ͱͰ͖·͢
None
None
͡Ίʹ wࢿྉޙ΄ͲΠϯλʔωοτ্Ͱެ։͠·͢ wIUUQTTQFBLFSEFDLDPNPTBNUJNJ[FS
ࠓ͢͜ͱ w'MVUUFSͷ8JEHFU5FTU w1SPWJEFSʹґଘͨ͠ΟδΣοτͷ8JEHFU5FTUΛॻ͘ w·ͱΊ
8JEHFU5FTU
ΟδΣοτʹର͢Δςετ
'MVUUFSʹ͓͚Δςετ w6OJU5FTU୯ҰͷϝιουΫϥεʹର͢Δςετ w*OUFHSBUJPO5FTUΞϓϦશମʹର͢Δςετ w8JEHFU5FTU୯ҰͷΟδΣοτʹର͢Δςετ
'MVUUFSʹ͓͚Δςετ w6OJU5FTU୯ҰͷϝιουΫϥεʹର͢Δςετ w*OUFHSBUJPO5FTUΞϓϦશମʹର͢Δςετ w8JEHFU5FTU୯ҰͷΟδΣοτʹର͢Δςετ
ΟδΣοτͷԿΛ ςετ͢Δʁ
ΟδΣοτͷ ݟͨͱڍಈ
8JEHFU5FTU͕Χόʔ͢Δͷ wΟδΣοτએݴతʹهड़ ˠঢ়ଶΛ༩͑ͨͱ͖ɺఆͨ͠ݟͨʹͳΔ͔ʁ wϢʔβʔͷೖྗΠϕϯτͳͲΛड͚ͯԿ͔Λ͢ΔΟδΣοτ͋Δ ˠΠϕϯτ͕ൃՐͨ͠ͱ͖ɺఆͨ͠ڍಈΛ͢Δ͔ʁ
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('MyWidget has a title and message',
(WidgetTester tester) async { // ςετͷ४උ await tester.pumpWidget(MyWidget(title: 'T', message: 'M')); // ΟδΣοτͷ୳ࡧ final titleFinder = find.text('T'); final messageFinder = find.text('M'); // ϚονϟͰΟδΣοτΛݕূ expect(titleFinder, findsOneWidget); expect(messageFinder, findsOneWidget); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('MyWidget has a title and message',
(WidgetTester tester) async { // ςετͷ४උ await tester.pumpWidget(MyWidget(title: 'T', message: 'M')); // ΟδΣοτͷ୳ࡧ final titleFinder = find.text('T'); final messageFinder = find.text('M'); // ϚονϟͰΟδΣοτΛݕূ expect(titleFinder, findsOneWidget); expect(messageFinder, findsOneWidget); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('MyWidget has a title and message',
(WidgetTester tester) async { // ςετͷ४උ await tester.pumpWidget(MyWidget(title: 'T', message: 'M')); // ΟδΣοτͷ୳ࡧ final titleFinder = find.text('T'); final messageFinder = find.text('M'); // ϚονϟͰΟδΣοτΛݕূ expect(titleFinder, findsOneWidget); expect(messageFinder, findsOneWidget); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('MyWidget has a title and message',
(WidgetTester tester) async { // ςετͷ४උ await tester.pumpWidget(MyWidget(title: 'T', message: 'M')); // ΟδΣοτͷ୳ࡧ final titleFinder = find.text('T'); final messageFinder = find.text('M'); // ϚονϟͰΟδΣοτΛݕূ expect(titleFinder, findsOneWidget); expect(messageFinder, findsOneWidget); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('Add and remove a todo', (WidgetTester
tester) async { await tester.pumpWidget(TodoList()); // WidgetTesterܦ༝ͰΟδΣοτΛૢ࡞ await tester.enterText(find.byType(TextField), 'hi'); await tester.tap(find.byType(FloatingActionButton)); // ΟδΣοτΛϦϏϧυ await tester.pump(); expect(find.text('hi'), findsOneWidget); await tester.drag(find.byType(Dismissible), Offset(500.0, 0.0)); await tester.pumpAndSettle(); expect(find.text('hi'), findsNothing); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('Add and remove a todo', (WidgetTester
tester) async { await tester.pumpWidget(TodoList()); // WidgetTesterܦ༝ͰΟδΣοτΛૢ࡞ await tester.enterText(find.byType(TextField), 'hi'); await tester.tap(find.byType(FloatingActionButton)); // ΟδΣοτΛϦϏϧυ await tester.pump(); expect(find.text('hi'), findsOneWidget); await tester.drag(find.byType(Dismissible), Offset(500.0, 0.0)); await tester.pumpAndSettle(); expect(find.text('hi'), findsNothing); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUΛॻ͍ͯΈΔ void main() { testWidgets('Add and remove a todo', (WidgetTester
tester) async { await tester.pumpWidget(TodoList()); // WidgetTesterܦ༝ͰΟδΣοτΛૢ࡞ await tester.enterText(find.byType(TextField), 'hi'); await tester.tap(find.byType(FloatingActionButton)); // ΟδΣοτΛϦϏϧυ await tester.pump(); expect(find.text('hi'), findsOneWidget); await tester.drag(find.byType(Dismissible), Offset(500.0, 0.0)); await tester.pumpAndSettle(); expect(find.text('hi'), findsNothing); }); } ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTUͷ࣮ߦ $ flutter test 00:05 +1: All tests passed! ࢀߟIUUQTqVUUFSEFWEPDTDPPLCPPLUFTUJOHXJEHFUJOUSPEVDUJPO
8JEHFU5FTU wݕূ͍ͨ͠ΟδΣοτΛ5FTUFSʹ͢ wίʔυʹΑͬͯΟδΣοτΛૢ࡞ͯ͠ݕূ wཁૉ͕ଘࡏ͢Δ͔ wΠϕϯτൃՐ࣌ʹఆͨ͠ڍಈʹͳΔ͔
8JEHFU5FTUͷࠔΓͲ͜Ζ w6OJU5FTUͱൺֱ͢Δͱɺมߋʹऑ͍ w6*ͦͦมߋ͞Ε͍͢ wςετͳΔ͘$*Ͱࣗಈ࣮ߦ͍ͤͨ͞ w͋·Γڽͬͨ8JEHFU5FTUΛॻ͖͗͢Δͱɺςετͷमਖ਼ʹΘΕΔ
1SPWJEFSʹґଘͨ͠ ΟδΣοτͷςετ
1SPWJEFSʹґଘͨ͠ΟδΣοτͷςετ w1SPWJEFS w'MVUUFSͰͷঢ়ଶཧΛ͘͢͢͠Δύοέʔδ wґଘ͍ͯ͠ΔΟδΣοτͷ8JEHFU5FTUʹ͕ඞཁ w͔͠͠ɺϝϦοτ͋Δ
αϯϓϧΞϓϦ
ˠ
αϯϓϧΞϓϦ wϝʔϧΞϓϦ wΞϓϦΛىಈ͢Δͱ࠷৽ͷϝʔϧΛऔಘͯ͠දࣔ wϦετΛλοϓ͢Δͱϝʔϧͷৄࡉը໘ʹϓογϡભҠ
αϯϓϧΞϓϦ .BUFSJBM"QQ )PNF 4DB⒎PME .BJM-JTU -JTU5JMF 1SPWJEFS -JTU5JMF -JTU5JMF
αϯϓϧΞϓϦ .BUFSJBM"QQ )PNF 4DB⒎PME .BJM-JTU -JTU5JMF 1SPWJEFS -JTU5JMF -JTU5JMF
αϯϓϧΞϓϦ class MailList extends StatefulWidget { … } class _MailListState
extends State<MailList> { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { // initStateྃޙʹϝʔϧΛऔಘ͢ΔΞΫγϣϯΛൃߦ context.read<MailStore>().fetchMails(); }); } …
αϯϓϧΞϓϦ class MailList extends StatefulWidget { … } class _MailListState
extends State<MailList> { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { // initStateྃޙʹϝʔϧΛऔಘ͢ΔΞΫγϣϯΛൃߦ context.read<MailStore>().fetchMails(); }); } …
αϯϓϧΞϓϦ Widget build(BuildContext context) { // Providerܦ༝Ͱද͖ࣔ͢ϝʔϧҰཡΛऔಘ final mails =
context.watch<MailStore>().mails; return Container( child: ListView.builder( itemBuilder: (context, index) { return ListTile( … onTap: () async { // ListTileλοϓ࣌ʹϝʔϧৄࡉʹભҠ Navigator.of(context).pushNamed( MailDetail.routeName, arguments: mails[index], );
αϯϓϧΞϓϦͰςετ͍ͨ͠ϙΠϯτ wΟδΣοτͷॳճϏϧυ࣌ʹϦΫΤετΛ࣮ߦͯ͠ϝʔϧΛऔಘ wϝʔϧΛλοϓ͢Δͱɺͦͷϝʔϧͷৄࡉը໘ભҠ
αϯϓϧΞϓϦͰςετ͍ͨ͠ϙΠϯτ wΟδΣοτͷॳճϏϧυ࣌ʹϦΫΤετΛ࣮ߦͯ͠ϝʔϧΛऔಘ wϝʔϧΛλοϓ͢Δͱɺͦͷϝʔϧͷৄࡉը໘ભҠ
αϯϓϧΞϓϦͷ8JEHFU5FTU void main() { testWidgets("initialization", (WidgetTester tester) async { //ςετ༻ͷStoreΛ༻ҙ
final store = MailStore(); expect(store.mails.length, 0); await tester.pumpWidget( // testerʹ͢ΟδΣοτΛProviderͰϥοϓ ChangeNotifierProvider.value( value: store, child: Home(), ), ); // Storeͷঢ়ଶΛݕূ expect(store.mails.length, 20);
αϯϓϧΞϓϦͷ8JEHFU5FTU void main() { testWidgets("initialization", (WidgetTester tester) async { //ςετ༻ͷStoreΛ༻ҙ
final store = MailStore(); expect(store.mails.length, 0); await tester.pumpWidget( // testerʹ͢ΟδΣοτΛProviderͰϥοϓ ChangeNotifierProvider.value( value: store, child: Home(), ), ); // Storeͷঢ়ଶΛݕূ expect(store.mails.length, 20);
αϯϓϧΞϓϦͷ8JEHFU5FTU void main() { testWidgets("initialization", (WidgetTester tester) async { //ςετ༻ͷStoreΛ༻ҙ
final store = MailStore(); expect(store.mails.length, 0); await tester.pumpWidget( // testerʹ͢ΟδΣοτΛProviderͰϥοϓ ChangeNotifierProvider.value( value: store, child: Home(), ), ); // Storeͷঢ়ଶΛݕূ expect(store.mails.length, 20);
αϯϓϧΞϓϦͷ8JEHFU5FTU void main() { testWidgets("initialization", (WidgetTester tester) async { //ςετ༻ͷStoreΛ༻ҙ
final store = MailStore(); expect(store.mails.length, 0); await tester.pumpWidget( // testerʹ͢ΟδΣοτΛProviderͰϥοϓ ChangeNotifierProvider.value( value: store, child: Home(), ), ); // Storeͷঢ়ଶΛݕূ expect(store.mails.length, 20);
1SPWJEFSΛ͏8JEHFU5FTU wςετͷର6*Ͱͳ͘ɺΟδΣοτͷৼΔ͍ w௨ৗͷ8JEHFU5FTUͱൺֱ͢Δͱɺมߋʹڧ͍ wςετΛॻ͘ෛՙΛ͑ͭͭɺมߋʹڧ͍ΞϓϦΛ࡞Γ͘͢ͳΔ
·ͱΊ w8JEHFU5FTU໊લͷ௨ΓΟδΣοτʹର͢Δςετ wίʔυͰΟδΣοτͷૢ࡞Λهड़Ͱ͖Δ wมߋʹऑ͍͕ɺ1SPWJEFSͱΈ߹ΘͤΔͱৼΔ͍ͷςετ͕Ͱ͖Δ wৼΔ͍ͷςετมߋʹڧ͍