Flutter 測試應用

2020-08-27 14:48 更新

介紹

應用的功能越多,手動測試的難度就越大。一套完整的自動化測試將幫助您確保您的應用在發(fā)布之前正確執(zhí)行,同時保留您的功能和錯誤修復速度。

有很多種自動化測試。這些總結如下:

  • 單元測試:測試單一功能、方法或類。例如,被測單元的外部依賴性通常被模擬出來,如package:mockito。 單元測試通常不會讀取/寫入磁盤、渲染到屏幕,也不會從運行測試的進程外部接收用戶操作。單元測試的目標是在各種條件下驗證邏輯單元的正確性。
  • widget 測試:(在其它UI框架稱為 組件測試) 測試的單個widget。測試widget涉及多個類,并且需要提供適當的widget生命周期上下文的測試環(huán)境。 例如,它應該能夠接收和響應用戶操作和事件,執(zhí)行布局并實例化子widget。widget測試因此比單元測試更全面。 然而,就像一個單元測試一樣,一個widget測試的環(huán)境被一個比完整的UI系統(tǒng)簡單得多的實現所取代。小部件測試的目標是驗證小部件的UI如預期的那樣的外觀和交互。
  • 集成測試: 測試一個完整的應用程序或應用程序的很大一部分。通常,集成測試可以在真實設備或OS仿真器上運行,例如iOS Simulator或Android Emulator。 被測試的應用程序通常與測試驅動程序代碼隔離,以避免結果偏差。集成測試的目標是驗證應用程序作為一個整體正確運行,它所組成的所有widget如預期的那樣相互集成。 您還可以使用集成測試來驗證應用的性能。

這里是一個表格,總結了在不同類型測試之間進行選擇的權衡:

 單元測試widget測試集成測試
ConfidenceLowHigherHighest
維護成本LowHigherHighest
依賴FewMoreLots
執(zhí)行速度QuickSlowerSlowest
    

提示: 作為一個經驗法則,經過充分測試的應用程序具有非常多的單元和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);
  });
}

另外,您必須將以下內容添加到您的pubspec.yaml:

dev_dependencies:
  flutter_test:
    sdk: flutter

即使你的測試本身沒有明確導入flutter_test,也需要這樣做 ,因為測試框架本身在后臺也使用了它。

要運行測試,從您的項目目錄(而不是從test子目錄)運行 flutter test test/unit_test.dart

要運行所有測試,請從項目目錄運行flutter test


Widget 測試

您以類似于單元測試的方式實現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

為了幫助調試widget測試,您可以使用debugDumpApp() 函數來可視化測試的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與這些集成測試工具的等價物。 此外,Flutter Driver還提供API以記錄測試執(zhí)行的操作的性能跟蹤(又名時間軸)。

Flutter的Driver是:

  • 一個命令行工具 flutter drive
  • 一個包 package:flutter_driver (API)

這兩者允許你:

  • 為集成測試創(chuàng)建指令化的應用程序
  • 寫一個測試
  • 運行測試

添加flutter_driver依賴項

要使用flutter_driver,您必須將以下塊添加到您的pubspec.yaml:

dev_dependencies:
  flutter_driver:
    sdk: flutter

創(chuàng)建指令化的Flutter應用程序

一個指令化的應用程序是一個Flutter應用程序,它啟用了Flutter Driver 擴展。啟用擴展請調用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調試。然后運行以下命令:

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

該命令將:

  • 構建 --target 應用,并將其安裝在設備上
  • 啟動應用
  • 運行my_app/test_driver/下的user_list_scrolling_test.dart

您可能想知道該命令如何找到正確的測試文件。flutter drive 命令使用一種約定來查找與--target應用程序在同一目錄中具有相同文件名但是具有_test后綴的測試文件。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號