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
660
Flutter+Providerでウィジェットのテストを書く/widget-test-with-provider
Osamtimizer
August 07, 2020
Tweet
Share
More Decks by Osamtimizer
See All by Osamtimizer
osamtimizer
1
430
osamtimizer
1
830
osamtimizer
2
9.9k
osamtimizer
3
1.1k
Other Decks in Programming
See All in Programming
tourismgeek
1
130
grapecity_dev
1
190
christianweyer
PRO
0
280
bkuhlmann
2
310
doyaaaaaken
0
820
takahi5
1
430
legalforce
PRO
0
630
danilop
0
230
ryosukes
0
1.3k
grapecity_dev
0
170
hanasuke
1
540
mackee
0
570
Featured
See All Featured
destraynor
222
47k
yeseniaperezcruz
302
31k
danielanewman
200
20k
bryan
100
11k
michaelherold
225
8.5k
dougneiner
118
7.9k
shlominoach
176
7.5k
marcelosomers
221
15k
morganepeng
18
1.2k
imathis
479
150k
rasmusluckow
318
18k
smashingmag
283
47k
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ৼΔ͍ͷςετมߋʹڧ͍