應用的功能越多,手動測試的難度就越大。一套完整的自動化測試將幫助您確保您的應用在發(fā)布之前正確執(zhí)行,同時保留您的功能和錯誤修復速度。
有很多種自動化測試。這些總結如下:
這里是一個表格,總結了在不同類型測試之間進行選擇的權衡:
單元測試 | widget測試 | 集成測試 | |
---|---|---|---|
Confidence | Low | Higher | Highest |
維護成本 | Low | Higher | Highest |
依賴 | Few | More | Lots |
執(zhí)行速度 | Quick | Slower | Slowest |
提示: 作為一個經(jīng)驗法則,經(jīng)過充分測試的應用程序具有非常多的單元和widget測試,通過代碼覆蓋(code coverage)進行跟蹤,以及覆蓋所有重要使用場景的大量集成測試。
某些Flutter庫,如dart:ui在獨立的Dart VM附帶的Dart SDK的中是不可用。該flutter test命令允許您在本地Dart VM中運行測試,使用無頭版(不會顯示UI)的Flutter引擎。 使用這個命令你可以運行任何測試,不管它是否依賴于Flutter的庫。
使用package:test,編寫一個Flutter單元測試。編寫單元測試使用的package:test文檔在這里。
例如:
將此文件添加到 test/unit_test.dart:
import 'package:test/test.dart';
void main() {
test('my first unit test', () {
var answer = 42;
expect(answer, 42);
});
}
另外,您必須將以下內(nèi)容添加到您的pubspec.yaml:
dev_dependencies:
flutter_test:
sdk: flutter
即使你的測試本身沒有明確導入flutter_test,也需要這樣做 ,因為測試框架本身在后臺也使用了它。
要運行測試,從您的項目目錄(而不是從test子目錄)運行 flutter test test/unit_test.dart
要運行所有測試,請從項目目錄運行flutter test
您以類似于單元測試的方式實現(xiàn)widget測試。要在測試中執(zhí)行與widget的交互,請使用Flutter提供的WidgetTester。 例如,您可以發(fā)送點擊和滾動手勢。您還可以使用WidgetTester在widget樹中查找子widget、讀取文本、驗證widget屬性的值是否正確。
例子:
將此文件添加到test/widget_test.dart:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('my first widget test', (WidgetTester tester) async {
// You can use keys to locate the widget you need to test
var sliderKey = new UniqueKey();
var value = 0.0;
// Tells the tester to build a UI based on the widget tree passed to it
await tester.pumpWidget(
new StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return new MaterialApp(
home: new Material(
child: new Center(
child: new Slider(
key: sliderKey,
value: value,
onChanged: (double newValue) {
setState(() {
value = newValue;
});
},
),
),
),
);
},
),
);
expect(value, equals(0.0));
// Taps on the widget found by key
await tester.tap(find.byKey(sliderKey));
// Verifies that the widget updated the value correctly
expect(value, equals(0.5));
});
}
運行 flutter test test/widget_test.dart.
查看所有可用于widget測試的package:flutter_test API
為了幫助調(diào)試widget測試,您可以使用debugDumpApp() 函數(shù)來可視化測試的UI狀態(tài), 或者只是簡單的在您的首選運行時環(huán)境(例如模擬器或設備)中運行flutter run test/widget_test.dart以查看您的測試運行。 在運行flutter run的測試的會話期間,您還可以交互式地點擊Flutter工具的部分屏幕來打印建議的Finder。
如果您熟悉Selenium/WebDriver(web),Espresso(Android)或UI Automation(iOS),那么Flutter Driver就是Flutter與這些集成測試工具的等價物。 此外,F(xiàn)lutter Driver還提供API以記錄測試執(zhí)行的操作的性能跟蹤(又名時間軸)。
Flutter的Driver是:
這兩者允許你:
要使用flutter_driver,您必須將以下塊添加到您的pubspec.yaml:
dev_dependencies:
flutter_driver:
sdk: flutter
一個指令化的應用程序是一個Flutter應用程序,它啟用了Flutter Driver 擴展。啟用擴展請調(diào)用enableFlutterDriverExtension()。
例:
假設你有一個入口點的應用程序my_app/lib/main.dart。要創(chuàng)建它的指令化版本,請在my_app/test_driver/下創(chuàng)建一個Dart文件。 在您正在測試的功能之后命名它; 接下來定位到my_app/test_driver/user_list_scrolling.dart:
// 這一行導入擴展
import 'package:flutter_driver/driver_extension.dart';
void main() {
// 啟用擴展
enableFlutterDriverExtension();
// Call the `main()` of your app or call `runApp` with whatever widget
// you are interested in testing.
}
集成測試是一個簡單的package:test測試,它使用Flutter Driver API告訴應用程序執(zhí)行什么操作,然后驗證應用程序是否執(zhí)行了此操作。
例子:
為了有意思起見,我們也讓我們的測試記錄下性能跟蹤(performance timeline)。我們創(chuàng)建一個user_list_scrolling_test.dart測試文件位于my_app/test_driver/下:
import 'dart:async';
// Imports the Flutter Driver API
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
void main() {
group('scrolling performance test', () {
FlutterDriver driver;
setUpAll(() async {
// 連接app
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
if (driver != null) {
// 關閉連接
driver.close();
}
});
test('measure', () async {
// 記錄閉包中的performance timeline
Timeline timeline = await driver.traceAction(() async {
// Find the scrollable user list
SerializableFinder userList = find.byValueKey('user-list');
// Scroll down 5 times
for (int i = 0; i < 5; i++) {
// Scroll 300 pixels down, for 300 millis
await driver.scroll(
userList, 0.0, -300.0, new Duration(milliseconds: 300));
// Emulate a user's finger taking its time to go back to the original
// position before the next scroll
await new Future<Null>.delayed(new Duration(milliseconds: 500));
}
// Scroll up 5 times
for (int i = 0; i < 5; i++) {
await driver.scroll(
userList, 0.0, 300.0, new Duration(milliseconds: 300));
await new Future<Null>.delayed(new Duration(milliseconds: 500));
}
});
// The `timeline` object contains all the performance data recorded during
// the scrolling session. It can be digested into a handful of useful
// aggregate numbers, such as "average frame build time".
TimelineSummary summary = new TimelineSummary.summarize(timeline);
summary.writeSummaryToFile('stocks_scroll_perf', pretty: true);
summary.writeTimelineToFile('stocks_scroll_perf', pretty: true);
});
});
}
要在Android設備上運行測試,請通過USB將設備連接到計算機并啟用USB調(diào)試。然后運行以下命令:
flutter drive --target=my_app/test_driver/user_list_scrolling.dart
該命令將:
您可能想知道該命令如何找到正確的測試文件。flutter drive 命令使用一種約定來查找與--target應用程序在同一目錄中具有相同文件名但是具有_test后綴的測試文件。
更多建議: