【问题标题】:Best Approach To Testing App Appearance In Flutter While App Is In Dark/Light Theme (especially for Dark Theme)当应用程序处于深色/浅色主题(尤其是深色主题)时,在 Flutter 中测试应用程序外观的最佳方法
【发布时间】:2021-10-13 16:09:00
【问题描述】:

通过Flutter docs on testing 之后,我在我的应用程序中达到了一个点,我想在应用程序上测试浅色和深色主题外观。 Integration tests 可能是一种选择,但是它们运行起来“昂贵”,我想将集成测试的考虑作为测试深色/浅色主题应用程序外观问题的最后手段。

这是我用(Widget Tests)testWidgets尝试的:

void main() {
  testWidgets("Test that the app renders properly in 'Dark Theme'.",
      (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.dark(),
        home: RegistrationHomePage(),
      ),
    );

    expect(
      SchedulerBinding.instance.window.platformBrightness,
      Brightness.dark,
      reason: "The test suite should now be testing with app theme set to dark theme.",
    );
  })
}

但是,此测试失败。它失败了,因为小部件测试仍在以浅色主题而不是深色主题执行此测试

  • 可以采取什么措施来纠正这种情况以及运行小部件测试(专注于应用外观)的可行性如何?
  • 在 Flutter 中测试应用外观的通用默认设置是否应该是集成测试

更新: 实际上,我正在测试文本小部件将在[浅色主题和深色主题中]显示的颜色。

ma​​in.dart

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      debugShowCheckedModeBanner: false,
      themeMode: ThemeMode.system,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: RegistrationHomePage(),
    );
  }
}

registration_screen.dart

class RegistrationHomePage extends StatefulWidget {
  // Constructor
  RegistrationHomePage({Key key}) : super(key: key);

  @override
  _RegistrationHomePageState createState() => _RegistrationHomePageState();
}

class _RegistrationHomePageState extends State<RegistrationHomePage> {
  void setState(fn) {
    super.setState(fn);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(
          "Welcome to the app",
          style: TextStyle(
            color: MediaQuery.of(context).platformBrightness == Brightness.dark
                ? Colors.green.shade900
                : Colors.green,
            fontWeight: FontWeight.w600,
            fontSize: 35.0,
          ),
          textAlign: TextAlign.center,
        ),
      ),
    );
  }
}

test.dart

void main() {
  testWidgets("Test that the app renders properly in 'Dark Theme'.",
      (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.dark(),
        home: RegistrationHomePage(),
      ),
    );

    final Finder loginTextFinder = find.text("Welcome to the app.");
    final Text loginText = tester.firstWidget(loginTextFinder);

    expect(
      WelcomeText.style.color,
      Colors.green.shade900,
      reason:
          'While the system dark is dark theme, the text color should be dark green',
    );
  });
}

测试失败。测试失败,因为测试是在应用程序设置为浅色主题而不是深色主题的情况下进行的。一定有什么我在这里做错了。现在看来我无法将测试应用程序设置为我在test.dart 中尝试使用的深色主题

void main() {
  testWidgets("Test that the app renders properly in 'Dark Theme'.",
      (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.dark(),
        home: RegistrationHomePage(),
      ),
    );
  });
}

【问题讨论】:

  • 我不会测试直接的 MaterialApp 主题实现,Flutter 团队已经为您完成了 :)。我会测试处理主题切换的逻辑。
  • 非常感谢您的评论。从不同的方向思考问题非常有帮助[尽管我仍在考虑它]。现在我已经更新了问题,您认为我还能做些什么吗?

标签: android flutter dart tdd flutter-test


【解决方案1】:

如果我正在为深色主题的应用程序运行小部件测试,我会采取以下路线:

void main() {
  testWidgets("Test that the app renders properly in dark theme",
      (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(brightness: Brightness.dark),
      home: RegistrationHomePage(),
    ));

    // Capture a BuildContext object
    final BuildContext context = tester.element(find.byType(MaterialApp));

    // Get finders and relevant objects that would be available at first load of MaterialApp()
    final Finder welcomeTextFinder = find.text("Welcome to the app");
    final Text welcomeText = tester.firstWidget(welcomeTextFinder);

    // functions
    bool testIsInLightTheme() {
      /// return true if the test is in light theme, else false
      if (Theme.of(context).brightness == Brightness.light) {
        return true;
      }
      return false;
    }

    // Here is just a test to confirm that the MaterialApp is now in dark theme
    expect(
      Theme.of(tester.element(find.byWidget(welcomeText))).brightness,
      equals(Brightness.dark),
      reason:
          "Since MaterialApp() was set to dark theme when it was built at tester.pumpWidget(), the MaterialApp should be in dark theme",
    );

    // Now let's test the color of the text
    expect(
      welcomeText.style.color,
      testIsInLightTheme() ? Colors.green : Colors.green.shade900,
      reason:
          "When MaterialApp is in light theme, text is black. When Material App is in dark theme, text is white",
    );
  });
}

一些值得注意的提及: 在测试中捕获 BuildContext 对象:https://stackoverflow.com/a/67704136/7181909

关于如何进行主题测试的标准说明(基本上是一些处理主题测试的flutter source code [By the Flutter team that contributed to theme related testing!]

【讨论】:

    【解决方案2】:

    这是我的简短解决方案,基于@Alvindera97 答案:

      Future<void> testDarkMode(
        WidgetTester tester, {
        required keyElementToCheckDarkmodeIn,
        required keyDarkmodeSwitcher,
      }) async {
        expect(
          Theme.of(tester.element(_finder.key(keyElementToCheckDarkmodeIn))).brightness,
          equals(Brightness.light),
        );
    
        await tester.tap(_finder.key(keyDarkmodeSwitcher));
        await tester.pump();
        await tester.pumpAndSettle(_testUtils.delay(DELAY));
    
        expect(
          Theme.of(tester.element(_finder.key(keyElementToCheckDarkmodeIn))).brightness,
          equals(Brightness.dark),
        );
      }
    
      Finder key(String keyText) {
        return find.byKey(Key(keyText));
      }
    
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 2023-01-11
      • 2015-10-04
      相关资源
      最近更新 更多