使用集成测试测量性能
对于移动应用程序而言,性能对于用户体验至关重要。用户期望应用程序能够实现流畅的滚动和有意义的动画,并且不会出现卡顿或跳帧(称为“卡顿”)。如何确保您的应用程序在各种设备上都能避免卡顿?
有两种选择:首先,在不同的设备上手动测试应用程序。虽然这种方法可能适用于较小的应用程序,但随着应用程序规模的增长,它会变得越来越麻烦。或者,运行一个集成测试,该测试执行特定任务并记录性能时间线。然后,检查结果以确定应用程序的特定部分是否需要改进。
在本菜谱中,学习如何编写一个测试,该测试在执行特定任务时记录性能时间线并将结果摘要保存到本地文件。
本菜谱使用以下步骤
- 编写一个测试,滚动浏览项目列表。
- 记录应用程序的性能。
- 将结果保存到磁盘。
- 运行测试。
- 查看结果。
1. 编写一个测试,滚动浏览项目列表
#在本菜谱中,记录应用程序在滚动浏览项目列表时的性能。为了专注于性能分析,本菜谱建立在小部件测试中的 滚动 菜谱的基础之上。
按照该菜谱中的说明创建应用程序并编写测试以验证一切按预期工作。
2. 记录应用程序的性能
#接下来,记录应用程序在滚动浏览列表时的性能。使用 traceAction()
方法(由 IntegrationTestWidgetsFlutterBinding
类提供)执行此任务。
此方法运行提供的函数并记录一个 Timeline
,其中包含有关应用程序性能的详细信息。此示例提供了一个函数,该函数滚动浏览项目列表,确保显示特定项目。当函数完成时,traceAction()
创建一个包含 Timeline
的报告数据 Map
。
在运行多个 traceAction
时指定 reportKey
。默认情况下,所有 Timelines
都使用键 timeline
存储,在此示例中,reportKey
更改为 scrolling_timeline
。
await binding.traceAction(
() async {
// Scroll until the item to be found appears.
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
},
reportKey: 'scrolling_timeline',
);
3. 将结果保存到磁盘
#现在您已捕获了性能时间线,您需要一种方法来查看它。Timeline
对象提供了有关所有发生事件的详细信息,但它没有提供一种方便的方法来查看结果。
因此,将 Timeline
转换为 TimelineSummary
。TimelineSummary
可以执行两个任务,使查看结果更容易
- 在磁盘上写入一个 JSON 文档,该文档总结了
Timeline
中包含的数据。此摘要包含有关跳帧次数、最慢构建时间等信息。 - 将完整的
Timeline
作为 JSON 文件保存到磁盘。此文件可以使用 Chrome 浏览器的跟踪工具(位于chrome://tracing
)打开。
要捕获结果,请在 test_driver
文件夹中创建一个名为 perf_driver.dart
的文件并添加以下代码
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['scrolling_timeline'] as Map<String, dynamic>,
);
// 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(
'scrolling_timeline',
pretty: true,
includeSummary: true,
);
}
},
);
}
integrationDriver
函数具有一个 responseDataCallback
,您可以对其进行自定义。默认情况下,它将结果写入 integration_response_data.json
文件,但您可以将其自定义为像本示例一样生成摘要。
4. 运行测试
#在配置测试以捕获性能 Timeline
并将结果摘要保存到磁盘后,使用以下命令运行测试
flutter drive \
--driver=test_driver/perf_driver.dart \
--target=integration_test/scrolling_test.dart \
--profile
--profile
选项表示编译应用程序以用于“性能模式”而不是“调试模式”,以便基准测试结果更接近最终用户体验。
5. 查看结果
#测试成功完成之后,项目根目录下的 build
目录包含两个文件
scrolling_summary.timeline_summary.json
包含摘要。使用任何文本编辑器打开该文件以查看其中包含的信息。使用更高级的设置,您可以在每次测试运行时保存摘要并创建结果图表。scrolling_timeline.timeline.json
包含完整的时间线数据。使用 Chrome 浏览器的跟踪工具(位于chrome://tracing
)打开该文件。跟踪工具提供了一个方便的界面,用于检查时间线数据以发现性能问题的根源。
示例摘要
#{
"average_frame_build_time_millis": 4.2592592592592595,
"worst_frame_build_time_millis": 21.0,
"missed_frame_build_budget_count": 2,
"average_frame_rasterizer_time_millis": 5.518518518518518,
"worst_frame_rasterizer_time_millis": 51.0,
"missed_frame_rasterizer_budget_count": 10,
"frame_count": 54,
"frame_build_times": [
6874,
5019,
3638
],
"frame_rasterizer_times": [
51955,
8468,
3129
]
}
完整示例
#integration_test/scrolling_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:scrolling/main.dart';
void main() {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Counter increments smoke test', (tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp(
items: List<String>.generate(10000, (i) => 'Item $i'),
));
final listFinder = find.byType(Scrollable);
final itemFinder = find.byKey(const ValueKey('item_50_text'));
await binding.traceAction(
() async {
// Scroll until the item to be found appears.
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
},
reportKey: 'scrolling_timeline',
);
});
}
test_driver/perf_driver.dart
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['scrolling_timeline'] as Map<String, dynamic>,
);
// 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(
'scrolling_timeline',
pretty: true,
includeSummary: true,
);
}
},
);
}
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面最后更新于 2024-05-20。 查看源代码 或 报告问题.