forked from zulip/zulip-flutter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refer to `docs/integration_tests.md` for notes.
- Loading branch information
Showing
5 changed files
with
220 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Integration Tests | ||
|
||
Integration tests in flutter allow you to run test code | ||
on physical devices. These tests also allow performance | ||
metrics to be captured for analysis, and more accurately | ||
reflect production performance as it runs on real devices. | ||
|
||
For more background see | ||
[Flutter docs on integration testing][flutter-docs] | ||
|
||
[flutter-docs]: https://docs.flutter.dev/cookbook/testing/integration/profiling | ||
|
||
## Writing tests | ||
|
||
Writing an integration test is very much similar to | ||
writing widget tests: you have the same access to the | ||
`testWidgets` function as well as a `WidgetTester` to | ||
set up and run interactions. | ||
|
||
A big difference is the usage of an | ||
`IntegrationTestWidgetsFlutterBinding` binding | ||
that has a `traceAction` method that will capture | ||
performance metrics like widget build times as well | ||
as rendering times. | ||
|
||
These integration tests are recommended to be written | ||
in `integration_tests/`. | ||
|
||
The integration tests also interact with test driver | ||
code, which a sample exists as `test_driver/perf_driver.dart`. | ||
|
||
This test driver grabs performance metrics obtained | ||
by a `traceAction` call with a `reportKey: test` and | ||
writes both the entire timeline as well as a summary | ||
to disk inside the `build` directory. | ||
|
||
## Running tests | ||
|
||
The command to run an integration test: | ||
|
||
``` | ||
$ flutter drive \ | ||
--driver=test_driver/perf_driver.dart \ | ||
--target=integration_test/unreadmarker_test.dart \ | ||
-d <device_id> \ | ||
--profile \ | ||
--no-dds | ||
``` | ||
|
||
Obtain the `device_id` using `flutter devices`. | ||
|
||
Note: the `--no-dds` flag is required for running tests | ||
on mobile devices or simulators. It could be removed | ||
for other contexts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:integration_test/integration_test.dart'; | ||
import 'package:zulip/api/model/events.dart'; | ||
import 'package:zulip/api/model/model.dart'; | ||
import 'package:zulip/model/narrow.dart'; | ||
import 'package:zulip/model/store.dart'; | ||
import 'package:zulip/widgets/message_list.dart'; | ||
import 'package:zulip/widgets/store.dart'; | ||
|
||
import '../test/api/fake_api.dart'; | ||
import '../test/model/binding.dart'; | ||
import '../test/example_data.dart' as eg; | ||
import '../test/model/message_list_test.dart'; | ||
import '../test/model/test_store.dart'; | ||
|
||
void main() { | ||
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); | ||
TestZulipBinding.ensureInitialized(); | ||
|
||
late PerAccountStore store; | ||
late FakeApiConnection connection; | ||
|
||
Future<List<Message>> setupMessageListPage(WidgetTester tester, { | ||
Narrow narrow = const AllMessagesNarrow(), | ||
bool foundOldest = true, | ||
int? messageCount, | ||
List<Message>? messages, | ||
}) async { | ||
addTearDown(testBinding.reset); | ||
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot()); | ||
store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
connection = store.connection as FakeApiConnection; | ||
|
||
// prepare message list data | ||
store.addUser(eg.selfUser); | ||
assert((messageCount == null) != (messages == null)); | ||
messages ??= List.generate(messageCount!, (index) { | ||
return eg.streamMessage(id: index, sender: eg.selfUser, flags: [MessageFlag.read]); | ||
}); | ||
connection.prepare(json: | ||
newestResult(foundOldest: foundOldest, messages: messages).toJson()); | ||
|
||
await tester.pumpWidget( | ||
MaterialApp( | ||
home: GlobalStoreWidget( | ||
child: PerAccountStoreWidget( | ||
accountId: eg.selfAccount.id, | ||
child: MessageListPage(narrow: narrow))))); | ||
await tester.pumpAndSettle(); | ||
return messages; | ||
} | ||
|
||
testWidgets('Perf test', (tester) async { | ||
final messages = await setupMessageListPage(tester, messageCount: 500); | ||
final messageIds = messages.map((e) => e.id).toList(); | ||
await tester.pump(const Duration(seconds: 2)); | ||
|
||
await binding.traceAction( | ||
() async { | ||
store.handleEvent(UpdateMessageFlagsRemoveEvent( | ||
id: 1, | ||
flag: MessageFlag.read, | ||
messages: messageIds, | ||
messageDetails: {}, | ||
)); | ||
await tester.pumpAndSettle(); | ||
await tester.pumpAndSettle(); | ||
store.handleEvent(UpdateMessageFlagsAddEvent( | ||
id: 2, | ||
flag: MessageFlag.read, | ||
messages: messageIds, | ||
all: true, | ||
)); | ||
await tester.pumpAndSettle(); | ||
await tester.pumpAndSettle(); | ||
}, | ||
reportKey: 'test', | ||
); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import 'package:flutter_driver/flutter_driver.dart' as driver; | ||
import 'package:integration_test/integration_test_driver.dart'; | ||
|
||
Future<void> main() { | ||
return integrationDriver( | ||
responseDataCallback: (data) async { | ||
if (data != null) { | ||
final timeline = driver.Timeline.fromJson(data['test']); | ||
|
||
// Convert the Timeline into a TimelineSummary that's easier to | ||
// read and understand. | ||
final summary = driver.TimelineSummary.summarize(timeline); | ||
|
||
// Then, write the entire timeline to disk in a json format. | ||
// This file can be opened in the Chrome browser's tracing tools | ||
// found by navigating to chrome://tracing. | ||
// Optionally, save the summary to disk by setting includeSummary | ||
// to true | ||
await summary.writeTimelineToFile( | ||
'trace_output', | ||
pretty: true, | ||
includeSummary: true, | ||
); | ||
} | ||
}, | ||
); | ||
} |