This document provides a comprehensive example of testing an authentication flow using the AuthForm widget. We'll cover unit testing for validation logic, widget testing for UI interactions, and integration testing for the entire authentication process.
The AuthForm widget is a form for user authentication. It includes input fields for email and password, along with validation logic and a submit button.
class AuthForm extends StatefulWidget {
const AuthForm({super.key});
@override
State<AuthForm> createState() => _AuthFormState();
}
class _AuthFormState extends State<AuthForm> {
@override
Widget build(BuildContext context) {
AuthLogic authLogic = AuthLogic();
return Scaffold(
appBar: AppBar(
title: const Text("Testing example"),
),
body: Form(
key: authLogic.formKey,
child: Column(
children: [
TextFormField(
key: const Key('emailField'),
controller: authLogic.emailController,
validator: authLogic.emailValidator,
decoration: const InputDecoration(labelText: 'Email'),
),
TextFormField(
key: const Key('passwordField'),
controller: authLogic.passwordController,
validator: authLogic.passwordValidator,
decoration: const InputDecoration(labelText: 'Password'),
),
ElevatedButton(
key: const Key('submitButton'),
onPressed: authLogic.submitForm,
child: const Text('Submit'),
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
class AuthLogic {
final formKey = GlobalKey<FormState>();
final emailController = TextEditingController();
final passwordController = TextEditingController();
String? emailValidator(String? value) {
if (value == null || value.isEmpty || !value.contains('@')) {
return 'Invalid email';
}
return null;
}
String? passwordValidator(String? value) {
if (value == null || value.isEmpty || value.length < 6) {
return 'Password must be at least 6 characters';
}
return null;
}
void submitForm() {
if (formKey.currentState!.validate()) {
final email = emailController.text;
final password = passwordController.text;
// Perform authentication logic
if (email == 'test@example.com' && password == 'password123') {
// If credentials are valid, you can trigger a success action here
// For now, let's print a success message
print('Authentication successful');
} else {
// If credentials are invalid, you can trigger a failure action here
// For now, let's print an error message
print('Authentication failed');
}
}
}
}
main.dart
import 'package:auth_example/logic.dart';
import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';
void main() {
enableFlutterDriverExtension();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Testing Example'
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const AuthForm(),
);
}
}
dev_dependencies:
flutter_driver:
sdk: flutter
flutter_test:
sdk: flutter
Unit tests focus on testing individual components of the AuthForm widget, specifically the validation logic for email and password fields.
import 'package:flutter_test/flutter_test.dart';
import 'package:auth_example/auth_form.dart';
void main() {
group('AuthForm Unit Tests', () {
// Test for a valid email address
test('Valid email', () {
// Arrange: Create a validator function for email validation
final validator = AuthForm()._emailValidator;
// Act: Invoke the validator with a valid email
final result = validator('test@example.com');
// Assert: Ensure the result is null, indicating a valid email
expect(result, null);
});
// Test for an invalid email address
test('Invalid email', () {
// Arrange: Create a validator function for email validation
final validator = AuthForm()._emailValidator;
// Act: Invoke the validator with an invalid email
final result = validator('invalid_email');
// Assert: Ensure the result is 'Invalid email', indicating an error
expect(result, 'Invalid email');
});
// Test for a valid password
test('Valid password', () {
// Arrange: Create a validator function for password validation
final validator = AuthForm()._passwordValidator;
// Act: Invoke the validator with a valid password
final result = validator('password123');
// Assert: Ensure the result is null, indicating a valid password
expect(result, null);
});
// Test for an invalid password
test('Invalid password', () {
// Arrange: Create a validator function for password validation
final validator = AuthForm()._passwordValidator;
// Act: Invoke the validator with an invalid password
final result = validator('123');
// Assert: Ensure the result is 'Password must be at least 6 characters', indicating an error
expect(result, 'Password must be at least 6 characters');
});
});
}
Widget tests verify the behavior of the AuthForm widget's UI interactions, such as entering data and submitting the form.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:auth_example/auth_form.dart';
void main() {
testWidgets('AuthForm UI Test', (WidgetTester tester) async {
// Arrange: Build the widget under test, which is the AuthForm, within a MaterialApp.
await tester.pumpWidget(MaterialApp(home: AuthForm()));
// Find the email, password, and submit button widgets using their Key identifiers.
final emailField = find.byKey(Key('emailField'));
final passwordField = find.byKey(Key('passwordField'));
final submitButton = find.byKey(Key('submitButton'));
// Act: Enter text into the email and password fields.
await tester.enterText(emailField, 'test@example.com');
await tester.enterText(passwordField, 'password123');
// Tap the submit button to trigger the form submission.
await tester.tap(submitButton);
await tester.pump(); // Complete the frame transition.
// Assert: Check that the text 'Form submitted' is found in the widget tree.
expect(find.text('Form submitted'), findsOneWidget);
});
}
Integration tests simulate the entire authentication flow, combining multiple components and interactions.
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_test/flutter_test.dart' as test;
void main() {
test.group('AuthForm Integration Test', () {
FlutterDriver? driver;
// Connect to the app before running tests
test.setUpAll(() async {
// Establish a connection to the Flutter app running on a device or emulator.
driver = await FlutterDriver.connect(
// dartVmServiceUrl is a URL used for connecting to the Dart VM service,
// which is a debugging and profiling service provided by the Dart runtime.
dartVmServiceUrl: "ws://127.0.0.1:58557/lTla2qH-HXs=/ws",
printCommunication: true, // Print communication logs for debugging.
);
});
// Close the connection after tests are done
test.tearDownAll(() async {
if (driver != null) {
// Close the FlutterDriver connection.
driver?.close();
}
});
// Test for successful authentication
test.test('Successful authentication', () async {
// Find email, password, and submit button widgets using their value keys.
final emailField = find.byValueKey('emailField');
final passwordField = find.byValueKey('passwordField');
final submitButton = find.byValueKey('submitButton');
// Tap the email field and enter a valid email.
await driver?.tap(emailField);
await driver?.enterText('test@example.com');
// Tap the password field and enter a valid password.
await driver?.tap(passwordField);
await driver?.enterText('password123');
// Tap the submit button to simulate a form submission.
await driver?.tap(submitButton);
}, timeout: test.Timeout.none); // No timeout for this test.
// Test for failed authentication
test.test('Failed authentication', () async {
// Find email, password, and submit button widgets using their value keys.
final emailField = find.byValueKey('emailField');
final passwordField = find.byValueKey('passwordField');
final submitButton = find.byValueKey('submitButton');
// Tap the email field and enter a valid email.
await driver?.tap(emailField);
await driver?.enterText('test@example.com');
// Tap the password field and enter an invalid password.
await driver?.tap(passwordField);
await driver?.enterText('123'); // Invalid password
// Tap the submit button to simulate a form submission.
await driver?.tap(submitButton);
}, timeout: test.Timeout.none); // No timeout for this test.
});
}
This detailed documentation provides a structured overview of each testing aspect for the "auth_example" app, including the AuthForm widget, unit tests, widget tests, and integration tests. You can use this documentation as a reference to understand and implement testing strategies in your Flutter app.
Latest comments (0)