variables
Variables in specs
Because Behave specs are plain Raku, my and our variables work exactly as you'd expect. You don't need a special DSL to declare state, though let is usually the right tool when you want per-example memoization with automatic reset.
Top-level variables
Declared at the top of the spec file, visible to every describe and it:
use BDD::Behave;
my $top = 'top-level';
my @numbers = (1, 2, 3);
my %settings = (timeout => 5);
describe 'top-level access', {
it 'reads scalars, arrays, hashes', {
expect($top).to.be('top-level');
expect(@numbers[2]).to.be(3);
expect(%settings<timeout>).to.be(5);
}
}Variables inside describe / context
A my declared inside a describe is shared across that group's examples. Mutations carry over between examples in registration order:
describe 'shared describe-level state', {
my $counter = 0;
it 'a', { expect(++$counter).to.be(1); }
it 'b', { expect(++$counter).to.be(2); }
it 'c', { expect(++$counter).to.be(3); }
}This is the opposite of let, which resets between examples. Reach for let when you want isolation. Use a plain my when you intentionally want shared state.
Shadowing in nested contexts
Inner my declarations shadow outer ones the same way they would in any Raku block:
describe 'shadowing', {
my $value = 'outer';
it 'sees outer', { expect($value).to.be('outer') }
context 'inner', {
my $value = 'inner';
it 'sees inner', { expect($value).to.be('inner') }
}
it 'outer unchanged after nested context', {
expect($value).to.be('outer');
}
}Variables inside it
Variables declared inside an it block are example-local and never leak:
describe 'it-local vars', {
it 'first', { my $x = 'first'; expect($x).to.be('first') }
it 'second', { my $x = 'second'; expect($x).to.be('second') }
}When to use let vs a plain variable
Use a plain my | Use let |
|---|---|
| Shared mutable state across examples | Fresh value per example |
| Cheap constants | Expensive setup that should run lazily |
| Counters, accumulators | Test subjects, fixtures |
let works alongside plain variables: you can mix both in the same describe.
Classes, roles, enums
Type declarations follow the same scoping rules. See Classes inside specs.