olexale/bdd_widget_test/bdd-widget-test-gherkin
Claude Code and agent skill by olexale/bdd_widget_test
- community
Checking that the SKILL.md file is still in the repository.
Write `.feature` files and implement step definitions for the bdd_widget_test package, which generates Flutter widget tests from Gherkin. Use when the user is creating or changing feature files, scenarios or steps in a Flutter project that depends on bdd_widget_test, filling in generated step files, sharing steps between features, packages or integration tests, configuring `build.yaml` / `bdd_options.yaml` for bdd_widget_test, or setting up golden or Patrol tests with it.
Install
npx vskill@latest install olexale/bdd_widget_test/bdd-widget-test-gherkinSKILL.md
bdd_widget_test
How generation works
- Every
*.featurefile undertest/(orintegration_test/) is parsed with the official Gherkin
parser (cucumber_gherkin), plus a few package extensions described below.
dart run build_runner build --delete-conflicting-outputs(orwatch) writes a*_test.dart
file next to each feature. That file is regenerated on every build. Never edit it. The build also validates the feature file: invalid Gherkin fails with file, line and column.
- Every step becomes a call to a top-level function in a step file,
<step folder>/<snake_case_name>.dart. For a step with no file yet, the build writes a stub that throws UnimplementedError, or a working implementation for a predefined step.
- Step files are never overwritten. Once a file exists, the generator only imports it. The
project owns it and edits it freely.
- Run the tests with
flutter test(orflutter test integration_test).
Writing feature files
Before writing a step
- Always reuse an existing step before inventing one. List the step folder first (
test/step/
next to the feature by default, or the folder set by stepFolderName in build.yaml / bdd_options.yaml), check externalSteps in the same config, and check the predefined steps. Phrase the new step so it maps to the same function name.
- A step is identified by its function name only. The name is built from the step text with
{} parameters and <placeholders> removed, accents folded to ASCII, punctuation dropped, and the rest camel-cased. The keyword (Given/When/Then/And/But/*) is ignored.
Then I see {'0'} text→iSeeTextini_see_text.dartThen I don't see {'x'} text→iDontSeeText('is dropped)When I tap {Icons.add} icon <times> times→iTapIconTimesGiven I see text {'0'}is the same step asI see {'0'} text, since both areiSeeText.
So the parameters must line up with that function's signature.
- Two phrasings that differ only in articles or word order are different steps
(I see the text → iSeeTheText). Don't write near-duplicates.
- Never write a step whose text, with parameters removed, has no ASCII letter or digit, starts with
a digit (2FA is on), or starts with _. Never write a step made only of a parameter. All of these fail the build.
Parameters: {} holds Dart code
- Whatever is inside
{...}is copied into the generated test verbatim as a Dart expression. - Strings need quotes:
{'Login'}or{"Don't panic"}.{Login}is an identifier, not a string. - Numbers, booleans, types and constants are used as-is:
{42},{true},{Icons.add},
{LoginButton}.
- If a parameter references a symbol the default imports (
material.dart,flutter_test.dart)
don't cover, add the Dart import above Feature:, or configure customHeaders.
- Prefer domain-level parameters (
{'alice@example.com'}) over implementation details such as keys
or private widget types. Steps describe what a user does and sees.
Structure
- Scenarios become
testWidgets, andFeature:andRule:becomegroups. Givenarranges,Whenacts,Thenasserts. The keyword doesn't change which function is called.Background:runs before each scenario of its feature. ABackground:inside aRule:runs
after the feature's background, only for that rule's scenarios. Only one Background: is allowed per feature or rule.
Scenario Outline:/Scenario Template:must haveExamples:/Scenarios:. Example cells are
Dart too. A <placeholder> outside {} is substituted as {value}, and one inside {} is substituted raw. So | result | with a cell '0' passes a String, and 0 passes a number.
- Proofread the top of each block. Gherkin reads every line between
Feature:/Rule:/
Scenario: and the block's first step as description text. Typos that leave a block with no steps (Scenrio: swallowing the steps under it), step keywords written with a colon (Given: the app is running) under a scenario or background, and typos below the first step fail the build with file, line and column. A Feature:/Rule: description stays free text, so a colon step there is not reported. And a mistyped first step of a block that still has other steps (Gven the app is running followed by When ...) is read as description and silently dropped, and so is a mistyped Backround: in a feature that has steps elsewhere.
Tables under a step: two meanings
Read tables.md before putting a table under a step.
- Repeat the step: if the step contains
<placeholders>and the table's header row names all
of them, the step is generated once per row.
- DataTable argument: any other table is passed as a
bdd.DataTableparameter. **Every cell is
a Dart expression**, so quote strings in every row, the header included: | 'artist' | 'name' |.
- Doc strings, opened with
"""or with three backticks, are parsed but their
content is ignored. Don't put a table or data inside one.
Tags
- Tags filter runs (
flutter test --tags important) and are inherited fromFeature:andRule:
by their scenarios. Plain tags may share a line: @slow @integration.
- The package's own value tags go on their own line, because their value runs to the end of the
line and swallows any tag written after it: @testMethodName: patrolTest, @testerType: PatrolIntegrationTester, @testerName: $, @scenarioParams: nativeAutomation: true. Their scopes differ:
@testMethodName: patrolTestmakes the scenario callpatrolTest(...)instead of
testWidgets(...). Above Feature: it applies to every scenario in the file, above one scenario to that scenario only.
@testerType:and@testerName:change the tester parameter's type and name in newly
generated step stubs and in the Background:/After: functions. The test callback itself is untyped, so there only the name changes. They are file-level only: one value is picked from all tags in the file and used for every scenario and step. Put them above Feature:, never above a scenario, where they would also leak into that test's ordinary tag list.
@scenarioParams:takes comma-separated named arguments, which are appended to the test method
call. It is read per scenario, so put it above the scenario it configures, e.g. @scenarioParams: skip: true, timeout: Timeout(Duration(seconds: 5)). The value is split into arguments at every , (comma followed by a space), so no single argument may contain , . Write inner commas without the space: size: Size(400,800).
Package extensions
Use these freely:
After:underFeature:lists steps that run after every scenario of that feature, inside a
finally, so they run even when the scenario fails. Writing it inside a Rule: does not scope it to that rule. It still runs after every scenario of the feature.
- Dart lines above
Feature:are copied to the top of the generated test. Use them for imports
needed by {} parameters and for // ignore_for_file: lint suppressions. They are not copied into step files: add imports a step needs to the step file itself.
- A file may hold several
Feature:s. - Value tags and tables that repeat a step, both described above.
Languages
- To write keywords in another language, put
# language: xxabove the first feature keyword
(below Dart header lines is fine). Step text stays free-form, but its function name is still built from its ASCII characters, so keep some ASCII words in every step. After: stays in English.
Implementing steps
Step files
- One step means one file and one top-level
Future<void>function. The file name is the snake-case
form of the function name: iSeeText lives in i_see_text.dart. Keep both names. The generator finds existing steps by file name and calls them by function name, so renaming either breaks the generated tests.
- You may move step files into subfolders of the step folder (
step/common/,step/login/). The
generator searches the step folder recursively and imports from the new location. Step file names must be unique across the whole step folder. Two files with the same name in different subfolders collide silently, and the last one found wins.
- Never delete a step file to "regenerate" it if it has an implementation. Edit it instead.
- The signature is
(WidgetTester tester, ...params). The generated test passes one argument per
{} parameter and per <placeholder>, in the order they appear in the step text, then bdd.DataTable dataTable last if a DataTable is written under the step.
- Stubs list the
{}parameters first and the<placeholder>ones after them. When a placeholder
comes before a {} parameter in the text (I add <count> items to {'Cart'}), the stub's parameter order doesn't match the call, so reorder the parameters to follow the text.
- Stubs type literal parameters as
String,numorbool, and everything else asdynamic.
Tighten the types (int, IconData, Type, a domain enum) when implementing the step. The generated test passes the raw Dart expression, so any type that expression satisfies works.
- Keep the doc comment at the top of a generated step (
/// Usage:in stubs,/// Example:in
predefined steps). It records the step text the function was made for.
- If the step's text in the
.featurefile changes, the generator creates a new stub for the new
name. Rename the old file and function to match instead of keeping both.
Implementing
- Steps drive the UI through the tester the way a user would:
tester.tap,tester.enterText,
tester.drag, then tester.pump() or tester.pumpAndSettle(). Assert with expect(find..., matcher).
- After an action, pump. Use
pumpAndSettle()for navigation and animations. Usepump()or
pump(duration) when something animates forever (progress indicators), because pumpAndSettle() would time out.
- Keep steps small and reusable. A step may call another step function (
iTapIconTimescalling
iTapIcon). Put shared finders, fakes and setup code in plain helper files outside the step folder (e.g. test/helpers/) and import them. The generator treats every .dart file under the step folder as a step by its file name, so a helper there can shadow a step.
the app is runningis generated to pumpMyApp()frompackage:<app>/main.dart. Change it to
build the real root widget, inject fakes or mocks, and wrap it in whatever providers the app needs.
- Per-test state (fakes, repositories) can live in top-level variables in a helper file that is
reset in a Given step or in Hooks.beforeEach.
- For DataTable steps, see tables.md.
Configuration and recipes
Options go under bdd_widget_test|featureBuilder in build.yaml, or at the top level of bdd_options.yaml in the package root. After changing them, rebuild with --delete-conflicting-outputs.
- Read configuration.md for every option (step folder location,
external steps, hooks, tester type and name, custom headers) and the step lookup order.
- Read recipes.md for hooks, golden tests, integration tests, Patrol, and
steps shared between packages.
Examples
A feature with a background, an After: block and an outline:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/bdd-widget-test-gherkin/SKILL.md
Popularity
- Repository stars
- 114
- Repository forks
- 40
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/olexale/bdd_widget_test/bdd-widget-test-gherkin)