subject¶
subject defines the primary value under test in a describe or context block. It is implemented as a let under the name :subject, so all of let's lazy-and-memoized semantics apply.
Use subject when you want to name "the thing this group is about" once and refer to it across many examples.
Defining a subject¶
Three forms are accepted:
1 2 3 | |
When a name is given, the value is reachable through both the given name and :subject — they share a single memoized evaluation per example.
Reading the subject¶
There are three ways to read the subject:
1. The subject() reader¶
Inside an example, calling subject() with no arguments returns the memoized value:
1 2 3 4 5 6 7 | |
subject() outside an example body raises an error.
2. Named-argument form in expect¶
1 2 3 4 5 6 7 | |
3. Through the given name when subject(:name, ...) is used¶
1 2 3 4 5 6 7 8 9 10 11 | |
Memoization¶
subject is lazy: the block runs the first time it's read in an example, and the value is cached for subsequent reads in the same example. Between examples the cache is reset.
1 2 3 4 5 6 7 8 9 | |
Shadowing¶
Inner subject definitions shadow outer ones for examples in the inner group:
1 2 3 4 5 6 7 8 9 10 11 | |
subject-bang (eager evaluation)¶
subject-bang is the Raku-friendly spelling of RSpec's subject!. It defines a subject like subject does, but the block is forced before every example body so any side effects in the block run whether or not the example reads the value.
1 2 3 4 5 6 7 | |
subject-bang accepts the same three forms as subject:
1 2 3 | |
It registers the let definition(s) and a before-each hook in the current group that forces :subject. Memoization is the same as subject — the block runs at most once per example.
When to use subject-bang¶
Use subject-bang when the creation of the subject is itself the test setup — typically for inserting database rows or otherwise mutating state that the example depends on existing before it runs. For pure values, plain subject is preferred because it stays cheap when the example doesn't actually read the value.
Restrictions¶
subject-bangmust be called inside adescribeorcontext. At the top-level (suite scope), only plainsubjectis supported.- Inside an
itblock, usesubject()orexpect(:subject)to read the value; eager forcing is meaningless once you're already in the example body.
is-expected¶
is-expected is a helper that builds an expect against the current :subject. It is the Behave equivalent of RSpec's is_expected.
1 2 3 4 5 6 | |
is-expected reads the memoized subject value via $*LET-RUNTIME and returns an ExpectationBuilder, so the same .to / .not.to chain that you use with expect applies. Multiple calls within the same example share the subject's memoization — the subject block runs at most once per example.
Restrictions¶
is-expectedmust be called inside an example body.- A
subject(orsubject-bang) must be defined in the enclosingdescribe/contextchain. Callingis-expectedwithout one raises a clear error.
One-liner it form¶
For terse, single-expectation examples you can omit the description:
1 2 3 4 5 6 | |
When it is called with only a block, Behave generates the description from the first matcher invoked in the example. The above renders as:
1 2 3 4 | |
Negation (expect(...).not.to.be(...) or is-expected.not.to.be(...)) flips the verb to should not. If the block runs no matchers — for example, it { 1 + 1 } — Behave falls back to a placeholder of the form example at <basename>:<line>.
The block-only form composes with fit and xit:
1 2 | |
Description filtering¶
--example PATTERN matches against the description that was registered with the example, which for block-only it { ... } is the placeholder (e.g. example at foo-spec.raku:42), not the matcher-derived rendering. To filter on the rendered description, use a regular it 'should be X', { ... } form instead.
Comparison with let¶
subject is sugar around let(:subject, ...). The two are interchangeable when reading via :subject, but subject makes the intent — "this is what I'm testing" — explicit and adds the dual-name alias when you give it a name. Use subject for the value under test and let for everything else (inputs, fixtures, helpers).