做(zuò)自(zì)由與創造的先行(xíng)者

Flutter 測試應用

Flutter開(kāi)發手冊

介紹

應用的功能(néng)越多,手動測試的難度就越大。一(yī)套完整的自(zì)動化測試将幫助您确保您的應用在發布之前正确執行(xíng),同時(shí)保留您的功能(néng)和(hé)錯誤修複速度。

有很(hěn)多種自(zì)動化測試。這(zhè)些總結如(rú)下(xià):

單元測試:測試單一(yī)功能(néng)、方法或類。例如(rú),被測單元的外(wài)部依賴性通(tōng)常被模拟出來,如(rú)package:mockito。 單元測試通(tōng)常不會讀取/寫入磁盤、渲染到屏幕,也不會從(cóng)運行(xíng)測試的進程外(wài)部接收用戶操作(zuò)。單元測試的目标是在各種條件下(xià)驗證邏輯單元的正确性。

widget 測試:(在其它UI框架稱為(wèi) 組件測試) 測試的單個widget。測試widget涉及多個類,并且需要(yào)提供适當的widget生命周期上(shàng)下(xià)文的測試環境。 例如(rú),它應該能(néng)夠接收和(hé)響應用戶操作(zuò)和(hé)事件,執行(xíng)布局并實例化子widget。widget測試因此比單元測試更全面。 然而,就像一(yī)個單元測試一(yī)樣,一(yī)個widget測試的環境被一(yī)個比完整的UI系統簡單得多的實現所取代。小部件測試的目标是驗證小部件的UI如(rú)預期的那(nà)樣的外(wài)觀和(hé)交互。

集成測試: 測試一(yī)個完整的應用程序或應用程序的很(hěn)大一(yī)部分。通(tōng)常,集成測試可(kě)以在真實設備或OS仿真器上(shàng)運行(xíng),例如(rú)iOS Simulator或Android Emulator。 被測試的應用程序通(tōng)常與測試驅動程序代碼隔離,以避免結果偏差。集成測試的目标是驗證應用程序作(zuò)為(wèi)一(yī)個整體正确運行(xíng),它所組成的所有widget如(rú)預期的那(nà)樣相互集成。 您還可(kě)以使用集成測試來驗證應用的性能(néng)。

單元測試

某些Flutter庫,如(rú)dart:ui在獨立的Dart VM附帶的Dart SDK的中是不可(kě)用。該flutter test命令允許您在本地(dì)Dart VM中運行(xíng)測試,使用無頭版(不會顯示UI)的Flutter引擎。 使用這(zhè)個命令你可(kě)以運行(xíng)任何測試,不管它是否依賴于Flutter的庫。

使用package:test,編寫一(yī)個Flutter單元測試。編寫單元測試使用的package:test文檔在這(zhè)裏。

例如(rú):

将此文件添加到 test/unit_test.dart:

import 'package:test/test.dart';

void main() {

test('my first unit test', () {

var answer = 42;

expect(answer, 42);

});

}

另外(wài),您必須将以下(xià)內(nèi)容添加到您的pubspec.yaml:

dev_dependencies:

flutter_test:

sdk: flutter

即使你的測試本身沒有明(míng)确導入flutter_test,也需要(yào)這(zhè)樣做(zuò) ,因為(wèi)測試框架本身在後台也使用了(le)它。

要(yào)運行(xíng)測試,從(cóng)您的項目目錄(而不是從(cóng)test子目錄)運行(xíng) flutter test test/unit_test.dart

要(yào)運行(xíng)所有測試,請(qǐng)從(cóng)項目目錄運行(xíng)flutter test

Widget 測試

您以類似于單元測試的方式實現widget測試。要(yào)在測試中執行(xíng)與widget的交互,請(qǐng)使用Flutter提供的WidgetTester。 例如(rú),您可(kě)以發送點擊和(hé)滾動手勢。您還可(kě)以使用WidgetTester在widget樹(shù)中查找子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));

});

}

運行(xíng) flutter test test/widget_test.dart.

查看(kàn)所有可(kě)用于widget測試的package:flutter_test API

為(wèi)了(le)幫助調試widget測試,您可(kě)以使用debugDumpApp() 函數(shù)來可(kě)視(shì)化測試的UI狀态, 或者隻是簡單的在您的首選運行(xíng)時(shí)環境(例如(rú)模拟器或設備)中運行(xíng)flutter run test/widget_test.dart以查看(kàn)您的測試運行(xíng)。 在運行(xíng)flutter run的測試的會話期間(jiān),您還可(kě)以交互式地(dì)點擊Flutter工(gōng)具的部分屏幕來打印建議(yì)的Finder。

集成測試

如(rú)果您熟悉Selenium/WebDriver(web),Espresso(Android)或UI Automation(iOS),那(nà)麽Flutter Driver就是Flutter與這(zhè)些集成測試工(gōng)具的等價物(wù)。 此外(wài),Flutter Driver還提供API以記錄測試執行(xíng)的操作(zuò)的性能(néng)跟蹤(又名時(shí)間(jiān)軸)。

Flutter的Driver是:

一(yī)個命令行(xíng)工(gōng)具 flutter drive

一(yī)個包 package:flutter_driver (API)

這(zhè)兩者允許你:

為(wèi)集成測試創建指令化的應用程序

寫一(yī)個測試

運行(xíng)測試

添加flutter_driver依賴項

要(yào)使用flutter_driver,您必須将以下(xià)塊添加到您的pubspec.yaml:

dev_dependencies:

flutter_driver:

sdk: flutter

創建指令化的Flutter應用程序

一(yī)個指令化的應用程序是一(yī)個Flutter應用程序,它啓用了(le)Flutter Driver 擴展。啓用擴展請(qǐng)調用enableFlutterDriverExtension()。

例:

假設你有一(yī)個入口點的應用程序my_app/lib/main.dart。要(yào)創建它的指令化版本,請(qǐng)在my_app/test_driver/下(xià)創建一(yī)個Dart文件。 在您正在測試的功能(néng)之後命名它; 接下(xià)來定位到my_app/test_driver/user_list_scrolling.dart:

// 這(zhè)一(yī)行(xíng)導入擴展

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.

}

編寫集成測試

集成測試是一(yī)個簡單的package:test測試,它使用Flutter Driver API告訴應用程序執行(xíng)什麽操作(zuò),然後驗證應用程序是否執行(xíng)了(le)此操作(zuò)。

例子:

為(wèi)了(le)有意思起見(jiàn),我們也讓我們的測試記錄下(xià)性能(néng)跟蹤(performance timeline)。我們創建一(yī)個user_list_scrolling_test.dart測試文件位于my_app/test_driver/下(xià):

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.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.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);

});

});

}

運行(xíng)集成測試

要(yào)在Android設備上(shàng)運行(xíng)測試,請(qǐng)通(tōng)過USB将設備連接到計算機并啓用USB調試。然後運行(xíng)以下(xià)命令:

flutter drive --target=my_app/test_driver/user_list_scrolling.dart

該命令将:

構建 --target 應用,并将其安裝在設備上(shàng)

啓動應用

運行(xíng)my_app/test_driver/下(xià)的user_list_scrolling_test.dart

您可(kě)能(néng)想知道(dào)該命令如(rú)何找到正确的測試文件。flutter drive 命令使用一(yī)種約定來查找與--target應用程序在同一(yī)目錄中具有相同文件名但(dàn)是具有_test後綴的測試文件。

網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發
下(xià)一(yī)篇:Flutter 調試應用
上(shàng)一(yī)篇:Flutter 使用熱(rè)重載