Flutter自适应测试插件adaptive_test的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter自适应测试插件adaptive_test的使用

Table of Contents

简介

Adaptive Test 是由 Theodo Apps 开发的一个用于编写Flutter应用中出色的Widget测试的工具。它可以帮助开发者生成不同设备上的golden文件,加载字体,设置窗口大小和像素密度,等待图像渲染,渲染物理和系统UI层,模拟键盘输入,设置首选操作系统等。

Example

Features

使用此包可以在测试中实现以下功能:

  • 为不同的设备生成golden文件
  • 加载自定义字体
  • 设置窗口大小和像素密度
  • 等待图像渲染完成
  • 渲染物理和系统UI层
  • 在测试中渲染键盘
  • 设置运行测试的首选操作系统
  • 配置文件比较的差异容忍阈值

Getting Started

添加依赖

pubspec.yaml中添加adaptive_test到你的dev dependencies:

dev_dependencies:
  adaptive_test: ^latest_version

创建配置文件

test目录下创建一个名为flutter_test_config.dart的文件,并添加如下代码:

import 'package:flutter_test/flutter_test.dart';
import 'package:adaptive_test/adaptive_test.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  await testMain();
}

Usage

Rendering Custom Fonts

  1. 将字体文件添加到你的项目资源文件夹中。
  2. pubspec.yaml中注册这些字体:
flutter:
  fonts:
    - family: Roboto
      fonts:
        - asset: fonts/Roboto-Black.ttf
  1. 修改flutter_test_config.dart以调用loadFonts()方法:
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  TestWidgetsFlutterBinding.ensureInitialized();
  await loadFonts();
  await testMain();
}

Setting Up Test Devices

  1. 定义一组设备变体:
final defaultDeviceConfigs = {
  iPhone16,
  pixel9,
};
  1. 使用AdaptiveTestConfiguration单例来设置这些变体:
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  TestWidgetsFlutterBinding.ensureInitialized();
  AdaptiveTestConfiguration.instance
    ..setDeviceVariants(defaultDeviceConfigs);
  await loadFonts();
  await testMain();
}

Configuring Difference Threshold

为了允许处理器之间的微小像素差异,可以在flutter_test_config.dart中添加setupFileComparatorWithThreshold()

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  TestWidgetsFlutterBinding.ensureInitialized();
  AdaptiveTestConfiguration.instance
    ..setDeviceVariants(defaultDeviceConfigs);
  await loadFonts();
  setupFileComparatorWithThreshold();
  await testMain();
}

Enforcing Test Platform

通过配置AdaptiveTestConfiguration来强制指定测试平台:

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  TestWidgetsFlutterBinding.ensureInitialized();
  AdaptiveTestConfiguration.instance
    ..setEnforcedTestPlatform(TargetPlatform.macOS)
    ..setDeviceVariants(defaultDeviceConfigs);
  await loadFonts();
  setupFileComparatorWithThreshold();
  await testMain();
}

如果你想在不期望的平台上跳过测试而不是抛出错误,可以设置:

AdaptiveTestConfiguration.instance
  ..setEnforcedTestPlatform(TargetPlatform.macOS)
  ..setFailTestOnWrongPlatform(false)
  ..setDeviceVariants(defaultDeviceConfigs);

Writing a Test

使用testAdaptiveWidgets函数编写测试:

void main() {
  testAdaptiveWidgets(
    'Test description',
    (tester, variant) async {
      await tester.pumpWidget(
        AdaptiveWrapper(
          windowConfig: variant,
          tester: tester,
          child: const App(),
        ),
      );

      await tester.expectGolden<App>(variant);
    },
  );
}

Migration Guide

Migrating to version 0.7.x

Version 0.7.0 引入了几个破坏性变更和新特性:

  1. Breaking Change: loadFonts()不再接受packages参数,loadFontsFromPackage()已被移除。

    更新你的flutter_test_config.dart:

    // Old
    await loadFonts('my_package');
    // or
    await loadFontsFromPackage(
      package: Package(
        name: 'my_package',
        relativePath: '../package',
      ),
    );
    
    // New
    await loadFonts();
    

    loadFonts()现在支持自定义图标字体如material_symbols_icons。

  2. Breaking Change: WindowConfigData现在包含了一个新的keyboardName属性。

    更新你的自定义设备配置以包含这个新属性。

Migrating to version 0.5.x

Version 0.5.0 引入了一个与Windows文件系统兼容的新默认golden文件名。要重命名现有的golden文件,可以使用以下脚本:

#!/bin/bash

rename_files_in_preview() {
    find . -type d -name "preview" | while read -r dir; do
        echo "Processing directory: $dir"
        find "$dir" -type f | while read -r file; do
            new_name=$(echo "$file" | sed 's/:/-/g')
            if [ "$file" != "$new_name" ]; then
                mv "$file" "$new_name"
                echo "Renamed $file to $new_name"
            fi
        done
    done
}

rename_files_in_preview

将上述脚本保存为.sh文件并从项目根目录运行。

Additional Information

我们欢迎反馈、问题报告、贡献和建议!如果你有任何想法或需要帮助,请随时联系我们。Theodo Apps是一家专注于React Native和Flutter开发的公司,采用精益和敏捷的方法论来设计和开发通用应用程序。如果你有关于解决方案的问题,可以通过电子邮件或联系表单与我们取得联系。

希望这篇文档能帮助你更好地理解和使用adaptive_test插件进行Flutter应用的自适应测试。如果有任何疑问或需要进一步的帮助,请随时提问!


更多关于Flutter自适应测试插件adaptive_test的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自适应测试插件adaptive_test的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,我可以为你提供一个关于如何在Flutter项目中使用adaptive_test插件的代码示例。adaptive_test插件通常用于在不同屏幕尺寸和设备配置下测试应用的自适应布局。以下是一个基本的示例,展示如何集成和使用adaptive_test插件。

首先,你需要在你的pubspec.yaml文件中添加adaptive_test依赖:

dependencies:
  flutter:
    sdk: flutter
  adaptive_test: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来获取依赖。

接下来,我们编写一个示例应用,展示如何使用adaptive_test插件。

示例代码

  1. main.dart - 主应用代码
import 'package:flutter/material.dart';
import 'package:adaptive_test/adaptive_test.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Adaptive Test Example'),
        ),
        body: AdaptiveTestWidget(),
      ),
    );
  }
}

class AdaptiveTestWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('Hello, Adaptive Test!'),
          SizedBox(height: 20),
          AdaptiveTestExample(),
        ],
      ),
    );
  }
}

class AdaptiveTestExample extends StatelessWidget {
  @
override  Widget build(BuildContext context) {
    return AdaptiveLayoutBuilder(
      builder: (context, screenType ==) {
        if (screenType == ScreenType.mobile) {
          return MobileLayout();
        } else if (screenType ScreenType.tablet) {
          return TabletLayout();
        } else if (screenType == ScreenType.desktop) {
          return DesktopLayout();
        } else {
          return Container(child: Text('Unknown Screen Type'));
        }
      },
    );
  }
}

class MobileLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('This is Mobile Layout'),
        // 添加更多移动布局组件
      ],
    );
  }
}

class TabletLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('This is Tablet Layout - Left'),
        Spacer(),
        Text('This is Tablet Layout - Right'),
        // 添加更多平板布局组件
      ],
    );
  }
}

class DesktopLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      children: [
        Text('This is Desktop Layout - Cell 1'),
        Text('This is Desktop Layout - Cell 2'),
        Text('This is Desktop Layout - Cell 3'),
        Text('This is Desktop Layout - Cell 4'),
        // 添加更多桌面布局组件
      ],
    );
  }
}
  1. 使用adaptive_test进行测试

通常,adaptive_test插件主要用于测试目的,而不是在生产代码中直接使用。你可以编写测试文件来验证你的自适应布局。以下是一个简单的测试示例:

import 'package:flutter_test/flutter_test.dart';
import 'package:adaptive_test/adaptive_test.dart';
import 'package:your_app/main.dart';  // 替换为你的主应用文件路径

void main() {
  testWidgets('Adaptive Layout Test', (WidgetTester tester) async {
    // 使用AdaptiveTestEnvironment包装测试环境
    await tester.pumpWidget(AdaptiveTestEnvironment(
      child: MaterialApp(
        home: Scaffold(
          body: AdaptiveTestWidget(),
        ),
      ),
    ));

    // 模拟不同屏幕尺寸和设备类型
    await tester.pumpWidget(AdaptiveTestEnvironment.withScreenType(
      ScreenType.mobile,
      child: MaterialApp(
        home: Scaffold(
          body: AdaptiveTestWidget(),
        ),
      ),
    ));
    expect(find.text('This is Mobile Layout'), findsOneWidget);

    await tester.pumpWidget(AdaptiveTestEnvironment.withScreenType(
      ScreenType.tablet,
      child: MaterialApp(
        home: Scaffold(
          body: AdaptiveTestWidget(),
        ),
      ),
    ));
    expect(find.text('This is Tablet Layout - Left'), findsOneWidget);
    expect(find.text('This is Tablet Layout - Right'), findsOneWidget);

    await tester.pumpWidget(AdaptiveTestEnvironment.withScreenType(
      ScreenType.desktop,
      child: MaterialApp(
        home: Scaffold(
          body: AdaptiveTestWidget(),
        ),
      ),
    ));
    expect(find.text('This is Desktop Layout - Cell 1'), findsOneWidget);
    expect(find.text('This is Desktop Layout - Cell 2'), findsOneWidget);
    expect(find.text('This is Desktop Layout - Cell 3'), findsOneWidget);
    expect(find.text('This is Desktop Layout - Cell 4'), findsOneWidget);
  });
}

请注意,以上代码示例是一个基本的演示,实际项目中可能需要更复杂的布局和测试逻辑。确保你已经正确配置了测试环境,并且flutter_test依赖已经添加到你的pubspec.yaml文件中。

回到顶部