Flutter插件golden_variant的特性与使用

Flutter插件golden_variant的特性与使用

Flutter插件golden_variant的特性

假设你有黄金测试,并且希望为不同类型的变体创建黄金文件:

  • 不同设备屏幕尺寸;
  • 暗色和亮色主题;
  • LTR和RTL字体;
  • 带键盘和不带键盘;

只需设置所需的变体并将其传递给组合变体:

final variant = ValueVariantComposite([
  DeviceVariant({
    Devices.ios.iPhone13,
    Devices.ios.iPad,
  }),
  ThemeVariant({ThemeMode.light, ThemeMode.dark}),
  ShowKeyboardVariant(),
]);

然后使用常规的testWidgets

testWidgets(
  'MyHomePage 黄金测试',
  (tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: getThemeData(variant.get<ThemeMode>()),
        home: DeviceFrameWrapper(
          device: variant.get<DeviceInfo>(),
          showVirtualKeyboard: variant.get<ShowKeyboard>().show,
          child: MyApp(),
        ),
      ),
    );
  },
  variant: variant,
);

查看示例

Flutter插件golden_variant入门指南

步骤1

golden_variant添加到你的开发依赖项中。

步骤2

在你的test文件夹的根目录下创建一个flutter_test_config.dart文件,并包含一个testExecutable函数:

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

有关更多信息,请参阅官方 Flutter 文档

思路

如果你有任何想法来增强此包或有任何关注点,请随时创建一个问题


示例代码

以下是一个完整的示例,展示了如何使用golden_variant插件进行多变体黄金测试。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // 这个小部件是您的应用程序的根。它是一个状态小部件,意味着
  // 它有一个状态对象(定义如下),该状态对象包含影响其外观的字段。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: getThemeData(ThemeMode.system),
      home: myHomePage,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // 这个小部件是您的应用程序的首页。它是状态化的,意味着
  // 它有一个状态对象(在下面定义)包含影响其外观的字段。
  // 这个类是状态的配置。它保留了由父级(在这个例子中是App小部件)提供的值(在这种情况下是标题),
  // 并在构建方法中使用这些值。小部件子类中的字段总是标记为“final”。

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // 这个调用setState告诉Flutter框架某些东西已经改变,
      // 导致它重新运行下面的构建方法以使显示反映更新后的值。
      // 如果我们不调用setState更改_counter,那么构建方法就不会被再次调用,
      // 因此似乎什么都没有发生。
      _counter++;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 这个方法每次调用setState时都会重新运行,例如上面的_incrementCounter方法。
    //
    // Flutter框架经过优化,使得重新运行构建方法变得快速,
    // 因此您可以重建任何需要更新的东西,而不是逐个更改小部件实例。
    return Scaffold(
      appBar: AppBar(
        // 尝试:尝试在这里将颜色更改为特定颜色(可能是Colors.amber?)并触发热重载以查看AppBar
        // 在其他颜色保持不变的情况下改变颜色。
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // 这里我们从由App.build方法创建的MyHomePage对象获取值,
        // 并使用它来设置我们的appbar标题。
        title: Text(widget.title),
      ),
      body: Center(
        // Center是一个布局小部件。它接受单个子元素并将其定位在父元素中间。
        child: Column(
          // Column也是一个布局小部件。它接受一个小部件列表并垂直排列它们。
          // 默认情况下,它水平调整自身大小以适应其子元素,并尝试与父元素一样高。
          //
          // Column有几个属性可以控制其自身的大小和其子元素的位置。
          // 在这里我们使用mainAxisAlignment将子元素垂直居中;主轴是垂直方向,
          // 因为Column是垂直的(交叉轴是水平的)。
          //
          // 尝试:触发“调试绘制”(在IDE中选择“切换调试绘制”操作,或按控制台中的“p”键),
          // 以查看每个小部件的线框。
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '你已经按下了按钮这么多次:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: '增加',
        child: const Icon(Icons.add),
      ), // 这个逗号使得自动格式化更好看。
    );
  }
}

const myHomePage = MyHomePage(title: 'Flutter Demo Home Page');

ThemeData getThemeData(ThemeMode themeMode) => ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: Colors.deepPurple,
        brightness: themeMode == ThemeMode.dark ? Brightness.dark : Brightness.light,
      ),
      useMaterial3: true,
      fontFamily: 'Roboto',
    );

更多关于Flutter插件golden_variant的特性与使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件golden_variant的特性与使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


golden_variant 是一个用于 Flutter 的插件,主要用于生成和管理 Golden Tests 的变体。Golden Tests 是一种用于验证 UI 在不同条件下(如不同的主题、语言、设备等)是否按预期渲染的测试方法。golden_variant 插件可以帮助开发者更轻松地生成和管理这些变体,从而提高测试的覆盖率和准确性。

1. 安装 golden_variant 插件

首先,你需要在 pubspec.yaml 文件中添加 golden_variant 作为开发依赖:

dev_dependencies:
  golden_variant: ^1.0.0

然后运行 flutter pub get 来安装插件。

2. 创建 Golden Test

Golden Tests 通常使用 flutter_test 包中的 expect 函数来比较实际渲染的 UI 与预期的 Golden 文件。以下是一个简单的 Golden Test 示例:

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

void main() {
  testGoldens('MyWidget golden test', (tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: Text('Hello, World!'),
          ),
        ),
      ),
    );

    await expectLater(find.byType(Scaffold), matchesGoldenFile('my_widget.png'));
  });
}

3. 使用 golden_variant 生成变体

golden_variant 插件允许你为 Golden Tests 生成不同的变体。例如,你可以为不同的主题、语言或设备生成不同的 Golden 文件。

3.1 定义变体

你可以使用 Variant 类来定义不同的变体。以下是一个为不同主题生成变体的示例:

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

void main() {
  final variants = [
    Variant<ThemeData>(
      name: 'light',
      value: ThemeData.light(),
    ),
    Variant<ThemeData>(
      name: 'dark',
      value: ThemeData.dark(),
    ),
  ];

  testGoldens('MyWidget golden test with variants', (tester) async {
    for (final variant in variants) {
      await tester.pumpWidget(
        MaterialApp(
          theme: variant.value,
          home: Scaffold(
            body: Center(
              child: Text('Hello, World!'),
            ),
          ),
        ),
      );

      await expectLater(
        find.byType(Scaffold),
        matchesGoldenFile('my_widget_${variant.name}.png'),
      );
    }
  });
}

3.2 使用 VariantBuilder

golden_variant 还提供了一个 VariantBuilder,可以更方便地生成变体:

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

void main() {
  testGoldens('MyWidget golden test with VariantBuilder', (tester) async {
    await tester.pumpWidgetBuilder(
      (context) => Scaffold(
        body: Center(
          child: Text('Hello, World!'),
        ),
      ),
      variantBuilder: () => [
        Variant<ThemeData>(
          name: 'light',
          value: ThemeData.light(),
        ),
        Variant<ThemeData>(
          name: 'dark',
          value: ThemeData.dark(),
        ),
      ],
    );

    await expectLater(
      find.byType(Scaffold),
      matchesGoldenFile('my_widget_light.png'),
    );

    await expectLater(
      find.byType(Scaffold),
      matchesGoldenFile('my_widget_dark.png'),
    );
  });
}

4. 运行 Golden Tests

你可以使用以下命令来运行 Golden Tests:

flutter test --update-goldens
回到顶部