Skip to content

Commit 1be0594

Browse files
sethvsadityapatwardhan
authored andcommitted
Improve code coverage in Export-Csv.Tests.ps1. (#6795)
* Improve code coverage in Export-Csv.Tests.ps1. * Change test logic.
1 parent c1026b3 commit 1be0594

1 file changed

Lines changed: 153 additions & 46 deletions

File tree

test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1

Lines changed: 153 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,36 @@ Describe "Export-Csv" -Tags "CI" {
44
BeforeAll {
55
$testObject = @("test","object","array")
66
$testCsv = Join-Path -Path $TestDrive -ChildPath "output.csv"
7+
$newLine = [environment]::NewLine
8+
$P1 = [pscustomobject]@{"P1" = "first"}
9+
$P2 = [pscustomobject]@{"P2" = "second"}
10+
$P11 = [pscustomobject]@{"P1" = "eleventh"}
711
}
812

913
AfterEach {
10-
Remove-Item $testCsv -Force -ErrorAction SilentlyContinue
14+
Remove-Item -Path $testCsv -Force -ErrorAction SilentlyContinue
1115
}
1216

1317
It "Should be able to be called without error" {
14-
{ $testObject | Export-Csv $testCsv -ErrorAction Stop } | Should -Not -Throw
18+
{ $testObject | Export-Csv -Path $testCsv -ErrorAction Stop } | Should -Not -Throw
1519
}
1620

1721
It "Should throw if an output file isn't specified" {
18-
{ $testObject | Export-Csv -ErrorAction Stop } | ShouldBeErrorId "CannotSpecifyPathAndLiteralPath,Microsoft.PowerShell.Commands.ExportCsvCommand"
22+
{ $testObject | Export-Csv -ErrorAction Stop } | Should -Throw -ErrorId "CannotSpecifyPathAndLiteralPath,Microsoft.PowerShell.Commands.ExportCsvCommand"
1923
}
2024

2125
It "Should be a string when exporting via pipe" {
22-
$testObject | Export-Csv $testCsv -IncludeTypeInformation
23-
24-
$piped = Get-Content $testCsv
26+
$testObject | Export-Csv -Path $testCsv -IncludeTypeInformation
27+
$results = Get-Content -Path $testCsv
2528

26-
$piped[0] | Should -BeExactly "#TYPE System.String"
29+
$results[0] | Should -BeExactly "#TYPE System.String"
2730
}
2831

2932
It "Should be an object when exporting via the inputObject switch" {
3033
Export-Csv -InputObject $testObject -Path $testCsv -IncludeTypeInformation
34+
$results = Get-Content -Path $testCsv
3135

32-
$switch = Get-Content $testCsv
33-
34-
$switch[0] | Should -BeExactly "#TYPE System.Object[]"
36+
$results[0] | Should -BeExactly "#TYPE System.Object[]"
3537
}
3638

3739
It "Should output a csv file containing a string of all the lengths of each element when piped input is used" {
@@ -43,81 +45,186 @@ Describe "Export-Csv" -Tags "CI" {
4345
$expected = @("#TYPE System.String", "`"Length`"", $first , $second, $third)
4446

4547
for ($i = 0; $i -lt $expected.Count; $i++) {
46-
$(Get-Content $testCsv)[$i] | Should -Be $expected[$i]
48+
$(Get-Content -Path $testCsv)[$i] | Should -Be $expected[$i]
4749
}
4850
}
4951

5052
It "Does not include type information by default" {
5153
$testObject | Export-Csv -Path $testCsv
54+
$results = Get-Content -Path $testCsv
5255

53-
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("System.String"))
54-
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
56+
$results[0] | Should -Not -Match ([regex]::Escape("System.String"))
57+
$results[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
5558
}
5659

5760
It "Does not include type information with -NoTypeInformation" {
5861
$testObject | Export-Csv -Path $testCsv -NoTypeInformation
62+
$results = Get-Content -Path $testCsv
5963

60-
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("System.String"))
61-
$(Get-Content $testCsv)[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
64+
$results[0] | Should -Not -Match ([regex]::Escape("System.String"))
65+
$results[0] | Should -Not -Match ([regex]::Escape("#TYPE"))
6266
}
6367

6468
It "Includes type information when -IncludeTypeInformation is supplied" {
6569
$testObject | Export-Csv -Path $testCsv -IncludeTypeInformation
70+
$results = Get-Content -Path $testCsv
6671

67-
$(Get-Content $testCsv)[0] | Should -BeExactly "#TYPE System.String"
72+
$results[0] | Should -BeExactly "#TYPE System.String"
6873
}
6974

7075
It "Does not support -IncludeTypeInformation and -NoTypeInformation at the same time" {
71-
{ $testObject | Export-Csv -Path $testCsv -IncludeTypeInformation -NoTypeInformation } |
72-
ShouldBeErrorId "CannotSpecifyIncludeTypeInformationAndNoTypeInformation,Microsoft.PowerShell.Commands.ExportCsvCommand"
76+
{ $testObject | Export-Csv -Path $testCsv -IncludeTypeInformation -NoTypeInformation } | Should -Throw -ErrorId "CannotSpecifyIncludeTypeInformationAndNoTypeInformation,Microsoft.PowerShell.Commands.ExportCsvCommand"
7377
}
74-
}
7578

76-
Describe "Export-Csv DRT Unit Tests" -Tags "CI" {
77-
BeforeAll {
78-
$filePath = Join-Path $TestDrive -ChildPath "test.csv"
79-
$newLine = [environment]::NewLine
79+
It "Should support -LiteralPath parameter" {
80+
$testObject | Export-Csv -LiteralPath $testCsv
81+
$results = Import-Csv -Path $testCsv
82+
83+
$results | Should -HaveCount 3
84+
}
85+
86+
It "Should overwrite file without -NoClobber parameter" {
87+
$P1 | Export-Csv -Path $testCsv
88+
$P2 | Export-Csv -Path $testCsv
89+
$results = Import-Csv -Path $testCsv
90+
91+
$results.P2 | Should -BeExactly "second"
92+
}
93+
94+
It "Should not overwrite file with -NoClobber parameter" {
95+
$P1 | Export-Csv -Path $testCsv
96+
{ $P2 | Export-Csv -Path $testCsv -NoClobber} | Should -Throw -ErrorId "NoClobber,Microsoft.PowerShell.Commands.ExportCsvCommand"
97+
$results = Import-Csv -Path $testCsv
98+
99+
$results.P1 | Should -BeExactly "first"
100+
}
101+
102+
It "Should not overwrite read-only file without -Force parameter" {
103+
$P1 | Export-Csv -Path $testCsv
104+
Set-ItemProperty -Path $testCsv -Name IsReadOnly -Value $true
105+
106+
{ $P2 | Export-Csv -Path $testCsv } | Should -Throw -ErrorId "FileOpenFailure,Microsoft.PowerShell.Commands.ExportCsvCommand"
107+
$results = Import-Csv -Path $testCsv
108+
109+
$results.P1 | Should -BeExactly "first"
110+
}
111+
112+
It "Should overwrite read-only file with -Force parameter" {
113+
$P1 | Export-Csv -Path $testCsv
114+
Set-ItemProperty -Path $testCsv -Name IsReadOnly -Value $true
115+
116+
$P2 | Export-Csv -Path $testCsv -Force
117+
$results = Import-Csv -Path $testCsv
118+
119+
$results.P2 | Should -BeExactly "second"
120+
}
121+
122+
It "Should not export to file if -WhatIf parameter specified" {
123+
$P1 | Export-Csv -Path $testCsv -WhatIf
124+
$testCsv | Should -Not -Exist
125+
}
126+
127+
It "Should append to file if -Append parameter specified" {
128+
$P1 | Export-Csv -Path $testCsv
129+
$P11 | Export-Csv -Path $testCsv -Append
130+
$results = Import-Csv -Path $testCsv
131+
132+
$results[0].P1 | Should -BeExactly "first"
133+
$results[1].P1 | Should -BeExactly "eleventh"
134+
}
135+
136+
# This test is not a duplicate of the previous one, since it covers a separate branch in code.
137+
It "Should append to empty file if -Append parameter specified" {
138+
New-Item -Path $testCsv -ItemType File | Out-Null
139+
140+
$P11 | Export-Csv -Path $testCsv -Append
141+
$results = Import-Csv -Path $testCsv
142+
143+
$results[0].P1 | Should -BeExactly "eleventh"
144+
}
145+
146+
It "Should throw when appended property does not exist in existing .csv file" {
147+
$P1 | Export-Csv -Path $testCsv
148+
{ $P2 | Export-Csv -Path $testCsv -Append -ErrorAction Stop } | Should -Throw -ErrorId "CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand"
149+
$results = Import-Csv -Path $testCsv
150+
151+
$results[0].P1 | Should -BeExactly "first"
152+
}
153+
154+
It "Should append existing properties, add missing properties with empty value, and skip extra properties" {
155+
$object1 = [PSCustomObject]@{first = 1; second = 2}
156+
$object2 = [PSCustomObject]@{first = 11; third = 13}
157+
158+
$object1 | Export-Csv -Path $testCsv
159+
$object2 | Export-Csv -Path $testCsv -Append -Force
160+
161+
$results = Import-Csv -Path $testCsv
162+
163+
$results[0].first | Should -BeExactly "1"
164+
$results[0].second | Should -BeExactly "2"
165+
$results[1].first | Should -BeExactly "11"
166+
$results[1].second | Should -BeNullOrEmpty
167+
$results[1].PSObject.properties.Name | Should -Not -Contain 'third'
168+
}
169+
170+
It "First line should be #TYPE if -IncludeTypeInformation used and pstypenames object property is empty" {
171+
$object = [PSCustomObject]@{first = 1}
172+
$pstypenames = $object.pstypenames | ForEach-Object -Process {$_}
173+
$pstypenames | ForEach-Object -Process {$object.pstypenames.Remove($_)}
174+
$object | Export-Csv -Path $testCsv -IncludeTypeInformation
175+
$content = Get-Content -Path $testCsv
176+
177+
$content[0] | Should -BeExactly '#TYPE'
178+
}
179+
180+
# If type starts with CSV: Export-CSV should remove it. This would happen when you export
181+
# an imported object. Import-Csv adds CSV: prefix to the type.
182+
It "Should remove 'CSV:' from the type name" {
183+
$object = [PSCustomObject]@{first = 1}
184+
$object.pstypenames.Insert(0, "CSV:TheType")
185+
$object | Export-Csv -Path $testCsv -IncludeTypeInformation
186+
$result = Get-Content -Path $testCsv
187+
188+
$result[0] | Should -BeExactly "#TYPE TheType"
189+
}
190+
191+
It "Should escape double quote with another double quote" {
192+
$object = [PSCustomObject]@{first = 'Double quote " in the middle.'}
193+
$object | Export-Csv -Path $testCsv
194+
$result = Get-Content -Path $testCsv
195+
196+
$result[1] | Should -BeExactly '"Double quote "" in the middle."'
80197
}
81198

82199
It "Test basic function works well" {
83-
$input = [pscustomobject]@{ "P1" = "V11"; "P2" = "V12"; "P3" = "V13" }
84-
$input | Export-Csv -Path $filePath -NoTypeInformation
85-
$results = Import-Csv $filePath
200+
$in = [pscustomobject]@{ "P1" = "V11"; "P2" = "V12"; "P3" = "V13" }
201+
$in | Export-Csv -Path $testCsv -NoTypeInformation
202+
$results = Import-Csv -Path $testCsv
203+
86204
$results.P1 | Should -BeExactly "V11"
87205
$results.P2 | Should -BeExactly "V12"
88206
$results.P3 | Should -BeExactly "V13"
89207
}
90208

91209
It "Test if it works with special character" {
92210
$v3 = "abc" + $newLine + "foo"
93-
$input = [pscustomobject]@{ "P1" = " "; "P2" = "abc,foo"; "P3" = $v3}
94-
$input | Export-Csv -Path $filePath -NoTypeInformation
95-
$results = Import-Csv $filePath
211+
$in = [pscustomobject]@{ "P1" = " "; "P2" = "abc,foo"; "P3" = $v3}
212+
$in | Export-Csv -Path $testCsv -NoTypeInformation
213+
$results = Import-Csv -Path $testCsv
214+
96215
$results.P1 | Should -BeExactly " "
97216
$results.P2 | Should -BeExactly "abc,foo"
98-
$results.P3 | Should -Be $v3
99-
}
100-
101-
It "Test force switch works well" {
102-
$input = [pscustomobject]@{ "P1" = "first" }
103-
$input | Export-Csv -Path $filePath
104-
105-
$input = [pscustomobject]@{ "P2" = "second" }
106-
$input | Export-Csv -Path $filePath -Force
107-
$results = Import-Csv $filePath
108-
109-
$results.P2 | Should -BeExactly "second"
110-
$property = $results | Get-Member | Where-Object { $_.MemberType -eq "NoteProperty" } | ForEach-Object { $_.Name }
111-
$property | Should -Not -Be P1
217+
$results.P3 | Should -BeExactly $v3
112218
}
113219

114220
It "Test export-csv with a useculture flag" {
115-
$outputFilesDir = Join-Path $TestDrive -ChildPath "Monad"
116-
$fileToGenerate = Join-Path $outputFilesDir -ChildPath "CSVTests.csv"
221+
$outputFilesDir = Join-Path -Path $TestDrive -ChildPath "Monad"
222+
$fileToGenerate = Join-Path -Path $outputFilesDir -ChildPath "CSVTests.csv"
117223
$delimiter = (Get-Culture).TextInfo.ListSeparator
118224
New-Item -Path $outputFilesDir -ItemType Directory -Force
119-
Get-Item -Path $outputFilesDir| Export-Csv -Path $fileToGenerate -UseCulture -NoTypeInformation
225+
Get-Item -Path $outputFilesDir | Export-Csv -Path $fileToGenerate -UseCulture -NoTypeInformation
120226
$contents = Get-Content -Path $fileToGenerate
227+
121228
$contents.Count | Should -Be 2
122229
$contents[0].Contains($delimiter) | Should -BeTrue
123230
$contents[1].Contains($delimiter) | Should -BeTrue

0 commit comments

Comments
 (0)