Last updated:
0 purchases
finder matcher annotation
Finder Matcher Gen #
❗ This package contains annotations for finder_matcher_gen. You cannot use this package independently of finder_matcher_gen.
Motivation ✨
Installation 💻
Annotation usage 🎮
@Match annotation
Finders 🔍
Matcher
@MatchDeclaration annotation
Linting
Generate code
Configure generation for integration tests
Detailed Documentation 📄
Bugs/Request 🐛
Continuous Integration 🤖
Running Tests 🧪
A Flutter package for generating custom Finder and Matcher for widget tests. Not sure what a Matcher or Finder is? Visit finder-matcher-gen documentation.
✨ Motivation #
I find myself writing custom Finder and Matcher to abstract validation code for widget/integration tests. Implementing these can be tedious.
Finder-Matcher-Gen tries to fix this by implementing these custom classes for you.
Before
After
Finder
Matcher
💻 Installation #
❗ In order to start using Finder Matcher Gen you must have the Dart SDK installed on your machine.
Add finder_matcher_gen to your pubspec.yaml:
Run the following command on your terminal:
flutter pub add finder_matcher_annotation
copied to clipboard
flutter pub add finder_matcher_gen --dev
copied to clipboard
flutter pub add build_runner --dev
copied to clipboard
Or add it manually to your pubspec.yaml file.
dependencies:
finder_matcher_annotation: ^[version]
dev_dependencies:
finder_matcher_gen: ^[version]
build_runner: ^[version]
copied to clipboard
Run the command below to install.
Install it:
flutter pub get
copied to clipboard
Copy and paste the code below into your test file to import.
import 'package:finder_matcher_annotation/finder_matcher_annotation.dart';
copied to clipboard
🚀 Annotation usage #
Finder-matcher-gen makes use of annotation declarations to generate code. This tool provides two annotations: @Match and @MatchDeclaration annotations.
@Match annotation #
Apply @Match annotation to a declaration, usually, the test main() function to specify widgets to generate a finder or matcher counterpart.
@Match(finders: [], matchers: [])
void main() {
//Test code in here
}
copied to clipboard
The @Match annotation accepts two parameters: a list of Type for finders; a list of MatchWidget for matchers.
Finders
For a widget named TrafficLightLampWidget pass the type of the widget to the finders param of the @Match annotation to generate a finder counterpart.
@Match(finders: [TrafficLightLampWidget])
copied to clipboard
You can pass any number of widget types to the finders param to generate a finder counterpart.
Matcher
Pass a list of MatchWidget to the matchers param. MatchWidgets accepts three params.
A required type: The runtime representation of this widget to generate a matcher counterpart.
A required matchSpecification: An enum of MatchSpecification to define the kind of Matcher to generate for this widget.
An optional secondaryType: The runtime representation of another widget that this Matcher will utilise.
Some Matcher specifications involve a different widget. For example, to generate a matcher that asserts if WidgetA is contained in WidgetB, WidgetB will be passed as the secondaryType.
@Match(matchers: [
MatchWidget(TrafficLightLampWidget, MatchSpecification.matchesOneWidget),
])
copied to clipboard
To learn more about the different match specifications you can set, click here.
@MatchDeclaration annotation #
In most cases, declarations (getters, fields, functions) defined in a widget are essential to the widget’s identity. In other words, they will be used for asserting this widget behaviour.
Annotate widget fields, getters, or functions with @MatchDeclaration to mark them for use in the validation code. The @MatchDeclaration annotation accepts a defaultValue argument used to compare to the actual value of the widget found in the test environment. A constructor field for this declaration will be added to the generated code if no default value is provided.
class RedTrafficLightLampWidget extends StatelessWidget{
@MatchDeclaration()
final Color lightColor;
@MatchDeclaration(defaultValue: 'STOP')
final String text;
}
copied to clipboard
The code below highlights the result of providing a default value and otherwise.
/// Where `_lightColor` is a constructor field of this generated code
return widget.lightColor == _lightColor && widget.text == 'STOP';
copied to clipboard
Linting #
A common pitfall while using this annotation is passing a wrong data type (different from the data type of the annotated property) to the defaultValue.
Fortunately, this package provides static analysis to throw an error when this kind of mistake is made.
Note: The annotation @MatchDeclaration can only be used on getters, fields, and non-void methods
🏭 Generate code #
Run the command below to generate the custom finder and matcher code.
flutter pub run build_runner build
copied to clipboard
After a successful run, you should notice two newly generated files.
A ${my_test_file}.finders.dart file containing generated finders.
A ${my_test_file}.matchers.dart file containing generated matchers.
For more information, see generate section to explore how to use generated files.
Configure generation for integration tests #
Create a build.yaml file in the top-level folder of your project. Insert the code below in the newly created file.
targets:
$default:
sources:
- integration_test/**
- lib/**
- test/**
# Note that it is important to include these in the default target.
- pubspec.*
- $package$
copied to clipboard
You can also include custom folders where you need to generate matchers and finders.
📄 Detailed Documentation #
For more detailed information of using this tool, visit the documentation.
🐛 Bugs/Request #
If you encounter any problems feel free to open an issue. If you feel the library is missing a feature, please raise a ticket on Github and I'll look into it. Pull requests are also welcomed.
🤖 Continuous Integration #
Finder Matcher Gen comes with a built-in GitHub Actions workflow powered by Very Good Workflows but you can also add your preferred CI/CD solution.
Out of the box, on each pull request and push, the CI formats, lints, and tests the code. This ensures the code remains consistent and behaves correctly as you add functionality or make changes. The project uses Very Good Analysis for a strict set of analysis options used by our team. Code coverage is enforced using the Very Good Workflows.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.