[mobile][photos] Fix performance benchmarking config (#1195)
## Description - Fix broken integration test used for benchmarking gallery scroll performance. - Automate email and password entry. - Write script to run perf test.
This commit is contained in:
parent
bdd6663461
commit
ed4886a6a5
6 changed files with 147 additions and 127 deletions
17
mobile/gallery_scroll_perf_test.sh
Executable file
17
mobile/gallery_scroll_perf_test.sh
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Make sure to go through home_gallery_scroll_test.dart and
|
||||
# fill in email and password.
|
||||
# Specify destination directory for the perf results in perf_driver.dart.
|
||||
|
||||
|
||||
export ENDPOINT="https://api.ente.io"
|
||||
|
||||
flutter drive \
|
||||
--driver=test_driver/perf_driver.dart \
|
||||
--target=integration_test/home_gallery_scroll_test.dart \
|
||||
--dart-define=endpoint=$ENDPOINT \
|
||||
--profile --flavor independent \
|
||||
--no-dds
|
||||
|
||||
exit $?
|
|
@ -1,122 +0,0 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
import "package:integration_test/integration_test.dart";
|
||||
import "package:photos/main.dart" as app;
|
||||
import "package:scrollable_positioned_list/scrollable_positioned_list.dart";
|
||||
|
||||
void main() {
|
||||
group("App test", () {
|
||||
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||
testWidgets("Demo test", (tester) async {
|
||||
app.main();
|
||||
|
||||
await tester.pumpAndSettle(const Duration(seconds: 5));
|
||||
|
||||
await dismissUpdateAppDialog(tester);
|
||||
|
||||
//Automatically clicks the sign in button on the landing page
|
||||
final signInButton = find.byKey(const ValueKey("signInButton"));
|
||||
await tester.tap(signInButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
//Need to enter email address manually and clicks the login button automatically
|
||||
final emailInputField = find.byKey(const ValueKey("emailInputField"));
|
||||
final logInButton = find.byKey(const ValueKey("logInButton"));
|
||||
await tester.tap(emailInputField);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 12));
|
||||
await findAndTapFAB(tester, logInButton);
|
||||
|
||||
//Need to enter OTT manually and clicks the verify button automatically
|
||||
final ottVerificationInputField =
|
||||
find.byKey(const ValueKey("ottVerificationInputField"));
|
||||
final verifyOttButton = find.byKey(const ValueKey("verifyOttButton"));
|
||||
await tester.tap(ottVerificationInputField);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 6));
|
||||
await findAndTapFAB(tester, verifyOttButton);
|
||||
|
||||
//Need to enter password manually and clicks the verify button automatically
|
||||
final passwordInputField =
|
||||
find.byKey(const ValueKey("passwordInputField"));
|
||||
final verifyPasswordButton =
|
||||
find.byKey(const ValueKey("verifyPasswordButton"));
|
||||
await tester.tap(passwordInputField);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 10));
|
||||
await findAndTapFAB(tester, verifyPasswordButton);
|
||||
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await dismissUpdateAppDialog(tester);
|
||||
|
||||
//Grant permission to access photos. Must manually click the system dialog.
|
||||
final grantPermissionButton =
|
||||
find.byKey(const ValueKey("grantPermissionButton"));
|
||||
await tester.tap(grantPermissionButton);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||
|
||||
//Automatically skips backup
|
||||
final skipBackupButton = find.byKey(const ValueKey("skipBackupButton"));
|
||||
await tester.tap(skipBackupButton);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||
|
||||
await binding.traceAction(
|
||||
() async {
|
||||
//scroll gallery
|
||||
final scrollablePositionedList =
|
||||
find.byType(ScrollablePositionedList);
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -5000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 5000),
|
||||
4500,
|
||||
);
|
||||
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -7000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 7000),
|
||||
4500,
|
||||
);
|
||||
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -9000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 9000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
},
|
||||
reportKey: 'scrolling_summary',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> findAndTapFAB(WidgetTester tester, Finder finder) async {
|
||||
final RenderBox box = tester.renderObject(finder);
|
||||
final Offset desiredOffset = Offset(box.size.width - 10, box.size.height / 2);
|
||||
// Calculate the global position of the desired offset within the widget.
|
||||
final Offset globalPosition = box.localToGlobal(desiredOffset);
|
||||
await tester.tapAt(globalPosition);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||
}
|
||||
|
||||
Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
|
||||
await tester.tapAt(const Offset(0, 0));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
127
mobile/integration_test/home_gallery_scroll_test.dart
Normal file
127
mobile/integration_test/home_gallery_scroll_test.dart
Normal file
|
@ -0,0 +1,127 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_test/flutter_test.dart";
|
||||
import "package:integration_test/integration_test.dart";
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/main.dart" as app;
|
||||
import "package:scrollable_positioned_list/scrollable_positioned_list.dart";
|
||||
|
||||
void main() {
|
||||
group("Home gallery scroll test", () {
|
||||
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||
testWidgets("Home gallery scroll test", semanticsEnabled: false,
|
||||
(tester) async {
|
||||
// https://github.com/flutter/flutter/issues/89749#issuecomment-1029965407
|
||||
tester.testTextInput.register();
|
||||
|
||||
await runZonedGuarded(
|
||||
() async {
|
||||
///Ignore exceptions thrown by the app for the test to pass
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
FlutterError.onError = (FlutterErrorDetails errorDetails) {
|
||||
FlutterError.dumpErrorToConsole(errorDetails);
|
||||
};
|
||||
|
||||
app.main();
|
||||
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
|
||||
await dismissUpdateAppDialog(tester);
|
||||
|
||||
final signInButton = find.byKey(const ValueKey("signInButton"));
|
||||
await tester.tap(signInButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final emailInputField = find.byType(TextFormField);
|
||||
final logInButton = find.byKey(const ValueKey("logInButton"));
|
||||
//Fill email id here
|
||||
await tester.enterText(emailInputField, "enter email here");
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await tester.tap(logInButton);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||
|
||||
final passwordInputField =
|
||||
find.byKey(const ValueKey("passwordInputField"));
|
||||
final verifyPasswordButton =
|
||||
find.byKey(const ValueKey("verifyPasswordButton"));
|
||||
//Fill password here
|
||||
await tester.enterText(passwordInputField, "enter password here");
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await tester.tap(verifyPasswordButton);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await dismissUpdateAppDialog(tester);
|
||||
|
||||
//Grant permission to access photos. Must manually click the system dialog.
|
||||
final grantPermissionButton =
|
||||
find.byKey(const ValueKey("grantPermissionButton"));
|
||||
await tester.tap(grantPermissionButton);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||
|
||||
//Automatically skips backup
|
||||
final skipBackupButton =
|
||||
find.byKey(const ValueKey("skipBackupButton"));
|
||||
await tester.tap(skipBackupButton);
|
||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||
|
||||
await binding.traceAction(
|
||||
() async {
|
||||
//scroll gallery
|
||||
final scrollablePositionedList =
|
||||
find.byType(ScrollablePositionedList);
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -5000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 5000),
|
||||
4500,
|
||||
);
|
||||
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -7000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 7000),
|
||||
4500,
|
||||
);
|
||||
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, -9000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.fling(
|
||||
scrollablePositionedList,
|
||||
const Offset(0, 9000),
|
||||
4500,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
},
|
||||
reportKey: 'home_gallery_scrolling_summary',
|
||||
);
|
||||
},
|
||||
(error, stack) {
|
||||
Logger("gallery_scroll_test").info(error, stack);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
|
||||
await tester.tapAt(const Offset(0, 0));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
|
@ -650,7 +650,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.6.0"
|
||||
flutter_driver:
|
||||
dependency: "direct dev"
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
|
|
|
@ -191,8 +191,6 @@ flutter_intl:
|
|||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.7
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.1
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
|
@ -8,13 +8,13 @@ Future<void> main() {
|
|||
responseDataCallback: (data) async {
|
||||
if (data != null) {
|
||||
final timeline = driver.Timeline.fromJson(
|
||||
data['scrolling_summary'] as Map<String, dynamic>,
|
||||
data['home_gallery_scrolling_summary'] as Map<String, dynamic>,
|
||||
);
|
||||
|
||||
final summary = driver.TimelineSummary.summarize(timeline);
|
||||
|
||||
await summary.writeTimelineToFile(
|
||||
'scrolling_summary',
|
||||
'home_gallery_scrolling_summary',
|
||||
pretty: true,
|
||||
includeSummary: true,
|
||||
//Specify destination directory for the timeline files.
|
||||
|
|
Loading…
Reference in a new issue