From 54a29cded77a843830b0c491e43c043259a93a32 Mon Sep 17 00:00:00 2001 From: dfinke Date: Sun, 1 Oct 2017 13:05:55 -0400 Subject: [PATCH 1/6] First pass at adding std deviation to measure-object --- .../commands/utility/Measure-Object.cs | 56 ++- .../Measure-Object.Tests.ps1 | 406 +++++++++--------- 2 files changed, 247 insertions(+), 215 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs index 977fd640670..ba9e57384f2 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -35,7 +35,7 @@ public sealed class GenericMeasureInfo : MeasureInfo /// public GenericMeasureInfo() { - Average = Sum = Maximum = Minimum = null; + Average = Sum = Maximum = Minimum = StdDeviation = null; } /// @@ -72,6 +72,13 @@ public GenericMeasureInfo() /// /// public double? Minimum { get; set; } + + /// + /// + /// The StdDeviation of property values + /// + /// + public double? StdDeviation { get; set; } } /// @@ -91,7 +98,7 @@ public sealed class GenericObjectMeasureInfo : MeasureInfo /// public GenericObjectMeasureInfo() { - Average = Sum = null; + Average = Sum = StdDeviation = null; Maximum = Minimum = null; } @@ -129,6 +136,13 @@ public GenericObjectMeasureInfo() /// /// public object Minimum { get; set; } + + /// + /// + /// The StdDeviation of property values + /// + /// + public double? StdDeviation { get; set; } } @@ -227,6 +241,8 @@ private class Statistics // Generic/Numeric statistics internal double sum = 0.0; + internal double stdDeviation = 0.0; + internal List stdDeviationNumbers = new List(); internal object max = null; internal object min = null; @@ -265,6 +281,25 @@ public MeasureObjectCommand() #endregion Common parameters in both sets + /// + /// Set to true is StdDeviation is to be returned + /// + /// + [Parameter(ParameterSetName = GenericParameterSet)] + public SwitchParameter StdDeviation + { + get + { + return _measureStdDeviation; + } + set + { + _measureStdDeviation = value; + } + } + + private bool _measureStdDeviation; + /// /// Set to true is Sum is to be returned /// @@ -713,6 +748,8 @@ private void AnalyzeNumber(double numValue, Statistics stat) { if (_measureSum || _measureAverage) stat.sum += numValue; + if (_measureStdDeviation) + stat.stdDeviationNumbers.Add(numValue); } /// @@ -793,6 +830,7 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene { double? sum = null; double? average = null; + double? stdDeviation = null; object max = null; object min = null; @@ -800,8 +838,21 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene { if (_measureSum) sum = stat.sum; + if (_measureAverage && stat.count > 0) average = stat.sum / stat.count; + + if (_measureStdDeviation && _measureAverage && stat.count > 0) + { + var popdev = 0.0; + + foreach (double n in stat.stdDeviationNumbers) + { + popdev += Math.Pow((n - (double)average), 2); + } + + stdDeviation = Math.Round(Math.Sqrt(popdev / (stat.stdDeviationNumbers.Count - 1)), 4); + } } if (_measureMax) @@ -838,6 +889,7 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene gmi.Count = stat.count; gmi.Sum = sum; gmi.Average = average; + gmi.StdDeviation = stdDeviation; if (null != max) { gmi.Maximum = (double)max; diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 index e82baa82d7f..4e52ecc5174 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 @@ -1,28 +1,38 @@ Describe "Measure-Object" -Tags "CI" { - $testObject = 1,3,4 + $testObject = 1, 3, 4 It "Should be able to be called without error" { - { Measure-Object | Out-Null } | Should Not Throw + { Measure-Object | Out-Null } | Should Not Throw } It "Should be able to call on piped input" { - { $testObject | Measure-Object } | Should Not Throw + { $testObject | Measure-Object } | Should Not Throw } It "Should be able to count the number of objects input to it" { - $($testObject | Measure-Object).Count | Should Be $testObject.Length + $($testObject | Measure-Object).Count | Should Be $testObject.Length + } + + It "Should calculate Std Deviation" { + $actual = ($testObject | Measure-Object -Average -StdDeviation) + $actual.StdDeviation | Should Be 1.5275 + } + + It "Should not calculate Std Deviation if -Average not specified" { + $actual = ($testObject | Measure-Object -StdDeviation) + $actual.StdDeviation | Should BeNullOrEmpty } It "Should be able to count using the Property switch" { - $expected = $(Get-ChildItem $TestDrive).Length - $actual = $(Get-ChildItem $TestDrive | Measure-Object -Property Length).Count + $expected = $(Get-ChildItem $TestDrive).Length + $actual = $(Get-ChildItem $TestDrive | Measure-Object -Property Length).Count - $actual | Should Be $expected + $actual | Should Be $expected } It "Should be able to use wildcards for the Property argument" { $data = [pscustomobject]@{ A1 = 1; A2 = 2; C3 = 3 }, - [pscustomobject]@{ A1 = 1; A2 = 2; A3 = 3 } + [pscustomobject]@{ A1 = 1; A2 = 2; A3 = 3 } $actual = $data | Measure-Object -Property A* -Sum $actual.Count | Should Be 3 $actual[0].Property | Should Be A1 @@ -37,133 +47,122 @@ Describe "Measure-Object" -Tags "CI" { } Context "Numeric tests" { - It "Should be able to sum" { - $actual = $testObject | Measure-Object -Sum - $expected = 0 + It "Should be able to sum" { + $actual = $testObject | Measure-Object -Sum + $expected = 0 - foreach ( $obj in $testObject ) - { - $expected += $obj - } + foreach ( $obj in $testObject ) { + $expected += $obj + } - $actual.Sum | Should Be $expected - } + $actual.Sum | Should Be $expected + } - It "Should be able to average" { - $actual = $testObject | Measure-Object -Average - $expected = 0 + It "Should be able to average" { + $actual = $testObject | Measure-Object -Average + $expected = 0 - foreach ( $obj in $testObject ) - { - $expected += $obj - } + foreach ( $obj in $testObject ) { + $expected += $obj + } - $expected /= $testObject.length + $expected /= $testObject.length - $actual.Average | Should Be $expected - } + $actual.Average | Should Be $expected + } - It "Should be able to return a minimum" { - $actual = $testObject | Measure-Object -Minimum - $expected = $testObject[0] + It "Should be able to return a minimum" { + $actual = $testObject | Measure-Object -Minimum + $expected = $testObject[0] - for ($i=0; $i -lt $testObject.length; $i++) - { - if ( $testObject[$i] -lt $expected ) - { + for ($i = 0; $i -lt $testObject.length; $i++) { + if ( $testObject[$i] -lt $expected ) { - $expected = $testObject[$i] - } - } + $expected = $testObject[$i] + } + } - $actual.Minimum | Should Be $expected - } + $actual.Minimum | Should Be $expected + } - It "Should be able to return a minimum when multiple objects are the minimum" { - $testMinimum = 1,1,2,4 - $actual = $testMinimum | Measure-Object -Minimum - $expected = $testMinimum[0] + It "Should be able to return a minimum when multiple objects are the minimum" { + $testMinimum = 1, 1, 2, 4 + $actual = $testMinimum | Measure-Object -Minimum + $expected = $testMinimum[0] - for ($i=1; $i -lt $testMinimum.length; $i++) - { - if ( $testMinimum[$i] -lt $expected ) - { + for ($i = 1; $i -lt $testMinimum.length; $i++) { + if ( $testMinimum[$i] -lt $expected ) { - $expected = $testMinimum[$i] - } - } + $expected = $testMinimum[$i] + } + } - $actual.Minimum | Should Be $expected - } + $actual.Minimum | Should Be $expected + } - It "Should be able to return a maximum" { - $actual = $testObject | Measure-Object -Maximum - $expected = $testObject[0] + It "Should be able to return a maximum" { + $actual = $testObject | Measure-Object -Maximum + $expected = $testObject[0] - for ($i=1; $i -lt $testObject.length; $i++) - { - if ( $testObject[$i] -gt $expected ) - { + for ($i = 1; $i -lt $testObject.length; $i++) { + if ( $testObject[$i] -gt $expected ) { - $expected = $testObject[$i] - } - } + $expected = $testObject[$i] + } + } - $actual.Maximum | Should Be $expected - } + $actual.Maximum | Should Be $expected + } - It "Should be able to return a maximum when multiple objects are the maximum" { - $testMaximum = 1,3,5,5 - $actual = $testMaximum | Measure-Object -Maximum - $expected = $testMaximum[0] + It "Should be able to return a maximum when multiple objects are the maximum" { + $testMaximum = 1, 3, 5, 5 + $actual = $testMaximum | Measure-Object -Maximum + $expected = $testMaximum[0] - for ($i=1; $i -lt $testMaximum.length; $i++) - { - if ( $testMaximum[$i] -gt $expected ) - { + for ($i = 1; $i -lt $testMaximum.length; $i++) { + if ( $testMaximum[$i] -gt $expected ) { - $expected = $testMaximum[$i] - } - } + $expected = $testMaximum[$i] + } + } - $actual.Maximum | Should Be $expected - } + $actual.Maximum | Should Be $expected + } } Context "String tests" { - $nl = [Environment]::NewLine + $nl = [Environment]::NewLine - $testString = "HAD I the heavens' embroidered cloths,$nl Enwrought with golden and silver light,$nl The blue and the dim and the dark cloths$nl Of night and light and the half light,$nl I would spread the cloths under your feet:$nl But I, being poor, have only my dreams;$nl I have spread my dreams under your feet;$nl Tread softly because you tread on my dreams." + $testString = "HAD I the heavens' embroidered cloths,$nl Enwrought with golden and silver light,$nl The blue and the dim and the dark cloths$nl Of night and light and the half light,$nl I would spread the cloths under your feet:$nl But I, being poor, have only my dreams;$nl I have spread my dreams under your feet;$nl Tread softly because you tread on my dreams." - It "Should be able to count the number of words in a string" { - $expectedLength = $testString.Replace($nl,"").Split().length - $actualLength = $testString | Measure-Object -Word + It "Should be able to count the number of words in a string" { + $expectedLength = $testString.Replace($nl, "").Split().length + $actualLength = $testString | Measure-Object -Word - $actualLength.Words | Should Be $expectedLength - } + $actualLength.Words | Should Be $expectedLength + } - It "Should be able to count the number of characters in a string" { - $expectedLength = $testString.length - $actualLength = $testString | Measure-Object -Character + It "Should be able to count the number of characters in a string" { + $expectedLength = $testString.length + $actualLength = $testString | Measure-Object -Character - $actualLength.Characters | Should Be $expectedLength - } + $actualLength.Characters | Should Be $expectedLength + } - It "Should be able to count the number of lines in a string" { - $expectedLength = $testString.Split($nl, [System.StringSplitOptions]::RemoveEmptyEntries).length - $actualLength = $testString | Measure-Object -Line + It "Should be able to count the number of lines in a string" { + $expectedLength = $testString.Split($nl, [System.StringSplitOptions]::RemoveEmptyEntries).length + $actualLength = $testString | Measure-Object -Line - $actualLength.Lines | Should Be $expectedLength - } + $actualLength.Lines | Should Be $expectedLength + } } } Describe "Measure-Object DRT basic functionality" -Tags "CI" { - BeforeAll { - if(-not ([System.Management.Automation.PSTypeName]'TestMeasureGeneric').Type) - { - Add-Type -TypeDefinition @" + BeforeAll { + if (-not ([System.Management.Automation.PSTypeName]'TestMeasureGeneric').Type) { + Add-Type -TypeDefinition @" [System.Flags] public enum TestMeasureGeneric : uint { @@ -173,10 +172,9 @@ Describe "Measure-Object DRT basic functionality" -Tags "CI" { TestMin = 8 } "@ - } - if(-not ([System.Management.Automation.PSTypeName]'TestMeasureText').Type) - { - Add-Type -TypeDefinition @" + } + if (-not ([System.Management.Automation.PSTypeName]'TestMeasureText').Type) { + Add-Type -TypeDefinition @" [System.Flags] public enum TestMeasureText : uint { @@ -186,123 +184,105 @@ Describe "Measure-Object DRT basic functionality" -Tags "CI" { TestLine = 8 } "@ - } - $employees = [pscustomobject]@{"FirstName"="joseph"; "LastName"="smith"; "YearsInMS"=15}, - [pscustomobject]@{"FirstName"="paul"; "LastName"="smith"; "YearsInMS"=15}, - [pscustomobject]@{"FirstName"="mary jo"; "LastName"="soe"; "YearsInMS"=5}, - [pscustomobject]@{"FirstName"="edmund`todd `n"; "LastName"="bush"; "YearsInMS"=9} - } - - It "Measure-Object with Generic enum value options combination should work"{ + } + $employees = [pscustomobject]@{"FirstName" = "joseph"; "LastName" = "smith"; "YearsInMS" = 15}, + [pscustomobject]@{"FirstName" = "paul"; "LastName" = "smith"; "YearsInMS" = 15}, + [pscustomobject]@{"FirstName" = "mary jo"; "LastName" = "soe"; "YearsInMS" = 5}, + [pscustomobject]@{"FirstName" = "edmund`todd `n"; "LastName" = "bush"; "YearsInMS" = 9} + } + + It "Measure-Object with Generic enum value options combination should work" { $flags = [TestMeasureGeneric]0 - $property = "FirstName" - $testSum = ($flags -band [TestMeasureGeneric]::TestSum) -gt 0 + $property = "FirstName" + $testSum = ($flags -band [TestMeasureGeneric]::TestSum) -gt 0 $testAverage = ($flags -band [TestMeasureGeneric]::TestAverage) -gt 0 $testMax = ($flags -band [TestMeasureGeneric]::TestMax) -gt 0 $testMin = ($flags -band [TestMeasureGeneric]::TestMin) -gt 0 - $result = $employees | Measure-Object -Sum:$testSum -Average:$testAverage -Max:$testMax -Min:$testMin -Prop $property - $result.Count | Should Be 4 - $result.Sum | Should BeNullOrEmpty - $result.Average | Should BeNullOrEmpty - $result.Max | Should BeNullOrEmpty - $result.Min | Should BeNullOrEmpty - for ($i = 1; $i -lt 8 * 2; $i++) - { - $flags = [TestMeasureGeneric]$i - $property = "YearsInMS" - $testSum = ($flags -band [TestMeasureGeneric]::TestSum) -gt 0 - $testAverage = ($flags -band [TestMeasureGeneric]::TestAverage) -gt 0 - $testMax = ($flags -band [TestMeasureGeneric]::TestMax) -gt 0 - $testMin = ($flags -band [TestMeasureGeneric]::TestMin) -gt 0 - $result = $employees | Measure-Object -Sum:$testSum -Average:$testAverage -Max:$testMax -Min:$testMin -Prop $property - $result.Count | Should Be 4 - if($testSum) - { - $result.Sum | Should Be 44 - } - else - { - $result.Sum | Should BeNullOrEmpty - } - - if($testAverage) - { - $result.Average | Should Be 11 - } - else - { - $result.Average | Should BeNullOrEmpty - } - - if($testMax) - { - $result.Maximum | Should Be 15 - } - else - { - $result.Maximum | Should BeNullOrEmpty - } - - if($testMin) - { - $result.Minimum | Should Be 5 - } - else - { - $result.Minimum | Should BeNullOrEmpty - } - } + $result = $employees | Measure-Object -Sum:$testSum -Average:$testAverage -Max:$testMax -Min:$testMin -Prop $property + $result.Count | Should Be 4 + $result.Sum | Should BeNullOrEmpty + $result.Average | Should BeNullOrEmpty + $result.Max | Should BeNullOrEmpty + $result.Min | Should BeNullOrEmpty + for ($i = 1; $i -lt 8 * 2; $i++) { + $flags = [TestMeasureGeneric]$i + $property = "YearsInMS" + $testSum = ($flags -band [TestMeasureGeneric]::TestSum) -gt 0 + $testAverage = ($flags -band [TestMeasureGeneric]::TestAverage) -gt 0 + $testMax = ($flags -band [TestMeasureGeneric]::TestMax) -gt 0 + $testMin = ($flags -band [TestMeasureGeneric]::TestMin) -gt 0 + $result = $employees | Measure-Object -Sum:$testSum -Average:$testAverage -Max:$testMax -Min:$testMin -Prop $property + $result.Count | Should Be 4 + if ($testSum) { + $result.Sum | Should Be 44 + } + else { + $result.Sum | Should BeNullOrEmpty + } + + if ($testAverage) { + $result.Average | Should Be 11 + } + else { + $result.Average | Should BeNullOrEmpty + } + + if ($testMax) { + $result.Maximum | Should Be 15 + } + else { + $result.Maximum | Should BeNullOrEmpty + } + + if ($testMin) { + $result.Minimum | Should Be 5 + } + else { + $result.Minimum | Should BeNullOrEmpty + } + } } - It "Measure-Object with Text combination should work"{ - for ($i = 1; $i -lt 8 * 2; $i++) - { - $flags = [TestMeasureText]$i - $property = "FirstName" - $testIgnoreWS = ($flags -band [TestMeasureText]::TestIgnoreWS) -gt 0 - $testCharacter = ($flags -band [TestMeasureText]::TestCharacter) -gt 0 - $testWord = ($flags -band [TestMeasureText]::TestWord) -gt 0 - $testLine = ($flags -band [TestMeasureText]::TestLine) -gt 0 - $result = $employees | Measure-Object -IgnoreWhiteSpace:$testIgnoreWS -Character:$testCharacter -Word:$testWord -Line:$testLine -Prop $property - - if($testCharacter) - { - if($testIgnoreWS) - { - $result.Characters | Should Be 25 - } - else - { - $result.Characters | Should Be 29 - } - } - else - { - $result.Characters | Should BeNullOrEmpty - } - - if($testWord) - { - $result.Words | Should Be 6 - } - else - { - $result.Words | Should BeNullOrEmpty - } - - if($testLine) - { - $result.Lines | Should Be 4 - } - else - { - $result.Lines | Should BeNullOrEmpty - } - } + It "Measure-Object with Text combination should work" { + for ($i = 1; $i -lt 8 * 2; $i++) { + $flags = [TestMeasureText]$i + $property = "FirstName" + $testIgnoreWS = ($flags -band [TestMeasureText]::TestIgnoreWS) -gt 0 + $testCharacter = ($flags -band [TestMeasureText]::TestCharacter) -gt 0 + $testWord = ($flags -band [TestMeasureText]::TestWord) -gt 0 + $testLine = ($flags -band [TestMeasureText]::TestLine) -gt 0 + $result = $employees | Measure-Object -IgnoreWhiteSpace:$testIgnoreWS -Character:$testCharacter -Word:$testWord -Line:$testLine -Prop $property + + if ($testCharacter) { + if ($testIgnoreWS) { + $result.Characters | Should Be 25 + } + else { + $result.Characters | Should Be 29 + } + } + else { + $result.Characters | Should BeNullOrEmpty + } + + if ($testWord) { + $result.Words | Should Be 6 + } + else { + $result.Words | Should BeNullOrEmpty + } + + if ($testLine) { + $result.Lines | Should Be 4 + } + else { + $result.Lines | Should BeNullOrEmpty + } + } } - It "Measure-Object with multiple lines should work"{ - $result = "123`n4"|measure-object -line - $result.Lines | Should Be 2 - } + It "Measure-Object with multiple lines should work" { + $result = "123`n4"|measure-object -line + $result.Lines | Should Be 2 + } } From 06dfb2f5be0ebf5a163200cdb53683a4f01329b9 Mon Sep 17 00:00:00 2001 From: dfinke Date: Mon, 2 Oct 2017 16:48:05 -0400 Subject: [PATCH 2/6] Use A*A instead of Math.Pow. Throw if -Average not specified and fixed comments --- .../commands/utility/Measure-Object.cs | 18 ++++++++++++------ .../Measure-Object.Tests.ps1 | 7 +++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs index ba9e57384f2..c02f741f49d 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -75,7 +75,7 @@ public GenericMeasureInfo() /// /// - /// The StdDeviation of property values + /// The Standard Deviation of property values /// /// public double? StdDeviation { get; set; } @@ -139,7 +139,7 @@ public GenericObjectMeasureInfo() /// /// - /// The StdDeviation of property values + /// The Standard Deviation of property values /// /// public double? StdDeviation { get; set; } @@ -282,7 +282,7 @@ public MeasureObjectCommand() #endregion Common parameters in both sets /// - /// Set to true is StdDeviation is to be returned + /// Set to true if Standard Deviation is to be returned /// /// [Parameter(ParameterSetName = GenericParameterSet)] @@ -842,16 +842,22 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene if (_measureAverage && stat.count > 0) average = stat.sum / stat.count; + if(_measureStdDeviation && !_measureAverage) { + var message = "StdDeviation was requested and requires the average to be calculated, please add the -Average switch"; + throw new ArgumentException(message); + } + if (_measureStdDeviation && _measureAverage && stat.count > 0) { - var popdev = 0.0; + var sumOfDerivation = 0.0; foreach (double n in stat.stdDeviationNumbers) { - popdev += Math.Pow((n - (double)average), 2); + var m = n - (double)average; + sumOfDerivation += m * m; } - stdDeviation = Math.Round(Math.Sqrt(popdev / (stat.stdDeviationNumbers.Count - 1)), 4); + stdDeviation = Math.Round(Math.Sqrt(sumOfDerivation / (stat.stdDeviationNumbers.Count - 1)), 4); } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 index 4e52ecc5174..73d8ae8182d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 @@ -13,14 +13,13 @@ Describe "Measure-Object" -Tags "CI" { $($testObject | Measure-Object).Count | Should Be $testObject.Length } - It "Should calculate Std Deviation" { + It "Should calculate Standard Deviation" { $actual = ($testObject | Measure-Object -Average -StdDeviation) $actual.StdDeviation | Should Be 1.5275 } - It "Should not calculate Std Deviation if -Average not specified" { - $actual = ($testObject | Measure-Object -StdDeviation) - $actual.StdDeviation | Should BeNullOrEmpty + It "Should throw if Standard Deviation requested and -Average not specified" { + {$testObject | Measure-Object -StdDeviation} | Should Throw } It "Should be able to count using the Property switch" { From eb541c553b9daab7f5fb985bb65c84522ad7c09b Mon Sep 17 00:00:00 2001 From: dfinke Date: Mon, 2 Oct 2017 19:32:36 -0400 Subject: [PATCH 3/6] Added message to the rex file --- .../commands/utility/Measure-Object.cs | 10 ++++++++-- .../resources/MeasureObjectStrings.resx | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs index c02f741f49d..06d47b14c40 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -843,8 +843,14 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene average = stat.sum / stat.count; if(_measureStdDeviation && !_measureAverage) { - var message = "StdDeviation was requested and requires the average to be calculated, please add the -Average switch"; - throw new ArgumentException(message); + ErrorRecord errorRecord = new ErrorRecord( + PSTraceSource.NewArgumentException("Average"), + "AverageSwitchNotSet", + ErrorCategory.InvalidArgument, + null); + + errorRecord.ErrorDetails = new ErrorDetails(this, "MeasureObjectStrings", "AverageSwitchNotSet", "Average"); + WriteError(errorRecord); } if (_measureStdDeviation && _measureAverage && stat.count > 0) diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx index 8211114c335..c5c624771ac 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx @@ -126,4 +126,7 @@ Input object "{0}" is not numeric. + + StdDeviation was requested and requires the average to be calculated, please add the -Average switch. + From ca4b539ea1dea2dac966da19eac5e29ae1fc3286 Mon Sep 17 00:00:00 2001 From: dfinke Date: Tue, 3 Oct 2017 13:53:11 -0400 Subject: [PATCH 4/6] Set Average true if StdDeviation is set --- .../commands/utility/Measure-Object.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs index 06d47b14c40..2b10d108e11 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Measure-Object.cs @@ -295,6 +295,8 @@ public SwitchParameter StdDeviation set { _measureStdDeviation = value; + if(value == true) + _measureAverage = true; } } From 806f3a7b510e4d502432adbaf2f7f1402d5ff935 Mon Sep 17 00:00:00 2001 From: dfinke Date: Tue, 3 Oct 2017 13:53:19 -0400 Subject: [PATCH 5/6] Update message --- .../resources/MeasureObjectStrings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx b/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx index c5c624771ac..bccbd5db10c 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx +++ b/src/Microsoft.PowerShell.Commands.Utility/resources/MeasureObjectStrings.resx @@ -127,6 +127,6 @@ Input object "{0}" is not numeric. - StdDeviation was requested and requires the average to be calculated, please add the -Average switch. + StdDeviation was requested and requires the average to be calculated, however '-Average' was set to $false. From c95b829a983052be35cfb16fa32e0eb6f03eaa4d Mon Sep 17 00:00:00 2001 From: dfinke Date: Tue, 3 Oct 2017 13:53:26 -0400 Subject: [PATCH 6/6] Update tests --- .../Measure-Object.Tests.ps1 | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 index 73d8ae8182d..d708e0bdeaf 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Measure-Object.Tests.ps1 @@ -13,13 +13,25 @@ Describe "Measure-Object" -Tags "CI" { $($testObject | Measure-Object).Count | Should Be $testObject.Length } - It "Should calculate Standard Deviation" { - $actual = ($testObject | Measure-Object -Average -StdDeviation) + It "Should calculate Standard Deviation" { + $actual = ($testObject | Measure-Object -Average -StdDeviation) $actual.StdDeviation | Should Be 1.5275 } - It "Should throw if Standard Deviation requested and -Average not specified" { - {$testObject | Measure-Object -StdDeviation} | Should Throw + It "Should throw if Standard Deviation with -Average not specified" { + #{$testObject | Measure-Object -StdDeviation} | Should Throw + $actual = $testObject | Measure-Object -StdDeviation + $actual.StdDeviation | Should Be 1.5275 + } + + It 'Should throw if Standard Deviation requested and -Average:$false' { + try { + $Error.Clear() + $testObject | Measure-Object -StdDeviation -Average:$false -ErrorAction Stop + } + catch { + $Error.Count | should be 1 + } } It "Should be able to count using the Property switch" {