This script will watch a source directory for changes, just *.cs files in this case and then execute a script when a change is detected. This handles the issue of the change event being triggered twice for one change. I’m just calling my default Psake script, but you can put any build/test script call in place of it.

function watch-folder {
    param([string]$path, [string]$filter = "*.*", $command)
    get-eventsubscriber -force | unregister-event -force
    $global:lastGen = [datetime]::Now
    $expandedPath = convert-path $path
    write-host "Watching" $expandedPath\$filter
    $fileSystemWatcher = new-object System.IO.FileSystemWatcher
    $fileSystemWatcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite
    $fileSystemWatcher.Path = $expandedPath
    $fileSystemWatcher.Filter = $filter
    $fileSystemWatcher.IncludeSubdirectories = $true
    $action = {
        $timeGenerated = $event.TimeGenerated

        if ($timeGenerated - $global:lastGen -gt (new-timespan -sec 1)) {
            write-host ***************************************** -foreground Green
            write-host $eventArgs.FullPath -foreground Green
            write-host $eventArgs.ChangeType at $event.TimeGenerated -foreground Green
            write-host TESTING $event.MessageData -foreground Green
            $result = & $event.MessageData | out-string -stream
            if ($LastExitCode -gt 0) {
                $result | select-object -last 70 | out-host
                write-host FAILED -foreground Red
                write-host ***************************************** -foreground Red
            }
            else {
                write-host SUCCESS -foreground Green
                write-host ***************************************** -foreground Green
            }
        }

        $global:lastGen = $timeGenerated
    }
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Created -SourceIdentifier ThisFileWatcher -Action $action -MessageData $command)
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Changed -SourceIdentifier ThisFileWatcherA -Action $action -MessageData $command)
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Deleted -SourceIdentifier ThisFileWatcherB -Action $action -MessageData $command)
}

watch-folder ".\src" "*.cs" {
  psake
}

wait-event "ctrl-c"

Thanks to this post PowerShell, events and file watcher.