Replies: 1 comment
-
|
@ptrthomas this looks awesome! We'd gladly use this right now, as-proposed. The only thing that isn't totally clear is how we can run through the suite multiple times (e.g. for each browser). Perhaps a new "suite outline" concept similar to the current scenario outline that allows us to drive the entire suite with multiple iterations, each with their own custom state? I think this might work for the #2857 case as well (if I'm understanding correctly). It could potentially live directly in karate-boot.js with a small config like: boot.configure({
// restricts how many suite instances may be run in parallel - should it multiply or divide Runner threads? Multiply seems the simplest.
threads: 2,
// runs once for each thread and returns outline data to be run sequentially inside the thread - normal Runner thread behavior still applies within the the suite instance
setup(threadIndex, totalThreadCount) {
// custom logic to prepare state for each suite instance
return [{ ... }]
}
})This is obviously a much larger scope, but would perfectly address our use case and vastly improve the reporting experience. We're working around this now by (ab)using a highly customized scenario outline but, as you pointed out, the reporting experience is less than ideal (i.e. all tests under a single scenario per browser and all failures / retries reported together side-by-side). Until we have something like this, I think we will still need a mechanism to collect a list of scenarios at runtime to allow:
If this (or similar) is something you're interested in pursuing then I agree that there is no need to support runtime scenario resolution. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Background
A pattern has come up repeatedly: users want to programmatically orchestrate
test execution — control which scenarios run, in what order, with what retry
behavior, with what shared state — and the current framework doesn't have a
natural home for it. So they reach for whatever's closest and the result is
awkward.
Two recent examples:
add support for line filters in
karate.call#2863 (@jkeys089): grid runs (BrowserStack, Sauce Labs) where a browsersession takes minutes to start. The desired flow is "discover scenarios →
run them sequentially in one session → retry inline on comms-error → defer
the error if retries exhaust → continue". Today this has to be written as
a Scenario Outline that loops a JS
callWithRetry()function over apre-resolved list of scenarios — see the linked PR for the full v1
pattern that depended on internal APIs.
Running multiple Karate suites with different configurations in parallel via JUnit 5 @TestFactory #2857 (@aadam19): same
.featurefiles across N account configurationsfrom
accounts.json. Today this gets written as a JUnit 5@TestFactorythat calls
Karate.run().parallel(5)once per account.These look similar but they want different things. This proposal addresses
only the in-suite case (jkeys089). The cross-suite case (aadam19) is
called out as future work below.
Why feature-files are the wrong home for in-suite orchestration
The current workaround — defining orchestration inside a
.featurefilevia a Scenario Outline +
karate.call(...)loop — has a fatal structuralproblem: the report tree is wrong. Every scenario shows up nested under
one parent scenario's
callstep, instead of as its own top-level scenarioresult. So a run of 200 scenarios across 5 browsers becomes 5 deeply-nested
trees in HTML / JSONL / Cucumber JSON, rather than 1000 properly-attributed
scenario results. Pass/fail counters, embeds, retries — all flattened.
The orchestration logic and the test logic want to live at different layers.
Context:
karate-boot.jsis brand newWorth flagging up front, because the mechanism is recent enough that most
users won't have come across it yet:
karate-boot.jsis the firstJS-native suite-level entry point Karate has ever had. It landed only in
the last few releases of v2 and is currently scoped to plugin configuration
(
boot.plugin('agent'), etc.) and a smallboot.*helper namespace(
boot.env,boot.sysenv,boot.read,boot.log). It runs once perSuite, before
SUITE_ENTERfires, and can registerRunListener-backedplugins. See docs/DESIGN.md → Plugin + karate-boot.js
for the full surface today.
What this proposal does is extend that nascent JS-at-the-suite-level layer
into a second responsibility: declarative lifecycle hooks. And we
anticipate a third in time — JS-driven production and execution of suites
(the
karate-runner.jsdirection sketched under future work). Theend-state Karate is heading toward: a small, coherent JS surface for
operating on suites that gives non-Java teams the same control Java users
have had via
RuntimeHook/Runner.Builder— without forcing them into aJava toolchain.
Proposed direction —
karate-boot.jsgrows lifecycle hooksJS-native hooks on the existing Suite lifecycle, so users don't need to
author a Java plugin to interpose on execution:
Key properties:
RuntimeHook. A strategic direction for Karate hasbeen giving non-Java teams the same level of control that has historically
only been available through Java-side hook implementations. JS-native
lifecycle hooks close that gap directly.
stateabove), naturallyscoped to the Suite. No per-scenario plumbing needed.
{action: 'retry' | 'skip' | 'defer' | 'continue'}. More expressive than the current booleanRunListener.onEventreturn, and the explicit
actionkeyword makes the intent readable atthe call site (vs. helper-method side effects like
info.retry()).result. Retries become a first-class
attempts: [{result, duration, error}]array on the existing scenario, not a new nested call tree.karate-boot.jsthat already handlesplugin config.
What this replaces / makes unnecessary
RuntimeHookimplementations for in-suite control flow.callWithRetryJS function inadd support for line filters in
karate.call#2863).resolveScenariosuse case in add support for line filters inkarate.call#2863 — if you can hook theruntime, you don't need to enumerate scenarios up-front. (The narrower
karate.call('file.feature:N')syntax we just landed for retry-from-reportflows is still useful, but it stops being a workaround for the missing
orchestration layer.)
Out of scope / future work
Cross-suite orchestration (Running multiple Karate suites with different configurations in parallel via JUnit 5 @TestFactory #2857). The natural continuation of the
JS-at-the-suite-level layer this proposal extends: a separate
karate-runner.jswith arunner.*API that replaces the defaultpath-scan-then-parallel loop, letting users iterate Suites over a data
source. The name deliberately echoes the Java-side
Runner.BuilderAPIso the mental model carries over. Likely shape:
Linked here for context; this proposal is only the in-suite hook surface.
Open questions
first-class
attempts[]field. JSONL schema bump. What's the rightdefault for the legacy pass/fail counter — count only the final attempt,
or count every attempt as a separate event? Instinct: final attempt for
counters, full history in
attempts[].boot file is the proposed primitive (see
state.driverabove). Is thatenough, or do we need first-class "suite-scoped resource" helpers
(acquire/release patterns, lazy init)?
suiteEnter/Exit,featureEnter/Exit,scenarioEnter/Exit,scenarioFailure. ShouldstepEnter/Exit/httpEnter/Exitalso be exposed, or are those better left to theexisting
RunListenerJava-plugin path (too noisy / too fine-grainedfor JS)?
configure beforeScenario/afterScenario/
onStepFailurekeys. Those are scenario-scoped (set inside afeature). These new boot-level hooks would be suite-scoped (set once for
the whole run). Both should coexist — but the precedence order needs to
be spelled out.
Ask
@jkeys089 — if this direction looks promising, we'd suggest holding off on
#2863 (the cascade fix and call-by-line syntax are already on
main). Thediscovery/resolver part can come back as a hook-based design instead. We'd
love your feedback on:
resolver?
karate-boot.jsenough, or do you have requirements that need first-classsupport?
And @aadam19 — the in-suite hooks aren't your case, but the future
karate-runner.jsdirection in "Out of scope" above is. Comments on whetherthat shape would replace your
@TestFactorypattern welcome.Beta Was this translation helpful? Give feedback.
All reactions