NSpec icon indicating copy to clipboard operation
NSpec copied to clipboard

Continuous Runner similar to karma

Open dhilgarth opened this issue 7 years ago • 10 comments

I have created a simple continuous runner similar to karma: Whenever the test assembly is recompiled, the tests are re-executed. If the HTML formatter is specified, the runner opens the HTML file in a web browser and automatically reloads it on a new build.

Is this interesting to the community? I have more ideas for the runner like making the contexts and specs clickable to navigate to the source code in VS.

dhilgarth avatar Jan 29 '18 08:01 dhilgarth

The repo: https://github.com/dhilgarth/NSpec.ContinuousRunner/tree/develop

dhilgarth avatar Jan 29 '18 08:01 dhilgarth

I'd say @amirrajan would like that, but let's wait for his answer too

BrainCrumbz avatar Jan 29 '18 10:01 BrainCrumbz

Here's what I've used for the past few years. Basically this detects changes and then fires of rake scripts:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace SyncDeploy
{
    class Program
    {
        static string path = null; 
        static FileSystemWatcher watcher;
        static string[] fileBlackList = new []
        {
            "#",
            "g.cs",
            "0.cs",
            "g.i.cs"
        };
		    static string[] fileExtensionsWhiteList = new string[]
        {
          ".cs",
          ".coffee",
          ".rb",
          ".html",
          ".cshtml",
          ".js",
          ".css",
          ".fs",
          ".bat"
        };
        static void Main(string[] args)
        {
            path = Directory.GetCurrentDirectory();
            watcher = new FileSystemWatcher(path, "*.*");
            watcher.IncludeSubdirectories = true;
            watcher.EnableRaisingEvents = true;
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            watcher.Changed += new FileSystemEventHandler(watcher_Changed);
            watcher.Created += new FileSystemEventHandler(watcher_Changed);
            watcher.Renamed += watcher_Renamed;
            Console.WriteLine("Watching for changes to the following file types: " + string.Join(", ", fileExtensionsWhiteList));
            Console.WriteLine("Watching " + path + " for changes, press Enter to stop...");
            Shell("tutorial");
            Console.ReadLine();
        }

        static void Shell(params string[] args)
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo("ruby", ".watch " + string.Join(" ", args));
            processStartInfo.UseShellExecute = false;
            processStartInfo.ErrorDialog = false;
            processStartInfo.RedirectStandardError = true;
            processStartInfo.RedirectStandardInput = true;
            processStartInfo.RedirectStandardOutput = true;
            Process process = new Process();
            process.EnableRaisingEvents = true;
            process.StartInfo = processStartInfo;
            process.OutputDataReceived += (sender, args1) => System.Console.WriteLine(args1.Data);
            process.ErrorDataReceived += (sender, args2) => System.Console.WriteLine(args2.Data);

            bool processStarted = process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            process.WaitForExit();
            System.Console.WriteLine("---");
        }

        static void watcher_Renamed(object source, RenamedEventArgs e)
        {
            CallWatcher(e.FullPath);
        }

        static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            CallWatcher(e.FullPath);
        }

        static void CallWatcher(string path)
        {
            foreach(var p in fileBlackList)
            {
                if(path.Contains(p)) return;
            }

            if (fileExtensionsWhiteList.Contains(Path.GetExtension(path)) && System.IO.File.Exists(path))
            {
                watcher.EnableRaisingEvents = false;
                var relativeFile = path.Replace(Directory.GetCurrentDirectory(), "");
                System.Console.WriteLine("Changed: " + relativeFile);
                Shell("file_changed", relativeFile);
                watcher.EnableRaisingEvents = true;
            }
        }
    }
}

amirrajan avatar Jan 30 '18 22:01 amirrajan

Aside: I'm a glutton for low-fi solutions. CLI and terminal all the things.

With regards to running a context by clicking, I'd (personally), prefer some file watcher keep track of how a file has changed and execute "applicable" tests as needed (maybe parsing out a file using Roslyn).

amirrajan avatar Jan 30 '18 22:01 amirrajan

@dhilgarth - this looks very cool! Going to set it up. Wondering if you had plans to only rerun the tests that were changed somehow (I believe SpecWatchr did this?)

johnhamm avatar Feb 01 '18 14:02 johnhamm

@johnhamm no such plans currently as this is really not that trivial. You wouldn't just need to monitor the tests but also the code they test. This is something that NCrunch does really nice, but I don't see myself having the time to implement something like that

dhilgarth avatar Feb 01 '18 14:02 dhilgarth

Nice job though! I particularly like the HTMLSpecFormatter in action. I tried running it inside Visual Studio in the "Web Browser" window so I could embed it like my Test Explorer, but it doesn't seem to work when viewed this way. That's minor though as I just have it running on a second monitor.

johnhamm avatar Feb 01 '18 15:02 johnhamm

Does anyone know if nspec works with NCrunch? I want to try that out.

johnhamm avatar Feb 01 '18 15:02 johnhamm

No, it doesn't work and you already found the respective user voice entry.

dhilgarth avatar Feb 01 '18 19:02 dhilgarth

Regarding the embedding and other features / issues: Please don't hesitate to open issues in the repository.

dhilgarth avatar Feb 01 '18 19:02 dhilgarth