Skip to content

Invoke-Pester no longer overwrites the caller's $p and $d - #3061

Open
GioAbq wants to merge 1 commit into
pester:mainfrom
GioAbq:fix/invoke-pester-caller-variables
Open

GioAbq wants to merge 1 commit into
pester:mainfrom
GioAbq:fix/invoke-pester-caller-variables

Conversation

@GioAbq

@GioAbq GioAbq commented Oct 16, 2026 •

Copy link
Copy Markdown

PR Summary

Invoke-Pester replaced the caller's $p and $d with Pester internals: the path to Pester.ScriptScope.ps1 and a hashtable with the scriptblock to run. A script that kept its own path in $p and wrote to it after running tests wrote into Pester's installation instead.

The cause is in Invoke-InNewScriptScope. It dot-sourced its wrapper, which is bound to the caller's session state, so the wrapper's parameters $p and $d were bound in the caller's current scope. private: does not prevent that.

The fix calls the wrapper with & instead of .. The wrapper gets its own scope, and Pester.ScriptScope.ps1 still runs as a script file, so the new script scope is still pushed. Invoke-File already calls its wrapper this way.

Tests added in tst/Pester.RSpec.ts.ps1:

  • the caller's $p and $d keep their values after Invoke-Pester;
  • Invoke-Pester does not create $p or $d in the caller's scope.

Both fail without the fix and pass with it.

Local runs on Windows 11:

  • ./test.ps1 on PowerShell 7.6.7 with the en-US UI culture: all P tests pass; 2946 Pester tests pass and 1 fails. The same test fails on unmodified main on this machine: Mock.Tests.ps1 "mocks without extension and calls with extension", because notepad resolves to Git for Windows' usr/bin/notepad here.
  • tst/Pester.RSpec.ts.ps1 on Windows PowerShell 5.1: 130 of 130 pass.

Fix #3060

PR Checklist

  • PR has meaningful title
  • Summary describes changes
  • PR is ready to be merged
  • Tests are added/update (if required)
  • Documentation is updated/added (if required) - not required, no documented behavior changes

🤖

Invoke-InNewScriptScope dot-sourced a wrapper bound to the caller's
session state, so the wrapper's parameters $p and $d were bound in the
caller's current scope. Invoke-Pester replaced the caller's $p with the
path to Pester.ScriptScope.ps1 and $d with a hashtable of its own.

Calling the wrapper with & gives it its own scope. The script file it
runs still pushes the new script scope, as in Invoke-File.

🤖
@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@98e56d6). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3061   +/-   ##
=======================================
  Coverage        ?   91.72%           
=======================================
  Files           ?        2           
  Lines           ?     8359           
  Branches        ?        0           
=======================================
  Hits            ?     7667           
  Misses          ?      692           
  Partials        ?        0           
Flag Coverage Δ
ps51-windows-2022 91.15% <ø> (?)
ps51-windows-latest 91.17% <ø> (?)
ps7-macos-14 90.57% <ø> (?)
ps7-macos-latest 90.57% <ø> (?)
ps7-ubuntu-2204 90.58% <ø> (?)
ps7-ubuntu-latest 90.59% <ø> (?)
ps7-windows-2022 91.25% <ø> (?)
ps7-windows-latest 91.25% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Invoke-Pester overwrites the caller's $p and $d variables

1 participant