Flutter 實戰11

2021-02-25 AI開發測試實戰
單元測試通常用於測試單個功能、方法或類,其目的在於驗證邏輯單元在各種輸入條件下仍然可以輸出正確的結果。單元測試通常不會發生磁碟讀寫操作,不會顯示在屏幕上,也不會從運行測試的進程以外截取用戶操作。下面來看一下單元測試是如何進行的。

添加測試庫

用於測試的庫在新建Flutter工程時已經引入,你可以打開pubspec.yaml找到相關代碼:

dev_dependencies:  flutter_test:    sdk: flutter

但是,如果工程代碼不知為何沒有引入這個庫,請按照如上所示將其添加到pubspec.yaml文件中。

 創建測試類和被測試類

測試類是用來測試另一個類的,被測試類是等待另一個類來測試的。觀察整個Flutter工程的結構,來到項目的根目錄下,發現它包含test目錄。通常,該文件夾就是用來放測試類的,而將App的業務邏輯代碼放在lib目錄中。下面分別創建這兩個類:

lib/counter.dart

test/counter_test.dart

如上所示,在lib目錄中新建了counter.dart類,在test目錄中新建了counter_test.dart類。前者是被測試類,後者是測試類。

開發業務邏輯

編寫常規業務邏輯就等同於開發Fluter App,這裡實現一下簡單的變量自增和變量自減兩個方法。示例如下:
class Counter{  int value=0;  void increment() => value++;  void decrement() => value--;}

開發測試類

接下來,我們編寫counter_test.dart類,這裡需要導入test.dart類以便可以正常使用測試方法。在測試counter.dart類中變量自增和變量自減方法的代碼如下:
import 'package:flutter_test/flutter_test.dart';import 'package:flutter_app2/counter.dart';void main(){
test('Counter value shold be',() { final counter = Counter(); counter.increment(); expect(counter.value, 1); }); test('Value should be decremented', (){ final counter = Counter(); counter.decrement(); expect(counter.value,-1); });
}

除了上述寫法,如果多個測試方法屬於同一個功能或可歸為同一類,就可以使用group將其歸類,其實現如下:
import 'package:flutter_test/flutter_test.dart';import 'package:flutter_app2/counter.dart';void main(){  group('Counter',()  {    test('value 0', () {      expect(Counter().value, 0);    });    test('Counter value shold be', () {      final counter = Counter();      counter.increment();      expect(counter.value, 1);    });    test('Value should be decremented', () {      final counter = Counter();      counter.decrement();      expect(counter.value, -1);    });  });}

運行測試類

最後,為了得到最終的測試結果來運行測試類。打開Android Studio中的Terminal視圖,運行集成的控制臺,在其中輸入如下命令:

然後按回車鍵,稍等片刻,即可得到測試結果:

/Users/apple/tools/flutter/bin/flutter --no-color test --machine --start-paused --plain-name Counter test/counter_test.dart

那麼,在不指定測試類時,Flutter框架會默認運行所有測試類。

顧名思義,所謂組件測試就是用來測試單個組件的,即用來確保某個組件按預期的方式運行。下面分步驟來介紹組件測試如何進行。

添加測試庫

和單元測試一樣,運行組件測試依然需要添加測試庫,如下:
dev_dependencies:  flutter_test:    sdk: flutter

創建要被測試的組件

新建的項目包含一個MyApp組件,以及多個Material Design風格的組件,這裡測試的主要組件是MyApp。打開test目錄下的widget_test.dart文件,可以看到具體的測試步驟。

創建組件測試類

打開test目錄下的widget_test.dart文件,閱讀裡面的代碼,發現用於組件測試的結構如下。
import 'package:flutter/material.dart';import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_app2/main.dart';
void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { await tester.pumpWidget(MyApp());
expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing);
await tester.tap(find.byIcon(Icons.add)); await tester.pump();
expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); });}

這裡用testWidgets()方法進行組件測試,它包含了WidgetTester對象——tester。

使用WidgetTester創建組件

繼續閱讀widget_test.dart文件中的代碼,在testWidgets()方法中,開始執行以下語句:

testWidgets('Counter increments smoke test', (WidgetTester tester) async {

pumpWidget()方法創建了MyApp組件,這一步並沒有在行動裝置上運行,只是在後臺默默地完成了組件的渲染。還發現tester.tap()方法模擬點擊的操作,緊跟其後的tester.pump()方法則會重建組件。因為在單純的點擊後並不會使狀態組件發生最終的顯示變化,所以只有在調用tester.pump()方法之後才行。通常,在被測試的代碼中有setState()方法就會有tester.pump()方法出現。

使用find查找組件

在widget_test.dart文件中,還有類似這樣的寫法:

find.text('0')find.text('1')

使用find可以找到要驗證的組件。比如,在上面的代碼中,前者是通過「包含0」去尋找符合該要求的組件。運行被測試的代碼,界面顯示所示。


點擊加號的上面變為加1,

顯而易見,符合「包含0」條件的只有屏幕中央的文本,右下角的加號按鈕則是通過加號條件找到的。

使用Matcher驗證結果

在找到組件並模擬點擊事件後,就要驗證最終的結果。在widget_test.dart文件中,將查找組件和驗證結果寫到了一起。這段代碼很容易理解,通過查找「包含0」的條件,若符合「找到一個組件」的結果,則表示測試通過。widget_test.dart文件中的整段代碼如下:

其邏輯如下:

(1)創建MyApp組件。

(2)查找符合「包含0」條件的組件,期望結果是1個。

(3)查找符合「包含1」條件的組件,期望結果是0個。

(4)點擊包含加號圖標的組件。

(5)重建組件。

(6)查找符合「包含0」條件的組件,期望結果是0個。

(7)查找符合「包含1」條件的組件,期望結果是1個。

運行組件測試的方法和運行單元測試的相同。

我們知道,單元測試和組件測試都是針對某個方法、某個類或某個組件而言的,它們通常不會測試這些單獨的部分組合在一起後的情況。對於這種情況,就需要用到集成測試。集成測試的進行方式和單元/組件測試的不同,它需要在設備或虛擬設備上部署指令化的程序,然後使用測試套件驅動它,最後檢查並確保程序是按照期望的方式來運行的。

下面依舊分步驟來看一下集成測試是如何進行的。

創建要測試的App

由於集成測試是對整個App而言的,因此要進行集成測試就需要先創建目標App。在實際開發中,集成測試通常是在完成整個App開發後進行的。這裡,依舊使用新建的計數器應用為例,然後在計數值顯示的Text組件和FloatingActionButton組件上添加key屬性,如下:
import 'package:flutter/material.dart';
void main() { runApp(MyApp());}
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter 點擊按鈕加1', theme: ThemeData( primarySwatch: Colors.green, ), home: MyHomePage(title: 'Flutter 大成 Home Page'), ); }}
class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState();}
class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) {
return Scaffold( appBar: AppBar( title: Text(widget.title), ),      body: Center(        child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( '您已經點擊的次數 :', ), Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), ); }}

添加必要的測試庫

集成測試需要使用flutter_driver庫。除了要聲明flutter_test庫,還要將flutter_driver庫添加到pubspec.yaml的dev_dependencies節點中。如下:
  flutter_test:    sdk: flutter  flutter_driver:    sdk: flutter  test: any

創建測試類

集成測試用到的測試類位於工程根目錄下的test_driver目錄中,默認創建的Flutter工程並不包含這個目錄,需要手動新建。創建後,還需要創建指令化的Flutter應用程式類和集成測試用到的類。創建指令化的Flutter應用程式類。指令化的Flutter應用程式允許開發者運行App。本例中,將該類命名為app.dart,並將其保存在test_driver目錄下。創建集成測試用到的類。集成測試類包含用於驗證運行結果正確與否的測試套件,其同樣記錄性能分析數據。該類的命名規則為必須以與之相關的指令化應用程式類名後加_test為名。本例中,指令化的Flutter應用程式類名為app.dart,則集成測試用到的類名為app_test.dart。

構建指令化的Flutter應用程式類

創建指令化的Flutter應用程式很簡單,只需要啟動Flutter drive擴展並運行程序即可。完整的app.dart代碼如下:

import 'package:flutter_driver/driver_extension.dart';import 'package:flutter_app2/main.dart' as app;void main(){  enableFlutterDriverExtension();  app.main();}

由於main()方法在app.dart中也有聲明,因此這裡使用了import … as …的方式導入類,並在使用時通過調用app.main()方法區分不同類但同名的main()方法。

構建集成測試用到的類

在構建好指令化的Flutter應用程式後,就可以寫針對它的測試類了。這個測試類使用Flutter driver API來指導應用程式執行操作,之後再驗證這個操作是否正確。完整的app_test.dart代碼如下:

如上代碼所示,首先使用find定位要測試的組件。本例中,通過key的方式找到計數值Text組件和FloatingActionButton組件。接著,在正式測試前調用setUpAll()方法連接到App。然後,測試腳本的內容,分別對應本例中的兩個test()方法。最後,調用tearDownAll()方法和App斷開連接,結束測試流程。

運行測試

運行測試的方法是啟動集成的命令行視圖。在工程根目錄下運行以下指令:

flutter driver --target=test_driver/app.dart

注意,由於集成測試會真正地在設備上運行App,因此能看到測試操作的全過程。在測試完成後,App將自動關閉,並在命令行留下相關日誌。從日誌中查看的測試結果如下:flutter driver --target=test_driver/app.dart 

Running "flutter pub get" in flutter_app2...                       723msLaunching test_driver/app.dart on Chrome in debug mode...Waiting for connection from debug service on Chrome...             19.8sDebug service listening on ws:

相關焦點

  • Flutter 實戰4
    pub get下載安裝它需要切換指令: flutter channel beta(切回來:flutter channel stable)使本機flutter支持web指令: flutter config --enable-web用flutter doctor -v查看是否支持
  • 好課分享:動~腦~學~院~ 12套Flutter教程,零基礎到實戰開發
    動~腦~學~院~  |   ├──12套Flutter教程,零基礎到實戰開發  |   |   ├──01 Flutter Dart入門基礎語法  |   |   ├──02 flutter入門到精通課程  |   |   ├──03 Flutter移動應用開發實戰  |   |   ├──04 flutter移動電商實戰
  • Flutter 要起飛 , Flutter 1.12 正式發布回顧!
    早上還看到捷特也寫了一篇文章,更重 web 和桌面的實戰一些,後續分享給大家。前天谷歌為在 Flutter Interact 上為我們帶來了 Flutter 1.12 ,這是 1.9.x 的版本在經歷 6 次 hotfix 之後,才帶來的 stable 大版本更新。
  • Flutter 入門路線圖
    list=PLR2qQy0Zxs_W4a6P70VYtzna7jwl3-lxI對於那些不喜歡看視頻的人,可以查看以下站點• Tutorials11• Dart Programming Tutorial12• Learn Dart In A Week With These Free Resources13[11]https://dart.dev
  • 【Flutter桌面篇】Flutter&Windows應用嘗鮮
    一、運行Flutter初始項目1.FlutterSDK桌面程序創建目前穩定版不支持Windows,我可以新建個文件夾,下載master分支的Flutter修改計算機的環境變量,指向master分支的Flutter SDK開啟Windows支持: flutter config --enable-windows-desktop創建Flutter項目, 建議命令行創建,比較方便。
  • Flutter加載網頁之官方webview_flutter講解
    前言最近在用flutter開發一個App,其中需要加載網頁,本來以為很簡單的一件事,卻遇到了不少坑,最後整整搞了一上午。對於加載網頁這個功能來說,flutter並沒有組件,反而是第三方開發了一些組件,目前比較常用的有二種: flutter_webview_plugin webview_flutterflutter_webview_plugin是目前用得最火的一種,也是比較好用的,但是它有個致命的缺點,它不支持「進入某個URL之前攔截」,這也是我放棄它的原因。
  • 解決flutter運行報錯:flutter_tools depends的處理方法
    我是您的朋友義縣遊學電子科技.今天帶來的flutter的錯誤解決方法是關於web平臺運行時提示:"Because flutter_tools depends on shelf_packages_handler any which doesn't exist(could
  • Flutter doctor 命令,解決Flutter開發環境疑難雜症,建議收藏
    路徑我可以帶大家看看,這個flutter文件夾是我在官網下載的,大家可以自己去官網下載,然後隨便解壓到一個目錄就行了,然後就是配置環境變量,Flutter SDK安裝目錄路徑環境變量配置這個bin目錄就是flutter的具體命令目錄,平時在命令行裡面輸入的命令就是這個地方發出的。如果希望全局可用就的在這裡配置一個環境變量就行了。
  • Flutter 新人指導插件 onboarding_overlay
    老鐵記得 轉發 ,貓哥會呈現更多 Flutter 好文~~~~微信群 ducafecatb 站 https://space.bilibili.com/404904528原文https://medium.com/flutterdevs/explore-onboarding-overlay-in-flutter-5ed882e123ac參考https://pub.flutter-io.cn
  • 使用 Flutter 開發 Github 客戶端及學習歷程的小結
    第一周:初識Flutter最初學習Flutter的方式是通過學習 wendux 老師的 《Flutter實戰》:https://book.flutterchina.club/這是一本非常優秀的中文Flutter教程,對個人學習Flutter入門有非常大的幫助。
  • 使用Flutter一年後,這是我得到的經驗
    例如,Center 小部件(https://docs.flutter.io/flutter/widgets/Center-class.html)。為什麼要單獨使用一個小部件來讓元素居中?雖然它讓新手很容易上手,但在用它實現更複雜的布局時,會產生太多嵌套的 Dart 代碼。
  • Mac版最詳細的Flutter開發環境搭建
    更新flutter的PATH變量,以便可以運行flutter命令在任何終端會話中。/mySpace/flutterSDK/flutter/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/mongodb:/usr/local/go/bin~檢查開發環境到此我們已經安裝完flutter了,但此時還不具備開發的能力,flutter運行需要很多插件,運行以下命令查看是否需要安裝其它依賴項來完成安裝:1flutt
  • 學習Flutter遇到的問題以及解決方案
    https://github.com/flutter-cn/flutter_cookbook/tree/master/examples/stateful_communication9:Flutter 修改圖標、應用名稱、包名等?
  • 實操|在 Flutter 中創建通信橋
    在創建一個新的 Flutter 項目後,我們需要使用webview_flutter包來使得能夠使用 WebView。我們會向 pubspec.yaml 文件中添加依賴:dependencies: flutter: sdk: flutter webview_flutter: ^1.0.7然後,我們需要運行 Pub get 或者在終端中:flutter pub get然後,我們需要在 main.dart 文件中導入這個包:import 'package:webview_flutter
  • Flutter 會不會被蘋果限制其發展?
    這個可能性是存在的,而且不止是 flutter、react-native 、weex 、uni-app 、taro 、Hippy等都存在這個風險,雖然有些框架對比起 flutter 其他框架存在時間稍長,但是這不可否認它們一直都存在這個風向。
  • Flutter 中文文檔:Widget 測試介紹
    為了測試 widget 類,我們需要使用 flutter_test package 提供的額外工具,這些工具是跟 Flutter SDK 一起發布的。flutter_test package 提供了以下工具用於 widget 的測試:WidgetTester,使用該工具可在測試環境下建立 widget 並與其交互。
  • Flutter實現國際化
    如果想要添加其他語言,你的應用必須指定額外的 MaterialApp 屬性並且添加一個單獨的 package,叫做 flutter_localizations。截至到 2020 年 2 月份,這個 package 已經支持大約 77 種語言。
  • Flutter 常用widget之Text
    import 'package:flutter/material.dart';class TextPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center
  • Flutter Running Gradle task 'assembleDebug'解決方法
    前言最近用flutter做個app,當運行flutter run的時候,一直卡在這個地方動不了,如下圖:運行時會卡在Running 'gradle assembleDebug, 因為Gradle的Maven倉庫在國外, 可以使用阿里雲的鏡像地址。
  • Flutter Go首頁、文檔和下載 - Flutter 學習 App - OSCHINA
    flutter優點主要包括: 跨平臺 開源 Hot Reload、響應式框架、及其豐富的控制項以及開發工具 靈活的界面設計以及控制項組合 藉助可以移植的GPU加速的渲染引擎以及高性能ARM代碼運行時已達到高質量的用戶體驗Flutter Go 的由來 Flutter學習資料太少,對於英文不好的同學相對來說比較困難 官網文檔示例不夠健全,不夠直觀 各個 widget 的用法各異,屬性紛繁