Skip to content

Commit

Permalink
Add function Merge-PSCodeHealthSetting to override default settings w…
Browse files Browse the repository at this point in the history
…ith user-defined settings
  • Loading branch information
MathieuBuisson committed May 7, 2017
1 parent c441013 commit 8c58f97
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 0 deletions.
96 changes: 96 additions & 0 deletions PSCodeHealth/Private/Merge-PSCodeHealthSetting.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
Function Merge-PSCodeHealthSetting {
<#
.SYNOPSIS
Merges user-defined settings (metrics thresholds, etc...) into the default PSCodeHealth settings.
.DESCRIPTION
Merges user-defined settings (metrics thresholds, etc...) into the default PSCodeHealth settings.
The default PSCodeHealth settings are stored in PSCodeHealthSettings.json, but user-defined custom settings can override these defaults.
The custom settings are stored in JSON format in a file (similar to PSCodeHealthSettings.json).
Any setting specified in the custom settings file override the defaults and settings not specified in the custom settings file will use the defaults from PSCodeHealthSettings.json.
.PARAMETER DefaultSettings
PSCustomObject converted from the JSON data in PSCodeHealthSettings.json.
.PARAMETER CustomSettings
PSCustomObject converted from the JSON data in a user-defined custom settings file.
.OUTPUTS
System.Management.Automation.PSCustomObject
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
Param(
[Parameter(Mandatory=$True,Position=0)]
[PSCustomObject]$DefaultSettings,

[Parameter(Mandatory=$True,Position=1)]
[PSCustomObject]$CustomSettings
)

# Checking if $CustomSettings contains something
$ContainsSettings = $CustomSettings | Get-Member -MemberType Properties
If ( -not($ContainsSettings) ) {
Write-VerboseOutput -Message 'Custom settings do not contain any data, the resulting settings will be the defaults.'
return $DefaultSettings
}

$ContainsFunctionHealthRecordSettings = 'FunctionHealthRecordMetricsRules' -in $ContainsSettings.Name
$ContainsOverallHealthReportSettings = 'OverallHealthReportMetricsRules' -in $ContainsSettings.Name

If ( -not($ContainsFunctionHealthRecordSettings) -and -not($ContainsOverallHealthReportSettings) ) {
Write-Warning -Message 'Custom settings do not contain any of the settings groups expected by PSCodeHealth.'
return $DefaultSettings
}

If ( $ContainsFunctionHealthRecordSettings) {
$CustomFunctionSettings = $CustomSettings.FunctionHealthRecordMetricsRules | Where-Object { $_ }

# Casting to a list in case we need to add elements to it
$DefaultFunctionSettings = ($DefaultSettings.FunctionHealthRecordMetricsRules | Where-Object { $_ }) -as [System.Collections.ArrayList]

Foreach ( $CustomFunctionSetting in $CustomFunctionSettings ) {
$MetricName = ($CustomFunctionSetting | Get-Member -MemberType Properties).Name
Write-VerboseOutput -Message "Processing custom settings for metric : $MetricName"

$DefaultFunctionSetting = $DefaultFunctionSettings | Where-Object { $_.$($MetricName) }
If ( $DefaultFunctionSetting ) {
Write-VerboseOutput -Message "The setting '$MetricName' is present in the default settings, overriding it."
$DefaultFunctionSetting.$($MetricName) = $CustomFunctionSetting.$($MetricName)
}
Else {
Write-VerboseOutput -Message "The setting '$MetricName' is absent from the default settings, adding it."
$Null = $DefaultFunctionSettings.Add($CustomFunctionSetting)
}
}
}

If ( $ContainsOverallHealthReportSettings ) {
$CustomOverallSettings = $CustomSettings.OverallHealthReportMetricsRules | Where-Object { $_ }

# Casting to a list in case we need to add elements to it
$DefaultOverallSettings = ($DefaultSettings.OverallHealthReportMetricsRules | Where-Object { $_ }) -as [System.Collections.ArrayList]

Foreach ( $CustomOverallSetting in $CustomOverallSettings ) {
$MetricName = ($CustomOverallSetting | Get-Member -MemberType Properties).Name
Write-VerboseOutput -Message "Processing custom settings for metric : $MetricName"

$DefaultOverallSetting = $DefaultOverallSettings | Where-Object { $_.$($MetricName) }
If ( $DefaultOverallSetting ) {
Write-VerboseOutput -Message "The setting '$MetricName' is present in the default settings, overriding it."
$DefaultOverallSetting.$($MetricName) = $CustomOverallSetting.$($MetricName)
}
Else {
Write-VerboseOutput -Message "The setting '$MetricName' is absent from the default settings, adding it."
$Null = $DefaultOverallSettings.Add($CustomOverallSetting)
}
}
}
$MergedSettingsProperties = [ordered]@{
FunctionHealthRecordMetricsRules = $DefaultFunctionSettings
OverallHealthReportMetricsRules = $DefaultOverallSettings
}
$MergedSettings = New-Object -TypeName PSCustomObject -Property $MergedSettingsProperties
return $MergedSettings
}
131 changes: 131 additions & 0 deletions Tests/Unit/Private/Merge-PSCodeHealthSetting.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
$ModuleName = 'PSCodeHealth'
Import-Module "$PSScriptRoot\..\..\..\$ModuleName\$($ModuleName).psd1" -Force

Describe 'Merge-PSCodeHealthSetting' {
InModuleScope $ModuleName {

$DefaultSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\..\..\PSCodeHealth\PSCodeHealthSettings.json" -Raw)

Context 'Custom settings do not contain any data' {

$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\Empty.json" -Raw )
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings

It 'Should return an object of the type [PSCustomObject]' {
$Result | Should BeOfType [PSCustomObject]
}
It 'Should return an object with the expected property "FunctionHealthRecordMetricsRules"' {
$Result.FunctionHealthRecordMetricsRules | Should Be $DefaultSettings.FunctionHealthRecordMetricsRules
}
It 'Should return an object with the expected property "OverallHealthReportMetricsRules"' {
$Result.OverallHealthReportMetricsRules | Should Be $DefaultSettings.OverallHealthReportMetricsRules
}
}
Context 'Custom settings do not contain any of the expected settings groups' {

$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\NoSettingsGroup.json" -Raw )
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings

It 'Should return an object of the type [PSCustomObject]' {
$Result | Should BeOfType [PSCustomObject]
}
It 'Should return an object with the expected property "FunctionHealthRecordMetricsRules"' {
$Result.FunctionHealthRecordMetricsRules | Should Be $DefaultSettings.FunctionHealthRecordMetricsRules
}
It 'Should return an object with the expected property "OverallHealthReportMetricsRules"' {
$Result.OverallHealthReportMetricsRules | Should Be $DefaultSettings.OverallHealthReportMetricsRules
}
}
Context 'Custom settings contains only expected settings groups and metrics' {

$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\2SettingsGroups4Metrics.json" -Raw )
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings

It 'Should return an object of the type [PSCustomObject]' {
$Result | Should BeOfType [PSCustomObject]
}
It 'Resulting settings are the same as the defaults for metric "LinesOfCode"' {
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.WarningThreshold | Should Be 20
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.FailThreshold | Should Be 40
}
It 'Resulting settings are the same as the defaults for metric "TestCoverage"' {
$Result.FunctionHealthRecordMetricsRules.TestCoverage.WarningThreshold | Should Be 80
$Result.FunctionHealthRecordMetricsRules.TestCoverage.FailThreshold | Should Be 70
}
It 'Resulting settings override the defaults for metric "Complexity"' {
$Result.FunctionHealthRecordMetricsRules.Complexity.WarningThreshold | Should Be 17
$Result.FunctionHealthRecordMetricsRules.Complexity.FailThreshold | Should Be 33
}
It 'Resulting settings override the defaults for metric "MaximumNestingDepth"' {
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.WarningThreshold | Should Be 6
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.FailThreshold | Should Be 12
}
It 'Resulting settings are the same as the defaults for metric "TestsPassRate"' {
$Result.OverallHealthReportMetricsRules.TestsPassRate.WarningThreshold | Should Be 99
$Result.OverallHealthReportMetricsRules.TestsPassRate.FailThreshold | Should Be 97
}
It 'Resulting settings are the same as the defaults for metric "CommandsMissedTotal"' {
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.WarningThreshold | Should Be 20
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.FailThreshold | Should Be 40
}
It 'Resulting settings override the defaults for metric "LinesOfCodeTotal"' {
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.WarningThreshold | Should Be 1500
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.FailThreshold | Should Be 3000
}
It 'Resulting settings override the defaults for metric "LinesOfCodeAverage"' {
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.WarningThreshold | Should Be 21
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.FailThreshold | Should Be 42
}
}
Context 'Custom settings contains expected settings groups but contains metrics absent from the defaults' {

$DefaultSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\..\..\PSCodeHealth\PSCodeHealthSettings.json" -Raw)
$CustomSettings = ConvertFrom-Json (Get-Content -Path "$PSScriptRoot\..\TestData\NewMetrics.json" -Raw )
$Result = Merge-PSCodeHealthSetting -DefaultSettings $DefaultSettings -CustomSettings $CustomSettings

It 'Should return an object of the type [PSCustomObject]' {
$Result | Should BeOfType [PSCustomObject]
}
It 'Resulting settings are the same as the defaults for metric "LinesOfCode"' {
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.WarningThreshold | Should Be 20
$Result.FunctionHealthRecordMetricsRules.LinesOfCode.FailThreshold | Should Be 40
}
It 'Resulting settings are the same as the defaults for metric "TestCoverage"' {
$Result.FunctionHealthRecordMetricsRules.TestCoverage.WarningThreshold | Should Be 80
$Result.FunctionHealthRecordMetricsRules.TestCoverage.FailThreshold | Should Be 70
}
It 'Resulting settings are the same as the defaults for metric "Complexity"' {
$Result.FunctionHealthRecordMetricsRules.Complexity.WarningThreshold | Should Be 15
$Result.FunctionHealthRecordMetricsRules.Complexity.FailThreshold | Should Be 30
}
It 'Resulting settings are the same as the defaults for metric "MaximumNestingDepth"' {
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.WarningThreshold | Should Be 4
$Result.FunctionHealthRecordMetricsRules.MaximumNestingDepth.FailThreshold | Should Be 8
}
It 'Resulting settings are the same as the defaults for metric "TestsPassRate"' {
$Result.OverallHealthReportMetricsRules.TestsPassRate.WarningThreshold | Should Be 99
$Result.OverallHealthReportMetricsRules.TestsPassRate.FailThreshold | Should Be 97
}
It 'Resulting settings are the same as the defaults for metric "CommandsMissedTotal"' {
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.WarningThreshold | Should Be 20
$Result.OverallHealthReportMetricsRules.CommandsMissedTotal.FailThreshold | Should Be 40
}
It 'Resulting settings are the same as the defaults for metric "LinesOfCodeTotal"' {
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.WarningThreshold | Should Be 1000
$Result.OverallHealthReportMetricsRules.LinesOfCodeTotal.FailThreshold | Should Be 2000
}
It 'Resulting settings are the same as the defaults for metric "LinesOfCodeAverage"' {
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.WarningThreshold | Should Be 20
$Result.OverallHealthReportMetricsRules.LinesOfCodeAverage.FailThreshold | Should Be 40
}
It 'Resulting settings have metric absent from the defaults : "DummyMetric"' {
$Result.FunctionHealthRecordMetricsRules.DummyMetric.WarningThreshold | Should Be 2
$Result.FunctionHealthRecordMetricsRules.DummyMetric.FailThreshold | Should Be 4
}
It 'Resulting settings have metric absent from the defaults : "DummyMetric2"' {
$Result.OverallHealthReportMetricsRules.DummyMetric2.WarningThreshold | Should Be 7
$Result.OverallHealthReportMetricsRules.DummyMetric2.FailThreshold | Should Be 8
}
}
}
}
30 changes: 30 additions & 0 deletions Tests/Unit/TestData/2SettingsGroups4Metrics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"FunctionHealthRecordMetricsRules": [
{
"Complexity": {
"WarningThreshold": 17,
"FailThreshold": 33
}
},
{
"MaximumNestingDepth": {
"WarningThreshold": 6,
"FailThreshold": 12
}
}
],
"OverallHealthReportMetricsRules": [
{
"LinesOfCodeTotal": {
"WarningThreshold": 1500,
"FailThreshold": 3000
}
},
{
"LinesOfCodeAverage": {
"WarningThreshold": 21,
"FailThreshold": 42
}
}
]
}
3 changes: 3 additions & 0 deletions Tests/Unit/TestData/Empty.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{

}
18 changes: 18 additions & 0 deletions Tests/Unit/TestData/NewMetrics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"FunctionHealthRecordMetricsRules": [
{
"DummyMetric": {
"WarningThreshold": 2,
"FailThreshold": 4
}
}
],
"OverallHealthReportMetricsRules": [
{
"DummyMetric2": {
"WarningThreshold": 7,
"FailThreshold": 8
}
}
]
}
14 changes: 14 additions & 0 deletions Tests/Unit/TestData/NoSettingsGroup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"LinesOfCodeTotal": {
"WarningThreshold": 1500,
"FailThreshold": 3000
}
},
{
"LinesOfCodeAverage": {
"WarningThreshold": 21,
"FailThreshold": 42
}
}
]

0 comments on commit 8c58f97

Please sign in to comment.