为什么一些 Flutter widget 测试一起执行会失败,但单独执行会通过?

Kef*_*eff 6 dart flutter flutter-test

当同一文件中有多个测试,并且一个接一个地运行测试时。某些类型的测试会失败,但单独运行时相同的测试会通过。

\n

这是我目前的测试文件,虽然有点长:

\n
import \'package:flutter/material.dart\';\nimport \'package:flutter_test/flutter_test.dart\';\nimport \'package:rec/Components/Inputs/text_fields/DniTextField.dart\';\nimport \'package:rec/Helpers/Validators.dart\';\n\nimport \'../../test_utils.dart\';\n\nvoid main() {\n  testWidgets(\'DniTextField works with invalid DNI\', (WidgetTester tester) async {\n    var key = GlobalKey<DniTextFieldState>();\n    var formKey = GlobalKey<FormState>();\n    var onChangedResult;\n\n    var widget = Form(\n      key: formKey,\n      child: DniTextField(\n        key: key,\n        onChange: (String value) {\n          onChangedResult = value;\n        },\n        validator: (s) => Validators.verifyIdentityDocument(s),\n      ),\n    );\n    await tester.pumpWidget(\n      TestUtils.wrapPublicRoute(widget),\n    );\n    await tester.pumpAndSettle();\n\n    // Test that widget has at least rendered\n    TestUtils.widgetExists(widget);\n\n    // Enter text into field with\n    var widgetFinder = find.byWidget(widget);\n    await tester.tap(widgetFinder);\n    await tester.showKeyboard(widgetFinder);\n    await tester.enterText(widgetFinder, \'invaliddni\');\n\n    await tester.pumpAndSettle();\n\n    expect(onChangedResult, \'invaliddni\');\n\n    expect(formKey.currentState.validate(), false);\n  });\n\n  testWidgets(\'DniTextField works with valid DNI\', (WidgetTester tester) async {\n    var key = GlobalKey<DniTextFieldState>();\n    var formKey = GlobalKey<FormState>();\n    var onChangedResult;\n\n    var widget = Form(\n      key: formKey,\n      child: DniTextField(\n        key: key,\n        onChange: (String value) {\n          onChangedResult = value;\n        },\n        validator: (s) => Validators.verifyIdentityDocument(s),\n      ),\n    );\n    await tester.pumpWidget(\n      TestUtils.wrapPublicRoute(widget),\n    );\n    await tester.pumpAndSettle();\n\n    // Enter text into field\n    var widgetFinder = find.byType(DniTextField);\n    await tester.tap(widgetFinder);\n    await tester.showKeyboard(widgetFinder);\n    await tester.enterText(widgetFinder, \'80008000k\');\n\n    await tester.pumpAndSettle();\n\n    expect(onChangedResult, \'80008000k\');\n\n    expect(formKey.currentState.validate(), true);\n  });\n\n  testWidgets(\'DniTextField works with valid DNI with trailing space\', (WidgetTester tester) async {\n    var key = GlobalKey<DniTextFieldState>();\n    var formKey = GlobalKey<FormState>();\n    var onChangedResult;\n\n    var widget = Form(\n      key: formKey,\n      child: DniTextField(\n        key: key,\n        onChange: (String value) {\n          onChangedResult = value;\n        },\n        validator: (s) => Validators.verifyIdentityDocument(s),\n      ),\n    );\n    await tester.pumpWidget(TestUtils.wrapPublicRoute(widget));\n    await tester.pumpAndSettle();\n\n    // Enter text into field\n    var widgetFinder = find.byWidget(widget);\n    await tester.tap(widgetFinder);\n    await tester.showKeyboard(widgetFinder);\n    await tester.enterText(widgetFinder, \'80008000k \');\n\n    await tester.pumpAndSettle();\n\n    // The value emitted by the field, should be free of trailing whitespace\n    expect(onChangedResult, \'80008000k\');\n\n    expect(formKey.currentState.validate(), true);\n  });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果我这样运行:

\n
$ flutter test test/Components/inputs/dni_text_field_test.dart\n
Run Code Online (Sandbox Code Playgroud)\n

第一个测试通过,但接下来的两个测试未通过,并出现以下错误:

\n
\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following assertion was thrown running a test:\nThe finder "zero widgets with the given widget\n(DniTextField-[LabeledGlobalKey<DniTextFieldState>#0fb86]) (ignoring offstage widgets)" (used in a\ncall to "tap()") could not find any matching widgets.\n\nWhen the exception was thrown, this was the stack:\n#0      WidgetController._getElementPoint (package:flutter_test/src/controller.dart:902:7)\n#1      WidgetController.getCenter (package:flutter_test/src/controller.dart:841:12)\n#2      WidgetController.tap (package:flutter_test/src/controller.dart:273:18)\n#3      main.<anonymous closure> (file:///[masked]/test/Components/inputs/dni_text_field_test.dart:99:18)\n<asynchronous suspension>\n<asynchronous suspension>\n(elided one frame from package:stack_trace)\n
Run Code Online (Sandbox Code Playgroud)\n

如果我注释掉第一个测试,那么第二个测试会通过,但第三个测试不会。正如我所说,如果我单独运行它们,测试就会通过。

\n

我找不到任何有关此的信息,甚至一件事也没有。也许这里有人可以引导我走向正确的方向。我对 Flutter 小部件测试有点菜鸟,所以我可能会错过一些重要的事情。

\n

我目前找到的唯一解决方案是将每个测试放在单独的文件中。但这并不理想,将相关测试包含在同一个文件中会更好。Flutter 有示例表明,每个文件应该进行多次测试是允许的。

\n

颤振版本:2.4.0-5.0.pre.87

\n

Kef*_*eff 8

好吧,我找到了解决方案和原因,感谢这个问题和这个问题。

主要问题是使用从 JSON 文件加载的本地化。解决方案是将每个测试包装起来tester.runAsync()

testWidgets('widget test 2', (WidgetTester tester) async {
  await tester.runAsync(() async {
    // tests
  });
});
Run Code Online (Sandbox Code Playgroud)