Skip to content

Instantly share code, notes, and snippets.

@luikore
Created March 17, 2011 08:56
Show Gist options
  • Save luikore/874023 to your computer and use it in GitHub Desktop.
Save luikore/874023 to your computer and use it in GitHub Desktop.
runt unit/functional test of current file and output html for textmate

Playing with TextMate is fun, but I can't find any bundle that can make running a single-file unit test or functional test easily.

Effect

So I want to custom a command:

  • By pressing key, TextMate will figure out which test to run.

    When the opened file is app/controllers/abc_controller.rb, the test file is test/functional/abc_controller_test.rb

    When it becomes app/models/abc.rb then test file should be test/unit/abc_test.rb

  • By clicking the error message, I can google it (maybe plus a word "ruby")

  • By clicking the trace, I can navigate to the correct file and correct line

A screenshot: (Just like a vim plugin for ruby test)

effect

How

Thanks to the Very Decently Composed Introduction of TextMate Commands, it's easy!

A TextMate command is simply a script, which may be executed by bash, ruby, python, applescript ... Editor state is saved in environment variables such as $TM_FILEPATH.

  • To read some text input from current selection, just change the input field and read from stdin

  • To link to a page in web browser, use a link with TextMate specific javascript:

    <a href='javascript:TextMate.system("open http://the.page.you.want", null)'>text you see</a>
    
  • To link to a file opened or not opened in TextMate:

    <a href='txmt://open?url=*file_path*&line=*line_number*'>text you see</a>
    

Code

#!/usr/bin/env ruby
# custom options
ruby_switches = "-Ku -Itest"
google_template = "ruby %s"
# find out test file
require 'fileutils'
$f = ENV['TM_FILEPATH'].dup
$f.sub! /\/app\/models\/(\w+)\.rb/, '/test/unit/\1_test.rb'
$f.sub! /\/app\/controllers\/(\w+)\.rb/, '/test/functional/\1_test.rb'
unless dir = ( $f[/.*(?=\/test\/unit\/)/] or $f[/.*(?=\/test\/functional\/)/] )
puts "Can't recognize test file: #$f"
exit
end
FileUtils.cd dir
# run test
result = `ruby #{ruby_switches} #$f 2>&1`
result = result.split("\n")
# transform results
require 'cgi'
trace_pattern = /(.+\.rb):(\d+)(?=:in)/
error_flip = false
result.each do |line|
case line.strip
when /^\d+\)\ Error:$/
# the next line will be error class and message
error_flip = true
puts "<b style='font-weight:bold'>#{line}</b><br/>"
when trace_pattern
# link to trace file
line.sub! trace_pattern do
line_num = $2
file_base = $1.strip
file_name = File.expand_path file_base
"<a href='txmt://open?url=file://#{file_name}&line=#{line_num}'>#{file_base}:#{line_num}</a>"
end
puts line, '<br/>'
else
# link to google
if error_flip and line =~ /^(\w+):(.*)$/
style = 'text-decoration:none;color:black;background:#def'
q = CGI.escape google_template % [line.strip]
q = %Q["open http://www.google.com/search?q=#{q}"]
puts "<a href='javascript:TextMate.system(#{q},null);'"
puts "style='#{style};display:block;margin:4px 0'"
puts "title='search in google'>"
puts "#$1:<span style='color:c25'>#$2</span>"
puts "</a>"
error_flip = false
else
# faint grey unimportant text
puts "<span style='color:#999'>#{line}</span><br/>"
end
end
end

Config

config

Rspec is not supported yet, but it won't require much modification if you know how it goes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment