Skip to content

Instantly share code, notes, and snippets.

@JulianBirch
Created July 6, 2010 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JulianBirch/465677 to your computer and use it in GitHub Desktop.
Save JulianBirch/465677 to your computer and use it in GitHub Desktop.
RSpecRunner.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using IronRuby.Builtins;
using IronRuby.Runtime;
using Microsoft.Scripting.Hosting;
namespace ColourCoding
{
// NOTE That you'll need to have done the follow
// $env:HTTP_PROXY = "http://10.132.72.11:8080"
// igem install uuidtools
// igem install caricature
// igem install rspec
// igem install gherkin
// igem install cucumber
public class RSpecRunner
{
private readonly string _ironRubyLocation;
private readonly string _specFolder;
private readonly IEnumerable<string> _paths;
public static void Run(string ironRubyLocation) {
var runner = new RSpecRunner(ironRubyLocation);
// runner.RunCucumber();
runner.RunRSpec();
}
public RSpecRunner(string ironRubyLocation)
: this(ironRubyLocation, DefaultSpecFolder(), new[] { GetExecutingDirectory() })
{
}
public RSpecRunner(string ironRubyLocation,
string specFolder,
IEnumerable<string> paths)
{
_ironRubyLocation = ironRubyLocation;
_specFolder = specFolder;
_paths = paths;
AddFolderLoadPath(GherkinAssemblyFolder());
}
IEnumerable<string> RubyPaths()
{
return new[] { @"lib\ironruby", @"lib\ruby\1.8", @"Lib\ruby\site_ruby\1.8" }
.Select(x => Path.Combine(_ironRubyLocation, x));
}
private static string DefaultSpecFolder() {
var root = Path.GetDirectoryName(Path.GetDirectoryName(GetExecutingDirectory()));
return Path.Combine(root, "Spec");
}
IEnumerable<string> RSpecFiles(string directory)
{
return Directory.GetFiles(directory, "*_spec.rb")
.Union(Directory.GetDirectories(directory).SelectMany(RSpecFiles));
}
public void RunRSpec() {
var htmlOutput = Path.GetTempFileName() + ".html";
var args = RSpecFiles(_specFolder).Union(
new string[] { "--loadby", "mtime", "--format", "html" }
).ToList();
ScriptEngine engine = GetEngine();
engine.Runtime.IO.SetOutput(new FileStream(htmlOutput, FileMode.Create), Encoding.UTF8);
RunRubyCommandScript(engine, Path.Combine(_ironRubyLocation, @"bin\spec"), args);
ShowOutputFile(htmlOutput);
}
public string GherkinAssemblyFolder()
{
var gemFolder = Path.Combine(_ironRubyLocation, @"Lib\ironruby\gems\1.8\gems");
string searchPath = @"gherkin-*-universal-dotnet";
var result =
Directory.GetDirectories(gemFolder, searchPath)
.LastOrDefault();
if (result == null)
{
throw new DirectoryNotFoundException("Gherkin appears to be missing. I was looking for: "
+ Path.Combine(_ironRubyLocation, searchPath));
}
return Path.Combine(result, "lib");
}
public static void AddFolderLoadPath(string folderPath)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += (sender, args) => {
// var name = args.Name == "gherkin" ? "gherkin2" : args.Name;
var name = args.Name;
string assemblyPath = Path.Combine(folderPath, name + ".dll");
if (File.Exists(assemblyPath)) {
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
return null;
};
}
string _rspecPattern = "**/*_spec.rb";
public void RunCucumber() {
var htmlOutput = Path.GetTempFileName() + ".html";
// var args = new string[] { "--help" };
var args = new[] { _specFolder, "--out", htmlOutput, "--format", "html", "-exclude", _rspecPattern, "--strict" };
ScriptEngine engine = GetEngine();
// engine.Runtime.IO.SetOutput(new FileStream(htmlOutput, FileMode.Create), Encoding.UTF8);
RunRubyCommandScript(engine, RubyExecutable("cucumber"), args);
ShowOutputFile(htmlOutput);
}
public string RubyExecutable(string name)
{
return Path.Combine(_ironRubyLocation, "bin", name);
}
private static void ShowOutputFile(string htmlOutput)
{
var process = new System.Diagnostics.Process() {
StartInfo = new System.Diagnostics.ProcessStartInfo(htmlOutput) {
UseShellExecute = true
}
};
process.Start();
}
private ScriptEngine GetEngine()
{
var engine = IronRuby.Ruby.CreateEngine(); ;
var rubyPaths = RubyPaths().ToList();
rubyPaths.AddRange(_paths);
engine.SetSearchPaths(rubyPaths);
return engine;
}
public static void RunRubyCommandScript(ScriptEngine engine, string fileName, IEnumerable<string> rubyArgs)
{
SetArguments(engine, fileName, rubyArgs);
try {
engine.ExecuteFile(fileName);
} catch (SystemExit exit)
{
if (exit.Status != 0)
{
int x = 0; // Purely for breakpoints.
}
}
catch (SyntaxError syntaxError)
{
var rex = RubyExceptionData.GetInstance(syntaxError);
foreach (System.Collections.DictionaryEntry x in syntaxError.Data)
{
Console.WriteLine(string.Format("{0}:{1}", x.Key, x.Value));
}
throw;
}
catch (Exception ex) {
var rex = RubyExceptionData.GetInstance(ex);
throw;
}
}
private static void SetArguments(ScriptEngine engine, string fileName, IEnumerable<string> args) {
// var setup = engine.Setup.
dynamic rubyArgs = engine.Execute("$*");
rubyArgs.Clear();
foreach (string arg in args)
{
rubyArgs.Add(arg);
}
engine.Execute(string.Format("$0 = \"{0}\"", Escape(fileName)));
}
static string Escape(string arg) {
return arg
.Replace("\"", "\"\"")
.Replace("\\", "\\\\");
}
private static string GetExecutingDirectory() {
var codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
var uri = new Uri(codebase);
var fileName = uri.LocalPath + uri.Fragment;
return Path.GetDirectoryName(fileName);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment