[英]Flutter Integration test case fails when run
我正在尝试在我的应用程序中运行集成测试。 该屏幕是我的登录屏幕,它会引导注册流程并登录到主屏幕。 我正在使用框架本身的颤振集成测试。
我尝试在登录屏幕上运行集成测试,但出现此错误,
运行测试时抛出以下 TestFailure 对象:预期:小部件树中正好有一个匹配节点实际:_WidgetPredicateFinder:<零小部件与小部件匹配谓词(闭包:(小部件)=> bool)(忽略舞台外小部件)>其中:意味着没有找到,但预计会有一个
我的登录屏幕看起来像这样
class LoginScreen extends StatefulWidget {
static String tag = loginScreenRoute;
const LoginScreen({Key? key}) : super(key: key);
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _userLoginFormKey = GlobalKey<FormState>();
String? _userName = "";
String? _password = "";
bool _invisiblePass = false;
TextEditingController usernameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
bool hasInterNetConnection = false;
late StreamSubscription _connectionChangeStream;
@override
initState() {
//Create instance
ConnectionUtil connectionStatus = ConnectionUtil.getInstance();
//Initialize
connectionStatus.initialize();
//Listen for connection change
_connectionChangeStream =
connectionStatus.connectionChange.listen(connectionChanged);
super.initState();
}
@override
void dispose() {
_connectionChangeStream.cancel();
super.dispose();
}
void connectionChanged(dynamic hasConnection) {
setState(() {
hasInterNetConnection = hasConnection;
//print(isOffline);
});
if (!hasInterNetConnection) {
offlineBar(context);
}
}
final loading = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(
color: lightWTextColor,
),
Text(" Login in ... Please wait")
],
);
void _showPassword() {
setState(() {
_invisiblePass = !_invisiblePass;
});
}
@override
Widget build(BuildContext context) {
//// user email ////
TextFormField userName() => TextFormField(
key: const Key('login username input'),
autofocus: false,
keyboardType: TextInputType.emailAddress,
controller: usernameController,
validator: validateEmail,
onSaved: (value) => _userName = value!.trim(),
textInputAction: TextInputAction.next,
style: AppTheme.body1WTextStyle,
decoration: buildInputDecoration(
'Enter Email',
Icons.email,
lightWTextColor.withOpacity(0.4),
),
// focusNode: _usernameFocusNode,
// onFieldSubmitted: (String val) {
// final focusNode = FocusNode();
// focusNode.unfocus();
// },
);
//// user password ////
TextFormField userPassword() => TextFormField(
key: const Key('login password input'),
obscureText: !_invisiblePass,
keyboardType: TextInputType.visiblePassword,
controller: passwordController,
validator: validatePassword,
onSaved: (value) => _password = value!.trim(),
textInputAction: TextInputAction.done,
style: AppTheme.body1WTextStyle,
decoration: buildInputDecoration(
'Enter Password',
Icons.vpn_lock,
lightWTextColor.withOpacity(0.4),
).copyWith(
suffixIcon: GestureDetector(
onTap: () {
_showPassword();
},
child: Icon(
_invisiblePass ? Icons.visibility : Icons.visibility_off,
color: Colors.black54,
),
),
),
);
final forgotLabel = Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
alignment: Alignment.topRight,
child: TextButton(
child: const Text(
"Forgot password?",
style: AppTheme.body1WTextStyle,
),
onPressed: () {
Navigator.of(context).pushNamed(passwordResetScreenRoute);
},
),
),
);
final signupLabel = Padding(
padding: const EdgeInsets.all(10.0),
child: TextButton(
child: const Text(
"Sign Up for an Account",
style: AppTheme.subTitleWTextStyle,
),
onPressed: () {
Navigator.of(context).pushNamed(
userEditScreenRoute,
arguments: eProfile.addProfile,
);
},
),
);
final loginButton = ButtonWidget(
key: const Key('login button'),
text: 'LOG IN',
btnColor: accentColor,
borderColor: accentColor,
textColor: lightWTextColor,
onPressed: () {
Navigator.of(context).pushReplacementNamed(homeScreenRoute);
// _submit();
},
);
final loginForm = Form(
key: _userLoginFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
userName(),
const SizedBox(
height: 10.0,
),
userPassword(),
forgotLabel,
const SizedBox(
height: 10.0,
),
loginButton,
const SizedBox(
height: 10.0,
),
signupLabel,
],
),
);
final mainBody = InkWell(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: wBackground(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/_logo.png',
height: 200.0,
),
Expanded(
flex: 1,
child: loginForm, //Text('this text here'),
),
],
),
),
),
),
);
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: mainBody,
),
),
);
}
}
当我尝试点击登录按钮导航到主屏幕时,测试失败。
我的测试用例是这样的
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
//
// start.main();
login.main();
}
//
void main() {
doLoginTest();
}
void doLoginTest() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets("Login in test run", (WidgetTester tester) async {
//
pawfect.main();
await tester.pumpAndSettle(const Duration(seconds: 3));
//test here
final Finder login =
find.byWidgetPredicate((widget) => widget is LoginScreen);
expect(login, findsOneWidget);
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var emailInput = find.byKey(const Key('login username input'));
await tester.tap(emailInput);
await tester.enterText(emailInput, "test@m.com");
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var passwordInput = find.byKey(const Key('login password input'));
await tester.tap(passwordInput);
await tester.enterText(passwordInput, "password");
await tester.pumpAndSettle(const Duration(seconds: 1));
//
var loginButton = find.byKey(const Key('login button'));
await tester.tap(loginButton, warnIfMissed: false);
await tester.pumpAndSettle(const Duration(seconds: 3));
//
// expect(version, findsOneWidget);
// final Finder home = find.byWidget(const HomeScreen());
expect(find.byWidgetPredicate((widget) => widget is HomeScreen),
findsOneWidget);
// await tester.pumpAndSettle(const Duration(seconds: 1));
var version = find.byWidgetPredicate(
(widget) => widget is Text && widget.data!.contains("Version: 2.0"));
expect(version, findsOneWidget);
await tester.pumpAndSettle(const Duration(seconds: 3));
});
}
我在这里做错了什么? 我试图通过互联网和文档寻找一些有用的东西,但我的手不够脏。 有人可以帮我写一个很好的集成测试,将屏幕移到另一个屏幕。 非常感谢你提前。
你的测试文件中还有两个主要方法吗? 如果是这样,您可以删除第一个(我不明白它是如何存在的):
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
//
// start.main();
login.main();
}
还尝试单步执行您的代码 - 在您的测试文件中添加一个断点,并在该测试文件仍在编辑器中按 F5(我假设您像我一样在 VSCode 中),找出哪个expect
调用报告失败 - 我我猜是第二个:
expect(find.byWidgetPredicate((widget) => widget is HomeScreen),
findsOneWidget);
尝试在该调用之前添加此代码(而不是您现有的 pumpAndSettle 调用):
await tester.pump(const Duration(milliseconds: 4000));
await tester.pumpAndSettle();
还要考虑这个答案中的一些想法: https : //stackoverflow.com/a/70472212/491739
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.