Skip to main content
Version: 6.2.2 (Unmaintained)

Builder

Builder is a sealed interface for constructing immutable Action instances.

public sealed interface Builder
permits Conditional.Builder,
Instance.Builder,
Isolated.Builder,
Parallel.Builder,
Repeat.Builder,
Scope.Builder,
Sequential.Builder,
Static.Builder, // Deprecated since 6.2 — use Scope.Builder instead
Timeout.Builder,
Until.Builder {

Action build();
}

Design​

Each Action subtype that requires configuration exposes a corresponding Builder nested class. Callers configure the builder, then call build() to produce an immutable action snapshot. Builders are reusable — build() may be called multiple times.

Builder subtypes​

BuilderProducesDescription
Sequential.BuilderSequentialSequential execution; .child(action) adds children, .dependent()/.independent() controls failure propagation.
Parallel.BuilderParallelConcurrent execution; .parallelism(int) controls in-flight count.
Scope.BuilderScopeBefore-body-after with lifecycle guarantee.
Static.BuilderStaticBefore-body-after without fixture instance. (Deprecated since 6.2 — use Scope.Builder instead.)
Instance.BuilderInstanceFixture instance lifecycle; .body(action) sets the body.
Isolated.BuilderIsolatedNamed-lock execution; .body(action) sets the protected child.
Repeat.BuilderRepeatExecutes child action N times.
Timeout.BuilderTimeoutExecutes child action with wall-clock deadline.
Conditional.BuilderConditionalEvaluates a runtime predicate and gates body execution.
Until.BuilderUntilExecutes child repeatedly until predicate satisfied, body passes, or iterations exhausted; .until(Predicate) optional, rejects null. Without .until(), the loop stops when the body passes and reports PASSED.

Named builder entry points​

For common configurations that need quick action tree definitions, each composite action provides a static method named after the action (e.g., Scope.scope(name), Parallel.parallel(name)) that returns its Builder. Import these statically as a shorthand. See Named Builders.

Terminal actions Step and Delay provide named factory methods (step(name, consumer), delay(name, ms), delayRandom(name, min, max)) that return the action directly, also suitable for static imports.

Usage​

import static org.paramixel.api.action.Sequential.sequential;
import static org.paramixel.api.action.Step.step;

Action action = sequential("flow")
.child(step("step one", ctx -> stepOne()))
.child(step("step two", ctx -> stepTwo()))
.build();

var result = Runner.defaultRunner().run(action);

Each action factory method returns a Builder:

import static org.paramixel.api.action.Scope.scope;
import static org.paramixel.api.action.Instance.instance;
import static org.paramixel.api.action.Step.step;

Action scoped = scope("browser test")
.before(step("start", ctx -> start()))
.body(step("test", ctx -> test()))
.after(step("stop", ctx -> stop()))
.build();

Action fixture = instance("user test", UserFixture::new)
.body(step("verify", Context.withInstance(UserFixture.class, f -> f.verify())))
.build();

Sequential.Builder supports dependent/independent failure propagation:

import static org.paramixel.api.action.Sequential.sequential;

var dependent = sequential("flow")
.dependent()
.child(failingStep)
.child(skippedStep)
.build();

var independent = sequential("flow")
.independent()
.child(failingStep)
.child(stillRunsStep)
.build();

Shuffled execution​

Both Sequential.Builder and Parallel.Builder support randomizing child execution order with .shuffle():

import static org.paramixel.api.action.Sequential.sequential;
import static org.paramixel.api.action.Step.step;

var seq = sequential("checkout")
.shuffle()
.child(step("add to cart", ctx -> addToCart()))
.child(step("checkout", ctx -> checkout()))
.child(step("verify", ctx -> verify()))
.build();

.shuffle() generates a seed from ThreadLocalRandom at build time. For reproducible ordering — essential when investigating flaky order-dependent failures — use .shuffle(long seed):

import static org.paramixel.api.action.Sequential.sequential;
import static org.paramixel.api.action.Step.step;

var seq = sequential("checkout")
.shuffle(42L)
.child(step("add to cart", ctx -> addToCart()))
.child(step("checkout", ctx -> checkout()))
.child(step("verify", ctx -> verify()))
.build();

The stored seed is accessible via Sequential.seed() and Parallel.seed(). When .shuffle() is not called, isShuffled() returns false and children execute in insertion order.

See Action for the Action sealed interface and its subtypes.