所以我正在尝试在 Flutter 中创建一些 UI 测试用例,但目前我遇到了很多困难。它失败的确切时刻是当按下添加按钮时,会弹出一个保存窗口。保存窗口完成后,UI 测试人员应该等待下一个屏幕,然后按“确定”,但似乎它立即第二次按下“添加”按钮,这导致它失败,因为用户已经通过第一次单击添加了。无论我等待多少次或放入任何内容,只要有可能,它都会立即按下“添加”按钮。下面的代码是问题的核心部分,非常感谢!
// Find the 'Add' button
expect(find.text('Add'), findsOneWidget);
Finder addButton = find.text('Add');
print("About to tap Add button ONCE");
await tester.tap(addButton);
print("Add button tapped once. Now waiting for 'Select Player 2:' text");
// Immediately remove the Add button from the widget tree to prevent any possibility of tapping it again
await tester.pumpAndSettle();
// Wait for the "Select Player 2:" text to appear
bool selectPlayer2Found = false;
for (int i = 0; i < 30; i++) { // 30-second timeout
await tester.pump(Duration(seconds: 1));
print("Checking for 'Select Player 2:' (attempt ${i + 1})");
if (find.text('Select Player 2:').evaluate().isNotEmpty) {
print("'Select Player 2:' text found!");
selectPlayer2Found = true;
break;
}
// Double-check that the Add button is no longer present
if (find.text('Add').evaluate().isNotEmpty) {
throw Exception("Add button is still visible after tapping it once!");
}
}
if (!selectPlayer2Found) {
throw Exception("'Select Player 2:' text did not appear after 30 seconds");
}
// Now that we've confirmed "Select Player 2:" is visible, look for the OK button
print("Looking for OK button");
expect(find.text('OK'), findsOneWidget);
Finder okButton = find.text('OK');
// Tap the OK button
await tester.tap(okButton);
print("OK button tapped");
await tester.pumpAndSettle();
听起来您在 Flutter UI 测试中遇到的问题与应用程序中不同屏幕或窗口之间的计时和同步有关。当 UI 测试人员在下一个屏幕完全加载之前多次按下“添加”按钮时,可能是由于缺乏适当的等待或同步方法。
这里有一个解决这个问题的策略:
适当使用await和pumpAndSettle() PumpAndSettle() 方法等待小部件树稳定,这意味着它会等待,直到没有更多的预定帧要构建。这在触发可能导致新小部件出现的操作后非常有用(例如单击“添加”后)。
等待 tester.tap(find.byKey(Key('addButton'))); 等待 tester.pumpAndSettle(); // 等待 UI 稳定
明确等待下一个屏幕 不要只是等待 UI 稳定下来,而是等待您知道应该出现的下一个屏幕上的特定小部件或元素。
等待 tester.tap(find.byKey(Key('addButton'))); 等待 tester.pumpAndSettle(); // 等待弹出窗口出现
// 假设有一个文本字段用于输入名称 等待 tester.enterText(find.byKey(Key('nameField')), 'John Doe');
// 假设有保存按钮确认添加 等待 tester.tap(find.byKey(Key('saveButton'))); 等待 tester.pumpAndSettle(); // 等待保存操作完成
// 等待下一个屏幕上出现特定的小部件 等待 tester.waitFor(find.byKey(Key('nextScreenWidget')));
// 现在点击下一个屏幕上的“确定”按钮 等待 tester.tap(find.byKey(Key('okButton'))); 等待 tester.pumpAndSettle(); // 等待最后的操作完成
使用 tester.runAsync 进行异步操作 如果屏幕之间的转换涉及在正常测试泵周期内未完成的异步操作,您可能需要使用 tester.runAsync() 来正确处理此问题。
等待 tester.tap(find.byKey(Key('addButton'))); 等待 tester.pumpAndSettle(); // 等待弹出窗口出现
等待 tester.runAsync(() 异步 { // 模拟延迟或等待异步操作完成 等待 Future.delayed(持续时间(秒: 2));
等待 tester.pumpAndSettle(); // 异步操作后等待 UI 稳定 });
// 现在继续下一步 等待 tester.tap(find.byKey(Key('saveButton'))); 等待 tester.pumpAndSettle();
仔细检查小部件标识符和密钥 确保您使用的小部件标识符(例如 Key)是唯一的并且放置正确。如果存在任何重复的键或不正确的小部件引用,可能会导致测试人员与错误的小部件交互。
调查可能的帧延迟 如果您的测试环境运行速度太快而无法更新 UI,您可能需要手动引入泵延迟以允许动画或过渡。
等待 tester.tap(find.byKey(Key('addButton'))); 等待 tester.pump(持续时间(秒: 1)); // 如果需要的话添加延迟 等待 tester.pumpAndSettle();
结论 关键是将您的测试操作与实际 UI 状态同步。适当地使用 PumpAndSettle() 和 wait 可以帮助确保您的测试在继续下一步操作之前等待必要的 UI 元素加载。