single_test 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +49 -0
- data/Rakefile +21 -0
- data/VERSION +1 -0
- data/lib/single_test.rb +104 -0
- data/single_test.gemspec +48 -0
- data/spec/example_finder_test.txt +7 -0
- data/spec/single_test_spec.rb +166 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/single_test.rake +21 -0
- metadata +64 -0
data/README.markdown
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
Runs a single test/spec via rake.
|
2
|
+
|
3
|
+
USAGE
|
4
|
+
=====
|
5
|
+
As Rails plugin:
|
6
|
+
script/plugin install git://github.com/grosser/single_test.git
|
7
|
+
|
8
|
+
As Gem:
|
9
|
+
sudo gem install single_test
|
10
|
+
|
11
|
+
# in your Rakefile
|
12
|
+
require 'single_test'
|
13
|
+
SingleTest.load_tasks
|
14
|
+
|
15
|
+
|
16
|
+
###Single test/spec
|
17
|
+
rake spec:user #run spec/model/user_spec.rb (searches for user*_spec.rb)
|
18
|
+
rake test:users_c #run test/functional/users_controller_test.rb
|
19
|
+
rake spec:admin/users_c #run spec/controllers/admin/users_controller_spec.rb
|
20
|
+
rake test:u*hel #run test/helpers/user_helper_test.rb (searches for u*hel*_test.rb)
|
21
|
+
|
22
|
+
###Single test-case/example
|
23
|
+
rake spec:user:token #run the first spec in user_spec.rb that matches /token/
|
24
|
+
rake test:user:token #run all tests in user_test.rb that match /token/
|
25
|
+
|
26
|
+
###Spec-server
|
27
|
+
rake spec:user X= #run test on spec_sever (if one is running...), very fast for quick failure pin-pointing
|
28
|
+
|
29
|
+
###All one by one
|
30
|
+
rake spec:one_by_one #run each spec/test one by one, to find tests that fail when ran
|
31
|
+
rake test:one_by_one #on their own or produce strange output
|
32
|
+
|
33
|
+
###For last mofified file
|
34
|
+
rake test:last
|
35
|
+
rake spec:last
|
36
|
+
|
37
|
+
TIPS
|
38
|
+
====
|
39
|
+
- if `script/spec` is missing, if will use just `spec` for specs (which solves some issues)
|
40
|
+
|
41
|
+
TODO
|
42
|
+
====
|
43
|
+
- make test:last more clever e.g. lib -> try spec + spec/lib
|
44
|
+
|
45
|
+
AUTHOR
|
46
|
+
======
|
47
|
+
[Michael Grosser](http://pragmatig.wordpress.com)
|
48
|
+
grosser.michael@gmail.com
|
49
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
task :default do |t|
|
2
|
+
options = "--colour"
|
3
|
+
files = FileList['spec/**/*_spec.rb'].map{|f| f.sub(%r{^spec/},'') }
|
4
|
+
exit system("cd spec && spec #{options} #{files}") ? 0 : 1
|
5
|
+
end
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
project_name = 'single_test'
|
10
|
+
Jeweler::Tasks.new do |gem|
|
11
|
+
gem.name = project_name
|
12
|
+
gem.summary = "Rake tasks to invoke single tests/specs with rakish syntax"
|
13
|
+
gem.email = "grosser.michael@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/grosser/#{project_name}"
|
15
|
+
gem.authors = ["Michael Grosser"]
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
21
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/single_test.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
module SingleTest
|
4
|
+
extend self
|
5
|
+
CMD_LINE_MATCHER = /^(spec|test)\:.*(\:.*)?$/
|
6
|
+
SEARCH_ORDER = {
|
7
|
+
'test'=> %w(unit functional integration *),
|
8
|
+
'spec'=> %w(models controllers views helpers *),
|
9
|
+
}
|
10
|
+
|
11
|
+
def load_tasks
|
12
|
+
tasks = File.join(File.dirname(__FILE__), '..', 'tasks')
|
13
|
+
load File.join(tasks, 'single_test.rake')
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_last(type)
|
17
|
+
path = "app"
|
18
|
+
last = last_modified_file(path,:ext=>'.rb')
|
19
|
+
test = last.sub('app/',"#{type}/").sub('.rb',"_#{type}.rb")
|
20
|
+
if File.exist?(test)
|
21
|
+
run_test(type, test)
|
22
|
+
else
|
23
|
+
puts "could not find #{test}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def all_tests(type)
|
28
|
+
FileList["#{type}/**/*_#{type}.rb"].reject{|file|File.directory?(file)}
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_one_by_one(type)
|
32
|
+
tests = all_tests(type)
|
33
|
+
puts "Running #{tests.size} #{type}s"
|
34
|
+
tests.sort.each do |file|
|
35
|
+
puts "Running #{file}"
|
36
|
+
run_test(type, file)
|
37
|
+
puts ''
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_from_cli(call)
|
42
|
+
type, file, test_name = parse_cli(call)
|
43
|
+
file = find_test_file(type,file)
|
44
|
+
return unless file
|
45
|
+
|
46
|
+
#when spec, convert test_name regex to actual test_name
|
47
|
+
if type == 'spec' && test_name
|
48
|
+
test_name = find_example_in_spec(file, test_name) || test_name
|
49
|
+
end
|
50
|
+
|
51
|
+
#run the file
|
52
|
+
puts "running: #{file}"
|
53
|
+
ENV['RAILS_ENV'] = 'test' #current EVN['RAILS_ENV'] is 'development', and will also exist in all called commands
|
54
|
+
run_test(type, file, test_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
# spec:user:blah --> [spec,user,blah]
|
58
|
+
def parse_cli(call)
|
59
|
+
raise "you should not have gotten here..." unless call =~ CMD_LINE_MATCHER
|
60
|
+
arguments = call.split(":",3)
|
61
|
+
[
|
62
|
+
arguments[0], #type
|
63
|
+
arguments[1], #file name
|
64
|
+
arguments[2].to_s.strip.empty? ? nil : arguments[2] #test name
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
def find_test_file(type,file_name)
|
69
|
+
["","**/"].each do |depth| # find in lower folders first
|
70
|
+
['','*'].each do |exactness| # find exact matches first
|
71
|
+
SEARCH_ORDER[type].each do |folder|
|
72
|
+
base = "#{type}/#{folder}/#{depth}#{file_name}"
|
73
|
+
# without wildcard no search is performed -> ?rb
|
74
|
+
found = FileList["#{base}#{exactness}_#{type}?rb"].first
|
75
|
+
return found if found
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_example_in_spec(file, test_name)
|
83
|
+
File.readlines(file).each do |line|
|
84
|
+
return $2 if line =~ /.*it\s*(["'])(.*#{test_name}.*)\1\s*do/
|
85
|
+
end
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def run_test(type, file, test_name=nil)
|
90
|
+
case type.to_s
|
91
|
+
when 'test' then sh "ruby -Ilib:test #{file} -n /#{test_name}/"
|
92
|
+
when 'spec' then sh "export RAILS_ENV=test ; #{spec_executable} -O spec/spec.opts #{file}" + (test_name ? %Q( -e "#{test_name.sub('"',"\\\"")}") : '') + (ENV['X'] ? " -X" : "")
|
93
|
+
else raise "Unknown: #{type}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def spec_executable
|
98
|
+
File.exist?("script/spec") ? "script/spec" : "spec"
|
99
|
+
end
|
100
|
+
|
101
|
+
def last_modified_file(dir, options={})
|
102
|
+
Dir["#{dir}/**/*#{options[:ext]}"].sort_by { |p| File.mtime(p) }.last
|
103
|
+
end
|
104
|
+
end
|
data/single_test.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{single_test}
|
8
|
+
s.version = "0.3.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2009-12-13}
|
13
|
+
s.email = %q{grosser.michael@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.markdown"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
"README.markdown",
|
19
|
+
"Rakefile",
|
20
|
+
"VERSION",
|
21
|
+
"lib/single_test.rb",
|
22
|
+
"single_test.gemspec",
|
23
|
+
"spec/example_finder_test.txt",
|
24
|
+
"spec/single_test_spec.rb",
|
25
|
+
"spec/spec_helper.rb",
|
26
|
+
"tasks/single_test.rake"
|
27
|
+
]
|
28
|
+
s.homepage = %q{http://github.com/grosser/single_test}
|
29
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
s.rubygems_version = %q{1.3.5}
|
32
|
+
s.summary = %q{Rake tasks to invoke single tests/specs with rakish syntax}
|
33
|
+
s.test_files = [
|
34
|
+
"spec/spec_helper.rb",
|
35
|
+
"spec/single_test_spec.rb"
|
36
|
+
]
|
37
|
+
|
38
|
+
if s.respond_to? :specification_version then
|
39
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
40
|
+
s.specification_version = 3
|
41
|
+
|
42
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
43
|
+
else
|
44
|
+
end
|
45
|
+
else
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require 'single_test'
|
3
|
+
|
4
|
+
describe SingleTest do
|
5
|
+
describe :parse_cli do
|
6
|
+
it "finds the type spec" do
|
7
|
+
SingleTest.parse_cli('spec:something')[0].should == 'spec'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "finds the type test" do
|
11
|
+
SingleTest.parse_cli('test:something:else')[0].should == 'test'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not find another type" do
|
15
|
+
lambda{SingleTest.parse_cli('oops:something:else')}.should raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "parses the file name" do
|
19
|
+
SingleTest.parse_cli('test:something:else')[1].should == 'something'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "parses the test name" do
|
23
|
+
SingleTest.parse_cli('test:something:else')[2].should == 'else'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "parses missing test name as nil" do
|
27
|
+
SingleTest.parse_cli('test:something')[2].should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "parses empty test name as nil" do
|
31
|
+
SingleTest.parse_cli('test:something: ')[2].should be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "does not split test name further" do
|
35
|
+
SingleTest.parse_cli('test:something:else:oh:no')[2].should == 'else:oh:no'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe :find_test_file do
|
40
|
+
def make_file(path)
|
41
|
+
folder = File.dirname(path)
|
42
|
+
`mkdir -p #{folder}` unless File.exist?(folder)
|
43
|
+
`touch #{path}`
|
44
|
+
raise unless File.exist?(path)
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
`rm -rf spec`
|
49
|
+
end
|
50
|
+
|
51
|
+
it "finds exact matches first" do
|
52
|
+
make_file 'spec/mixins/xxx_spec.rb'
|
53
|
+
make_file 'spec/controllers/xxx_controller_spec.rb'
|
54
|
+
SingleTest.find_test_file('spec','xxx').should == 'spec/mixins/xxx_spec.rb'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "finds lower files first" do
|
58
|
+
make_file 'spec/mixins/xxx_spec.rb'
|
59
|
+
make_file 'spec/mixins/xxx/xxx_spec.rb'
|
60
|
+
SingleTest.find_test_file('spec','xxx').should == 'spec/mixins/xxx_spec.rb'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "finds models before controllers" do
|
64
|
+
make_file 'spec/models/xxx_spec.rb'
|
65
|
+
make_file 'spec/controllers/xxx_controller_spec.rb'
|
66
|
+
SingleTest.find_test_file('spec','xx').should == 'spec/models/xxx_spec.rb'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "finds with paths" do
|
70
|
+
make_file 'spec/controllers/admin/xxx_controller_spec.rb'
|
71
|
+
SingleTest.find_test_file('spec','ad*/xx').should == 'spec/controllers/admin/xxx_controller_spec.rb'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe :find_example_in_spec do
|
76
|
+
examples_file = File.join(File.dirname(__FILE__),'example_finder_test.txt')
|
77
|
+
|
78
|
+
it "finds a complete statement" do
|
79
|
+
SingleTest.find_example_in_spec(examples_file,'example 1').should == 'example 1'
|
80
|
+
end
|
81
|
+
|
82
|
+
it "finds a partial statement" do
|
83
|
+
SingleTest.find_example_in_spec(examples_file,'mple 1').should == 'example 1'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "finds in strangely formatted files" do
|
87
|
+
SingleTest.find_example_in_spec(examples_file,'2').should == 'example "2"'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns nil for unfound examples" do
|
91
|
+
SingleTest.find_example_in_spec(examples_file,'not here').should == nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe :run_last do
|
96
|
+
before do
|
97
|
+
`mkdir app` unless File.exist?('app')
|
98
|
+
`touch app/yyy.rb`
|
99
|
+
`touch app/xxx.rb`
|
100
|
+
`mkdir spec` unless File.exist?('spec')
|
101
|
+
`touch spec/xxx_spec.rb`
|
102
|
+
`touch spec/yyy_spec.rb`
|
103
|
+
end
|
104
|
+
|
105
|
+
it "runs the last test" do
|
106
|
+
SingleTest.should_receive(:run_test).with(:spec, "spec/yyy_spec.rb")
|
107
|
+
SingleTest.run_last(:spec)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "runs another file when timestamps change" do
|
111
|
+
`touch -t 12312359 #{SPEC_ROOT}/app/yyy.rb` # last minute in current year, spec will fail on new years eve :D
|
112
|
+
SingleTest.should_receive(:run_test).with(:spec, "spec/yyy_spec.rb")
|
113
|
+
SingleTest.run_last(:spec)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe :run_test do
|
118
|
+
after :all do
|
119
|
+
ENV['X']=nil
|
120
|
+
end
|
121
|
+
|
122
|
+
it "fails when type is not spec/test" do
|
123
|
+
lambda{SingleTest.run_test('x','y')}.should raise_error
|
124
|
+
end
|
125
|
+
|
126
|
+
it "runs whole tests" do
|
127
|
+
SingleTest.should_receive(:sh).with('ruby -Ilib:test xxx -n //')
|
128
|
+
SingleTest.run_test('test','xxx')
|
129
|
+
end
|
130
|
+
|
131
|
+
it "runs single tests on their own" do
|
132
|
+
SingleTest.should_receive(:sh).with('ruby -Ilib:test xxx -n /yyy/')
|
133
|
+
SingleTest.run_test('test', 'xxx', 'yyy')
|
134
|
+
end
|
135
|
+
|
136
|
+
it "runs whole specs without -e" do
|
137
|
+
SingleTest.should_receive(:sh).with('export RAILS_ENV=test ; script/spec -O spec/spec.opts xxx')
|
138
|
+
SingleTest.run_test('spec','xxx')
|
139
|
+
end
|
140
|
+
|
141
|
+
it "runs single specs through -e" do
|
142
|
+
SingleTest.should_receive(:sh).with('export RAILS_ENV=test ; script/spec -O spec/spec.opts xxx -e "yyy"')
|
143
|
+
SingleTest.run_test('spec','xxx', 'yyy')
|
144
|
+
end
|
145
|
+
|
146
|
+
it "runs single specs through -e with -X" do
|
147
|
+
ENV['X']=''
|
148
|
+
SingleTest.should_receive(:sh).with('export RAILS_ENV=test ; script/spec -O spec/spec.opts xxx -e "yyy" -X')
|
149
|
+
SingleTest.run_test('spec','xxx', 'yyy')
|
150
|
+
end
|
151
|
+
|
152
|
+
it "runs quoted specs though -e" do
|
153
|
+
SingleTest.should_receive(:sh).with(%Q(export RAILS_ENV=test ; script/spec -O spec/spec.opts xxx -e "y\\\"yy" -X))
|
154
|
+
SingleTest.run_test('spec','xxx', 'y"yy')
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe :load_tasks do
|
160
|
+
it "can load em" do
|
161
|
+
(Rake::Task['spec:one_by_one'] rescue nil).should == nil
|
162
|
+
SingleTest.load_tasks
|
163
|
+
Rake::Task['spec:one_by_one'].should_not == nil
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# ---- requirements
|
2
|
+
SPEC_ROOT = File.dirname(__FILE__)
|
3
|
+
$LOAD_PATH << File.expand_path("../lib", SPEC_ROOT)
|
4
|
+
|
5
|
+
# ---- rspec
|
6
|
+
Spec::Runner.configure do |config|
|
7
|
+
config.before do
|
8
|
+
`mkdir -p #{SPEC_ROOT}/script`
|
9
|
+
`touch #{SPEC_ROOT}/script/spec`
|
10
|
+
end
|
11
|
+
config.after do
|
12
|
+
`rm -rf #{SPEC_ROOT}/script`
|
13
|
+
`rm -rf #{SPEC_ROOT}/app`
|
14
|
+
`rm -rf #{SPEC_ROOT}/spec`
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#matches SingleTest::CMD_LINE_MATCHER --- test/spec:file[:method]
|
2
|
+
rule /^(spec|test)\:.*(\:.*)?$/ do |t|
|
3
|
+
require File.join(File.dirname(__FILE__),'..','lib','single_test')
|
4
|
+
SingleTest.run_from_cli(t.name)
|
5
|
+
end
|
6
|
+
|
7
|
+
[:spec, :test].each do |type|
|
8
|
+
namespace type do
|
9
|
+
desc "Runs each #{type} one by one and displays its results -> see which #{type}s fail on their own"
|
10
|
+
task :one_by_one do
|
11
|
+
require File.join(File.dirname(__FILE__),'..','lib','single_test')
|
12
|
+
SingleTest.run_one_by_one(type)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "run #{type} for last modified file in app folder"
|
16
|
+
task :last do
|
17
|
+
require File.join(File.dirname(__FILE__),'..','lib','single_test')
|
18
|
+
SingleTest.run_last(type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: single_test
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Grosser
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-13 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: grosser.michael@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.markdown
|
24
|
+
files:
|
25
|
+
- README.markdown
|
26
|
+
- Rakefile
|
27
|
+
- VERSION
|
28
|
+
- lib/single_test.rb
|
29
|
+
- single_test.gemspec
|
30
|
+
- spec/example_finder_test.txt
|
31
|
+
- spec/single_test_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- tasks/single_test.rake
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/grosser/single_test
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --charset=UTF-8
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.5
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Rake tasks to invoke single tests/specs with rakish syntax
|
62
|
+
test_files:
|
63
|
+
- spec/spec_helper.rb
|
64
|
+
- spec/single_test_spec.rb
|