Tests/Syntax.Tests.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
$here = Split-Path -Parent $MyInvocation.MyCommand.Path | Split-Path -Parent | Join-Path -ChildPath Functions

function Measure-String
{
[cmdletbinding()]
Param(
    [Parameter(ValueFromPipeline)]
    [string[]]$InputObject
    ,
    [string]$SearchString
    ,
    [switch]$SkipComments
)

Begin
{
    $count = 0
    $inCommentSection = $false
    $PreviousStr = ""
}

Process
{   
    if ($SearchString.Length -gt 1)
    {
        foreach ($str in $InputObject)
        {
            if($SkipComments.IsPresent)
            {
                if ($Str.Contains("<#"))
                {
                    $inCommentSection = $true
                    Write-Verbose "in commentssection"
                }
                
                $trimmed = $str.TrimStart()
                if ($PreviousStr.Contains("#>"))
                {
                    Write-Verbose "end of commentssection"
                    $inCommentSection = $false
                }

                $PreviousStr = $str

                if ($trimmed.StartsWith("#") -or $inCommentSection -eq $true)
                {
                    continue
                }
            }
            
            Write-Verbose "Searching [$str] for [$SearchString]"
            $stringlength = $str.length
            $searchTextLength = $SearchString.Length
            $replaced = $str.ToLower().Replace($SearchString.ToLower(),"")
            $foundCount = ($stringlength - $replaced.length) / $searchTextLength
            $count += $foundCount            
        }
    }
    else
    {
        foreach ($str in $InputObject)
        {
            
            if($SkipComments.IsPresent)
            {
                if ($Str.Contains("<#"))
                {
                    $inCommentSection = $true
                    Write-Verbose "Start of comment ssection"
                }
                
                $trimmed = $str.TrimStart()
                if ($PreviousStr.Contains("#>"))
                {
                    Write-Verbose "End of comment ssection"
                    $inCommentSection = $false
                }

                $PreviousStr = $str

                if ($trimmed.StartsWith("#") -or $inCommentSection -eq $true)
                {
                    Write-Verbose "Skipping searching [$str] for [$SearchString]"
                    continue
                }
            }

            Write-Verbose "Searching [$str] for [$SearchString]"
            foreach ($char in $str.ToCharArray())
            {
                if ($char -eq $SearchString)
                {
                    $count++
                }
            }
        }
    }    
}
END
{
    [Pscustomobject]@{
        SearchString = $SearchString
        Count = $count
    }    
}
}


Describe "Powershell Syntax Tests" {
    $files = Get-ChildItem -Path $here | Where-Object Name -notlike "*.Tests.ps1"
    #$files = Get-ChildItem -Path $here | Where-Object Name -eq "New-DynamicParam.ps1"

    foreach ($file in $files)
    {
        $content = Get-Content -Path $file.fullname -Encoding UTF8 -ReadCount 0 -Raw
        $fileName = $file.FileName
        $name = $file.BaseName.Replace(".Tests","")
        $functionNameCount = Measure-String -InputObject $content -SearchString $name | Select-Object -ExpandProperty Count
        $quotes = Measure-String -InputObject $content -SearchString "'" -SkipComments | Select-Object -ExpandProperty Count
        $doubleQuotes = Measure-String -InputObject $content -SearchString '"' | Select-Object -ExpandProperty Count
        $doubleDollar = Measure-String -InputObject $content -SearchString '$$' | Select-Object -ExpandProperty Count
        $ifFormatting = Measure-String -InputObject $content -SearchString "if(" | Select-Object -ExpandProperty Count
        $foreachFormatting = Measure-String -InputObject $content -SearchString "foreach(" | Select-Object -ExpandProperty Count
        $cmdletbindingCount = Measure-String -InputObject $content -SearchString "cmdletbinding(" | Select-Object -ExpandProperty Count
        $aliasExceptions = @("foreach","h","r","type")
        $aliases = Get-Alias | Where Name -notin $aliasExceptions | Select-Object -ExpandProperty Name
        $fixmeCount = Measure-String -InputObject $content -SearchString "FIXme" | Select-Object -ExpandProperty Count

        foreach ($alias in $aliases)
        {
            $aliasCount = (Measure-String -InputObject $content -SearchString " $alias " -SkipComments).Count
            if ($aliasCount -ne 0)
            {
                It "[$name] should not use Alias [$alias]" {
                    $aliasCount | Should Be 0
                }
            }            
        }

        It "[$name] should not be null" {
            $content | Should Not Be $null
        }

        It "[$name] should match function Name" {
            $functionNameCount | Should Not Be 0
        }

        It "[$name] Quotes count should be even" {
            $quotes % 2 | Should Be 0
        }

        It "[$name] doubleQuotes count should be even" {
            $doubleQuotes % 2 | Should Be 0
        }

        It "[$name] double dollar count should be 0" {
            $doubleDollar | Should Be 0
        }

        It "[$name] should not have if() formatting" {
            $ifFormatting | Should Be 0
        }

        It "[$name] should not have foreach() formatting" {
            $foreachFormatting | Should Be 0
        }

        It "[$name] should have cmdletbinding specified" {
            $cmdletbindingCount | should BeGreaterThan 0
        }        

        It "[$name] should not have [FIXme] comment" {
            $fixmeCount | should be 0
        }
        
        $aliasCount = 0        
    }    
}