finder_matcher_gen 0.1.0 finder_matcher_gen: ^0.1.0 copied to clipboard
A Flutter package for generating custom Finders and Matchers for widget tests.
Finder Matcher Gen #
Table of contents generated with markdown-toc
A Flutter package for generating custom Finders and Matchers for widget tests.
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
flutter pub add finder_matcher_gen --dev
flutter pub add build_runner --dev
Or add it manually to your pubspec.yaml file.
dependencies:
finder_matcher_annotation: ^[version]
dev_dependencies:
finder_matcher_gen: ^[version]
build_runner: ^[version]
Run the command below to install.
Install it:
flutter pub get
Copy and paste the code below into your test file to import.
import 'package:finder_matcher_annotation/finder_matcher_annotation.dart';
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
}
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])
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 ofMatchSpecification
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 inWidgetB
,WidgetB
will be passed as thesecondaryType
.
@Match(matchers: [
MatchWidget(TrafficLightLampWidget, MatchSpecification.matchesOneWidget),
])
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;
}
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';
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
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.
Detailed Documentation #
For more detailed information of using this tool, visit the documentation.
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.
Running Tests 🧪 #
To run all unit tests:
dart pub global activate coverage 1.2.0
dart test --coverage=coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info
To view the generated coverage report you can use lcov.
# Generate Coverage Report
genhtml coverage/lcov.info -o coverage/
# Open Coverage Report
open coverage/index.html