Data flow
This view shows what runs when, and whose code it is. Select the diagram to zoom in.
Behat owns the loop, and the library runs at 4 points in it. Those 4 points are the diagram's columns, and its 3 bands say whose code runs each part: Behat and Mink at the top, Behat Steps in the middle and the site under test at the bottom. Inside the Behat Steps band, each box takes the color of its layer, and the numbers give the order:
- The suite starts. Behat reads
behat.phpand loadsBehatStepsExtension, which registers the backends the configuration lists and wires the services.WebContext::assertOneContext()runs as aBeforeSuitehook and fails a suite that registers 2 contexts built onWebContext, such asWebContextandDrupalContext, since both would register every web step. - A scenario starts. Behat builds fresh contexts, and
BackendAwareInitializerinjects the extension's services into each.SkipTagListenerrejects a@behat-steps-skip:tag that names no composed trait.BackendListenergivesBackendRegistrythe scenario's backend order: the configuredbackendslist, with any backend a@backend:tag names moved to the front. Then each trait'sBeforeScenariohook callsskipTag()to check whether the trait is switched off, andassertPrerequisites()fails the scenario when the site lacks what the trait needs. - Each step runs. Behat matches the Gherkin line to a
#[Given],#[When]or#[Then]attribute on a trait method and calls it on the context. The step reaches out 1 of 3 ways: it drives the page through the Mink session, it callsbackendFor()with a capability to read or change the site or it sends a request of its own through 1 of the 3 HTTP clients. It then asserts on what came back, and a failure throws. - The scenario ends. Behat runs the
AfterScenariohooks.EntityLifecycleTraitdeletes the entities the scenario created through its helpers or registered withentityLifecycleRegister(), newest first, andAuthTraitdeletes the scenario's users and then its roles, each through the capability that deletes that entity type. An entity a step creates directly through a backend and never registers stays in place.
The Backend layer explains how backendFor() picks a backend, and the Extension layer what the extension wires up at the start.