Hooks
Hooks let you define steps that run automatically around your tests. They are defined at the file level and apply to all tests in that file.
FlutterProbe supports two levels of hooks:
- Suite-level:
before allandafter all— run once per file - Test-level:
before each,after each, andon failure— run around every test
before all
Section titled “before all”Runs once before the first test in the file. If it fails, all tests in the file are skipped:
before all open the app tap "Accept Terms" wait for the page to loadUse this for expensive one-time setup like accepting onboarding flows, seeding data, or logging in.
after all
Section titled “after all”Runs once after the last test in the file, regardless of whether tests passed or failed:
after all take screenshot "suite_final" call DELETE "https://api.example.com/test-data"Use this for suite-level teardown like cleaning up test data or capturing final state.
before each
Section titled “before each”Runs before every test in the file:
before each open the app wait for the page to loadUse this for common setup like launching the app, navigating to a screen, or logging in.
after each
Section titled “after each”Runs after every test in the file, regardless of whether the test passed or failed:
after each take screenshot "after_test"Use this for cleanup or final screenshots.
on failure
Section titled “on failure”Runs only when a test fails. Useful for capturing debugging information:
on failure take screenshot "failure" save logs dump treeCombining Hooks
Section titled “Combining Hooks”You can use all five hooks in the same file:
before all open the app tap "Accept Terms"
after all take screenshot "suite_final"
before each see "Home"
after each take screenshot "after_test"
on failure take screenshot "failure_state" save logs dump tree
test "user can view settings" tap "Settings" see "Account" go back
test "user can view profile" tap "Profile" see "Email" go backExecution Order
Section titled “Execution Order”Full execution order for a file with two tests:
before allsteps (once)before eachsteps- Test 1 steps
after eachstepsbefore eachsteps- Test 2 steps
after eachstepsafter allsteps (once)
For a failing test:
before eachsteps- Test steps (until failure)
on failuresteps (best-effort)after eachsteps (best-effort)
If before all fails, all tests in the file are marked as failed and skipped. after all always runs, even if tests failed.
Hooks with Recipes
Section titled “Hooks with Recipes”Hooks can call recipes just like regular test steps:
use "recipes/auth.probe"
before each log in as "test@example.com" with "password"
test "user can update name" tap "Profile" tap "Edit" type "New Name" into "Name" tap "Save" see "New Name"Hooks are file-scoped. Each .probe file can define its own set of hooks. There are no global hooks — if you need the same hooks across multiple files, define them in a recipe and call it from each file’s before each.
before all and after all share a separate executor from the per-test hooks, so state set in before all (like variables) does not carry into individual tests.
Shared App State Across Tests
Section titled “Shared App State Across Tests”All test blocks in a .probe file run against one continuous app instance and connection — nothing resets the app, navigator, or session state between blocks (or hooks) by default. If before all (or an earlier test) signs in, every later test in that file starts from wherever the app was left, still signed in — the same as if a person kept using the app without closing it.
This means:
- A later test failing with “widget not found” for something that should obviously be on screen is a real bug in your test flow (wrong screen, wrong timing, an earlier step left a dialog open) — it is not the framework silently resetting your session. Nothing implicit resets state between tests.
- If you want each test to start from a clean, logged-out state, do it explicitly —
restart the app,clear app data, orkill the appfollowed byopen the appinbefore each(or at the start of the specific test that needs it). Only these verbs actually reset app state; a bareopen the appwhen the agent is already connected is a no-op if the app is already running. - Conversely, if you’re relying on shared state (e.g.
before alllogs in once and every test in the file assumes it’s still signed in), no special opt-in is needed — this is already the default behavior described above.