psake / PowerShellBuild

Common build tasks for psake and Invoke-Build that build and test PowerShell modules
MIT License
133 stars 24 forks source link

Project module not explicitly imported during testing #45

Closed joeypiccola closed 4 years ago

joeypiccola commented 4 years ago

Pester tests that use InModuleScope fail to run because the psake Pester task does not import the project module. In addition to this issue, the module should be imported from the build output directory. This issue is difficult to reproduce as 1) it is dependant on Pester tests that use InModuleScope and 2) some other suit of tests (usually help.tests.ps1) having not already imported the module.

Expected Behavior

Test-PSBuildPester that is called by the psake Pester task should import the project module from the output directory.

Current Behavior

Pester tests that use InModuleScope fail to run resulting in the Pester test erroring with RuntimeException: No module named 'xyz' is currently loaded..

Possible Solution

Test-PSBuildPester that is called by the psake Pester task should import the project module from the output directory. Create a build property in the test hash named ModuleOutputManifest that is equal to the path of the built .psd1 file. This .psd1 file will be loaded within Test-PSBuildPester for use with all Pester tests.

Steps to Reproduce (for bugs)

  1. build a module with plaster via the current Stucco template 0.2.0
  2. create a pester test that uses InModuleScope
  3. run build.ps1 -bootstrap
  4. run build.ps1 -task pester

Context

I am unable to use PowerShellBuild's psake Pester Task on Pester tests that use InModuleScope.

Your Environment

JustinGrote commented 4 years ago

Why not just import the module as part of your pester script, using $PSSCRIPTROOT for the relative location?

That said, I'd see this being useful if gated behind a PSBPreference setting, because there are scenarios where you don't want to import the module during testing or some tests (especially around assemblies that can't be unloaded)

joeypiccola commented 4 years ago

Why not just import the module as part of your pester script, using $PSSCRIPTROOT for the relative location?

I guess because I prefer to keep my .tests.ps1 files simple and not have extraneous code in there to load the module. Did I understand your question correctly?

gated behind a PSBPreference setting

That's a good callout and has me questioning my proposed solution (#46). The link below #L51-L54 unloads any previously imported project modules and loads the copy from the output directory. I am not sure how this behavior will muck with .tests.ps1 files that also attempt to load the module. https://github.com/joeypiccola/PowerShellBuild/blob/16d596d323cd381ba121fc505ca5b4792d6e393c/PowerShellBuild/Public/Test-PSBuildPester.ps1#L51-L54

joeypiccola commented 4 years ago

@JustinGrote Well now you have me questioning if this is even an issue when I can (like you suggested) just import my module in my test. The snippet below (not mine) is all that is needed. Curious @devblackops thoughts on this given we chatted about it.

$moduleName         = $env:BHProjectName
$manifest           = Import-PowerShellDataFile -Path $env:BHPSModuleManifest
$outputDir          = Join-Path -Path $ENV:BHProjectPath -ChildPath 'Output'
$outputModDir       = Join-Path -Path $outputDir -ChildPath $env:BHProjectName
$outputModVerDir    = Join-Path -Path $outputModDir -ChildPath $manifest.ModuleVersion
$outputManifestPath = Join-Path -Path $outputModVerDir -Child "$($moduleName).psd1"
import-module $outputManifestPath
pauby commented 4 years ago

I would prefer not having the module automatically imported as I would prefer to have the flexibility to do that myself if needed. I'd also prefer to try and keep my build / tests as agnostic as possible.

JustinGrote commented 4 years ago

I generally run my pester tests as a separate powershell job in my build script, so that it is isolated to a separate process, and if I have to load any assemblies or anything, they aren't locked afterwards because they will be released on process exit.

joeypiccola commented 4 years ago

Thanks @pauby & @JustinGrote for the feedback. I like the idea 💡 of a PSBPreference (e.g. $PSBPreference.Test.ImportModule). Let me push these changes, curious if you all like it/find it a worth addition/option to PowerShellBuild.

devblackops commented 4 years ago

I like both of these ideas. How about making it a configurable option to automatically import the module prior to running Pester with $PSBPreference.Test.ImportModule, and another option to run the Pester in a PS job? Sometime like $PSBPreference.Test.RunAsJob.

When running Pester in a job, I think it should still rely on $PSBPreference.Test.ImportModule to import it for you.

What do you think?

joeypiccola commented 4 years ago

I like that idea, though I'm not sure I can implement the PS job piece. Perhaps that should be a new and separate issue? As for $PSBPreference.Test.ImportModule that's pretty much implemented in PR #46. Though, as I mentioned to @pauby it mucks with PSBPreference.Build.ModuleOurDir. Thoughts on how to better implement it?