Flutter golden testing 测试插件alchemist的使用

发布于 1周前 作者 gougou168 最后一次编辑是 5天前 来自 Flutter

Flutter golden testing 测试插件alchemist的使用

简介

🧙🏼 Alchemist 是由 Very Good Ventures 和 Betterment 共同开发的一款Flutter工具,它旨在使golden testing变得简单。Alchemist提供了函数、扩展和文档来支持golden测试,受到了Ebay Motor’s golden_toolkit包的启发,致力于简化Flutter中golden测试的编写和运行。

Very Good Ventures Betterment

ci codecov pub package License: MIT


功能概述

  • 🤖 分离本地与CI测试:支持平台测试(人类可读文本)和CI测试(颜色方块替代文本)
  • 📝 声明式&简洁的测试API
  • 📐 自动文件尺寸调整
  • 🔧 高级配置
  • 🌈 轻松的主题定制
  • 🔤 自定义文本缩放比例
  • 🧪 100%测试覆盖率
  • 📖 详细的文档

基本用法

编写测试

在项目的 test/ 目录下添加一个文件用于存放组件的测试代码,并使用 goldenTest 函数编写和运行golden测试。推荐将所有与同一组件相关的golden测试放在一个测试 group 中。

import 'package:alchemist/alchemist.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('ListTile Golden Tests', () {
    goldenTest(
      'renders correctly',
      fileName: 'list_tile',
      builder: () => GoldenTestGroup(
        scenarioConstraints: const BoxConstraints(maxWidth: 600),
        children: [
          GoldenTestScenario(
            name: 'with title',
            child: ListTile(
              title: Text('ListTile.title'),
            ),
          ),
          GoldenTestScenario(
            name: 'with title and subtitle',
            child: ListTile(
              title: Text('ListTile.title'),
              subtitle: Text('ListTile.subtitle'),
            ),
          ),
          GoldenTestScenario(
            name: 'with trailing icon',
            child: ListTile(
              title: Text('ListTile.title'),
              trailing: Icon(Icons.chevron_right_rounded),
            ),
          ),
        ],
      ),
    );
  });
}

生成golden文件

通过运行以下命令更新或生成golden文件:

flutter test --update-goldens

测试与比较

为了在CI过程中运行golden测试并进行比较,可以使用以下命令:

# 运行所有测试
flutter test

# 只运行golden测试
flutter test --tags golden

# 运行所有测试但不包括golden测试
flutter test --exclude-tags golden

高级用法

关于 AlchemistConfig

AlchemistConfig 类包含了多种设置以自定义测试行为。默认情况下,提供了一个 AlchemistConfig 实例,包含以下设置:

字段 默认值 描述
forceUpdateGoldenFiles false 如果为 true,则无论是否传递了 --update-goldens 标志,golden文件都将始终重新生成。
theme null 所有测试使用的主题;如果为 null,则使用默认的 ThemeData.light()
platformGoldensConfig PlatformGoldensConfig() 运行可读golden测试时使用的配置。
ciGoldensConfig CiGoldensConfig() 在CI环境中运行遮盖golden测试时使用的配置。

平台测试 vs CI测试

  • 平台测试:生成带有可读文本的golden文件,通常仅在本地机器上运行。
  • CI测试:文本块被彩色方块替换,确保输出一致,不受平台影响。

使用自定义配置

可以通过 AlchemistConfig.runWithConfig 方法设置自定义配置。例如,在 flutter_test_config.dart 文件中设置全局配置:

import 'dart:async';
import 'package:alchemist/alchemist.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  return AlchemistConfig.runWithConfig(
    config: AlchemistConfig(
      // 配置选项
    ),
    run: testMain,
  );
}

或者为单个测试或测试组设置配置:

void main() {
  group('with default config', () {
    test('test', () {
      expect(
        AlchemistConfig.current().forceUpdateGoldenFiles,
        isFalse,
      );
    });
  });

  AlchemistConfig.runWithConfig(
    config: AlchemistConfig(
      forceUpdateGoldenFiles: true,
    ),
    run: () {
      group('with overridden config', () {
        test('test', () {
          expect(
            AlchemistConfig.current().forceUpdateGoldenFiles,
            isTrue,
          );
        });
      });
    },
  );
}

模拟手势

某些golden测试可能需要用户输入,如点击按钮显示正确的颜色。可以通过 whilePerforming 参数模拟这些交互:

void main() {
  goldenTest(
    'ElevatedButton renders tap indicator when pressed',
    fileName: 'elevated_button_pressed',
    whilePerforming: press(find.byType(ElevatedButton)),
    builder: () => GoldenTestGroup(
      children: [
        GoldenTestScenario(
          name: 'pressed',
          child: ElevatedButton(
            onPressed: () {},
            child: Text('Pressed'),
          ),
        ),
      ],
    ),
  );
}

自动/自定义图像尺寸

Alchemist会自动找到最小可能的尺寸来生成golden图像,也可以通过 constraints 参数自定义尺寸:

goldenTest(
  'renders correctly',
  fileName: 'list_tile',
  constraints: const BoxConstraints(maxWidth: 600),
  builder: () => GoldenTestGroup(
    children: [
      // ...
    ],
  ),
);

自定义泵送行为

可以在测试前执行一些操作,如预加载图片:

goldenTest(
  'renders correctly',
  fileName: 'list_tile',
  pumpBeforeTest: precacheImages,
  builder: () => GoldenTestGroup(
    children: [
      // ...
    ],
  ),
);

自定义文本缩放因子

可以通过 GoldenTestScenario.withTextScaleFactor 构造函数为单个场景设置自定义文本缩放因子:

goldenTest(
  'renders correctly',
  fileName: 'list_tile',
  textScaler: TextScaler.linear(2.0),
  builder: () => GoldenTestGroup(
    children: [
      GoldenTestScenario.withTextScaleFactor(
        name: 'scaled text',
        child: ListTile(
          title: Text('Scaled Text'),
        ),
        textScaleFactor: 2.0,
      ),
    ],
  ),
);

资源


希望这个指南能帮助你更好地理解和使用Alchemist进行Flutter的golden测试!如果有任何问题或建议,请随时联系开发者社区。


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

1 回复

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


在Flutter中,对于像“alchemist”这样的未知功能插件(特别是当文档或介绍信息为“undefined”时),直接提供代码案例可能有些困难,因为我们不知道这个插件的具体API和功能。不过,我可以向你展示如何集成一个Flutter插件的基本步骤,并提供一个假设性的代码框架,以帮助你开始探索和使用这个插件。

步骤 1: 添加依赖

首先,你需要在pubspec.yaml文件中添加alchemist插件的依赖。请注意,由于我们不知道这个插件的真实名称和版本,这里只是一个假设性的例子:

dependencies:
  flutter:
    sdk: flutter
  alchemist: ^x.y.z  # 替换为实际的插件名称和版本号

然后运行flutter pub get来安装依赖。

步骤 2: 导入插件

在你的Dart文件中,导入这个插件:

import 'package:alchemist/alchemist.dart';

步骤 3: 假设性的代码框架

由于我们不知道alchemist插件的具体功能,以下是一个假设性的代码框架,展示了如何可能使用它:

import 'package:flutter/material.dart';
import 'package:alchemist/alchemist.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 假设alchemist插件有一个初始化方法
  late AlchemistPlugin alchemist;

  @override
  void initState() {
    super.initState();
    // 初始化插件
    alchemist = AlchemistPlugin();
    // 假设有一个初始化函数
    alchemist.init().then((_) {
      // 插件初始化完成后可以执行的代码
      print('Alchemist plugin initialized');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Alchemist Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '假设的功能展示',
            ),
            // 假设有一个按钮可以触发插件的某个功能
            ElevatedButton(
              onPressed: () {
                // 调用插件的某个功能
                alchemist.someUnknownFunction().then((result) {
                  // 处理结果
                  print('Result from alchemist: $result');
                }).catchError((error) {
                  // 处理错误
                  print('Error: $error');
                });
              },
              child: Text('触发未知功能'),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 文档和示例:尝试查找alchemist插件的官方文档或GitHub仓库,了解它的真实功能和API。
  2. 错误处理:在实际使用中,务必添加适当的错误处理逻辑,以确保应用的稳定性。
  3. 社区支持:如果插件没有官方文档,可以尝试在Stack Overflow、GitHub等社区寻求帮助。

希望这个框架能帮助你开始探索和使用alchemist插件。如果你能找到更多关于这个插件的信息,那么你可以根据这些信息来调整和完善你的代码。

回到顶部