Skip to content

Add -Context and -Describe to BeforeEach and AfterEach (#1219)#2913

Draft
nohwnd wants to merge 1 commit into
pester:mainfrom
nohwnd:feature-beforeeach-context
Draft

Add -Context and -Describe to BeforeEach and AfterEach (#1219)#2913
nohwnd wants to merge 1 commit into
pester:mainfrom
nohwnd:feature-beforeeach-context

Conversation

@nohwnd

@nohwnd nohwnd commented Jul 19, 2026

Copy link
Copy Markdown
Member

Draft. Implements #1219.

BeforeEach and AfterEach only run around each test today. This exposes the block level variants that were scaffolded in the runtime but never had a public setter, using the switches I sketched in the issue:

Describe 'my tests' {
    BeforeEach -Context { <# create the resource once per Context #> }
    AfterEach  -Context { <# remove it after each Context #> }

    Context 'context 1' { It 'it 1' { } It 'it 2' { } }
    Context 'context 2' { It 'it 1' { } It 'it 2' { } }
}
  • No switch keeps the classic per-test behavior (-It).
  • The switches combine: BeforeEach -Context -It runs before the Context and before each test in it.
  • -Describe targets Describe blocks, -Context targets Context blocks, using how the block was defined (FrameworkData.CommandUsed).
  • They inherit top down like the other setups, a setup on an outer block runs before every matching nested block, and teardowns run in the opposite order.

No BeforeAll -Context, that one is redundant, BeforeAll already runs once and its side effects persist for the whole subtree. I dropped the now unused OneTimeBlock* leftovers while here.

Scoping: it runs on the block's existing OuterSetup/OuterTeardown, the same path BeforeEach/BeforeAll already use, so no extra scope is introduced, the setup is just inherited down to the child.

Verification

Full test.ps1 run passes (2617 passed, 0 failed). New tests in SetupTeardown.Tests.ps1 cover: -Context wrapping each Context and not the direct tests, inheritance into nested Contexts, -Describe targeting only Describe blocks, and the combined -Context -It order.

Still todo before this leaves draft

  • docs on pester.dev
  • decide if the failure message should name which of the inherited setups failed (cheap to add, each already runs on its own step)

BeforeEach and AfterEach so far only run around each test. This exposes the
block level variants that were scaffolded in the runtime but never had a public
setter, so you can run a setup or teardown around each Context or Describe.

    Describe 'd' {
        BeforeEach -Context { <# runs before every Context in here #> }
        AfterEach  -Context { <# runs after every Context in here #> }
    }

No switch keeps the classic per-test behavior, and the switches combine, so
BeforeEach -Context -It runs before the Context and before each test in it.
-Describe and -Context inherit top down like the other setups (a setup on an
outer block runs before every matching nested block), teardowns run in the
opposite order.

The scriptblock is stored on the block as EachContextSetup / EachDescribeSetup,
and Invoke-Test walks up the ancestors and picks the one that matches how the
child block was defined (FrameworkData.CommandUsed). It runs on the block's
existing OuterSetup/OuterTeardown, so no extra scope is introduced.

Dropped the OneTimeBlock* leftovers while here, BeforeAll -Context makes no
sense since BeforeAll already runs once and its side effects persist for the
whole subtree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fflaten

fflaten commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

I think we'll quickly need a -Local/NoPropagate to only run for direct siblings. Nice to have for BeforeEach -It, but required for blocks as especially Context can have deep structures only used for organization or output.

A workaround would be to use nested Describe for that, but mixing child block types gets messy imo. (Personally I'd want Describe to be root-only and Context child-only groupings.)

@fflaten

fflaten commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Should also work for root block? Currently blocked in Invoke-ContainerRun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants