spec_query 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +5 -0
- data/README +31 -0
- data/Rakefile +2 -0
- data/init.rb +0 -0
- data/lib/extentions/README +5 -0
- data/lib/extentions/examples/breakout_query_ext.rb +139 -0
- data/lib/spec_query.rb +37 -0
- data/lib/spec_query/query/query.rb +45 -0
- data/lib/spec_query/run/simple_cmd.rb +19 -0
- data/lib/spec_query/search/grep.rb +66 -0
- data/lib/spec_query/search/search.rb +59 -0
- data/lib/spec_query/version.rb +4 -0
- data/lib/tasks/spec_query.rake +20 -0
- data/spec_query.gemspec +22 -0
- metadata +82 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
spec-query
|
2
|
+
==========
|
3
|
+
|
4
|
+
This is a small utility to query specs for Ruby on Rails projects.
|
5
|
+
This is useful if:
|
6
|
+
* you want to run specs that only contain some keywords
|
7
|
+
* you have a lot of slow specs and do not have a good organization of them
|
8
|
+
|
9
|
+
Install
|
10
|
+
=======
|
11
|
+
|
12
|
+
If you are using bundler, add this to the Gemfile:
|
13
|
+
|
14
|
+
gem "spec_query", :require => nil
|
15
|
+
|
16
|
+
No need for require, this is used only through a rake task.
|
17
|
+
|
18
|
+
You need to install the rake task manually. The easiest way is to find spec_query/lib/tasks/spec_query.rake in your GEM_PATH (run: `gem env` in console) and copy it to your projects lib/tasks.
|
19
|
+
|
20
|
+
Copy
|
21
|
+
|
22
|
+
Examples
|
23
|
+
========
|
24
|
+
|
25
|
+
# for help
|
26
|
+
rake q:spec # see help
|
27
|
+
rake q:spec q="keyword" # run only specs that have a keyword
|
28
|
+
rake q:spec q='keyword1&&keyword2||keyword3&&keyword4' # || is or, && is and
|
29
|
+
rake q:spec q='regexp --r' # use regexp
|
30
|
+
rake q:spec q='Case Sensitive statement --c' use case sensitive
|
31
|
+
|
data/Rakefile
ADDED
data/init.rb
ADDED
File without changes
|
@@ -0,0 +1,5 @@
|
|
1
|
+
Extentions
|
2
|
+
==========
|
3
|
+
|
4
|
+
If you want to add custom behavior to this gem you can do it via extentions. These modules will extend the SpecQuery::Query class. Default convention: extentions should be named *_query_ext.rb and put in ./spec directory. See examples for code.
|
5
|
+
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# created by Titas Norkūnas
|
2
|
+
# run specs by file contents extention for Breakout
|
3
|
+
# run specs by components
|
4
|
+
|
5
|
+
module BreakoutQuery
|
6
|
+
USE_CASE = "\nBreakout use cases:\n
|
7
|
+
1. Run specs by Breakout components. Use any (or just unique prefix) component name
|
8
|
+
rake q:spec g=Alerts
|
9
|
+
# runs all specs related to Alerts component
|
10
|
+
rake q:spec g=ag
|
11
|
+
# runs all specs related to Agile Planner component, as ag is unique prefix for this component
|
12
|
+
2. Provided there is a change related to space backups. To run only tests that can be related.
|
13
|
+
rake q:spec q=backup
|
14
|
+
3. Provided there are some changes related to portfolio views. To run only specs that can be related:
|
15
|
+
rake q:spec q='portfolio&&template||portfolio&&view'
|
16
|
+
# this will run all specs that have: (('portfolio' AND 'template') OR ('portfolio' AND 'view'))
|
17
|
+
4. Provided someone changed :space and :ticket factories. To run tests that use them:
|
18
|
+
rake q:spec q='Factory :space||Factory :ticket --c'
|
19
|
+
# this will run all specs that have either \"Factory :space\" OR \"Factory :ticket\" text. --c is for case-sensitive"
|
20
|
+
|
21
|
+
GROUP = "Please supply query q=query or g=group parameter for this rake task"
|
22
|
+
|
23
|
+
# TODO
|
24
|
+
# * add tags for missing components
|
25
|
+
COMPONENT_HASH = {
|
26
|
+
"Agile Planner" => "agile&&planner",
|
27
|
+
"Alerts" => "alerter||user_notify",
|
28
|
+
"App Admin" => "admin",
|
29
|
+
"Branded spaces" => "?",
|
30
|
+
"BreakoutParser" => "breakout&&parser",
|
31
|
+
"Catalog" => "?",
|
32
|
+
"Chat" => "chat",
|
33
|
+
"Commercial" => "?",
|
34
|
+
"Core" => "?",
|
35
|
+
"Core - spaces" => "?",
|
36
|
+
"Core - users" => "?",
|
37
|
+
"Core-processors" => "?",
|
38
|
+
"cron tasks scripts" => "?",
|
39
|
+
"Custom Status" => "ticket_status",
|
40
|
+
"Dashboard" => "?",
|
41
|
+
"Events" => "event",
|
42
|
+
"Files" => "?",
|
43
|
+
"Fork and Merge" => "fork||merge",
|
44
|
+
"FTP Tool" => "ftp",
|
45
|
+
"Gerrit" => "gerrit",
|
46
|
+
"Help and Docs" => "?",
|
47
|
+
"Home / Marketing" => "?",
|
48
|
+
"I18N" => "?",
|
49
|
+
"Image annotation" => "?",
|
50
|
+
"Jobs/recruit/contract" => "?",
|
51
|
+
"Messages" => "?",
|
52
|
+
"Milestones" => "milestone",
|
53
|
+
"New Tools" => "?",
|
54
|
+
"Other" => "?",
|
55
|
+
"Other Tools" => "?",
|
56
|
+
"Performance" => "?",
|
57
|
+
"Portfolio#Admin" => "portfolio&&admin",
|
58
|
+
"Portfolio#BrandingAndHome" => "portfolio&&brand",
|
59
|
+
"Portfolio#Filters" => "portfolio&&filter",
|
60
|
+
"Portfolio#Projects" => "portfolio&&project",
|
61
|
+
"Portfolio#Start" => "?",
|
62
|
+
"Portfolio#Stream" => "?",
|
63
|
+
"Portfolio#Tickets" => "portfolio&&ticket",
|
64
|
+
"Portfolio#Time" => "portfolio&&time",
|
65
|
+
"Portfolio#Users" => "portfolio&&user",
|
66
|
+
"Private Installation" => "?",
|
67
|
+
"Project Portfolio" => "?",
|
68
|
+
"RCB" => "rcb",
|
69
|
+
"Repo Exp." => "?",
|
70
|
+
"Repositories" => "?",
|
71
|
+
"REST-auth module" => "?",
|
72
|
+
"Scrum tool" => "?",
|
73
|
+
"Search" => "?",
|
74
|
+
"Server admin" => "?",
|
75
|
+
"Server Tool" => "?",
|
76
|
+
"Site Architecture" => "?",
|
77
|
+
"Skype" => "?",
|
78
|
+
"Spaces Admin" => "?",
|
79
|
+
"Staffing" => "?",
|
80
|
+
"Support" => "?",
|
81
|
+
"Ticket tool" => "?",
|
82
|
+
"Time tool" => "?",
|
83
|
+
"Time/bill/pay" => "?",
|
84
|
+
"Tool Permissions" => "permission",
|
85
|
+
"Trac" => "trac",
|
86
|
+
"Wiki" => "wiki"
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
def initialize(*args)
|
91
|
+
self.extend BreakoutQuery::QueryMethods
|
92
|
+
end
|
93
|
+
|
94
|
+
module QueryMethods
|
95
|
+
def help
|
96
|
+
help_info = super
|
97
|
+
help_info[0] = GROUP
|
98
|
+
help_info + [USE_CASE]
|
99
|
+
end
|
100
|
+
|
101
|
+
def env_condition
|
102
|
+
super || env["g"]
|
103
|
+
end
|
104
|
+
|
105
|
+
def make_query
|
106
|
+
group = env["g"]
|
107
|
+
if group
|
108
|
+
key, value = get_group(group)
|
109
|
+
puts "Running specs for: #{key}"
|
110
|
+
value
|
111
|
+
else
|
112
|
+
super
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def get_group(group)
|
119
|
+
c = COMPONENT_HASH[group]
|
120
|
+
if c == "?"
|
121
|
+
puts "Group not implemented"
|
122
|
+
exit 1
|
123
|
+
else
|
124
|
+
return [group, c] if c.present?
|
125
|
+
# if only one key starts with group
|
126
|
+
keys = COMPONENT_HASH.keys.select do |k|
|
127
|
+
k.downcase.start_with?(group.downcase)
|
128
|
+
end
|
129
|
+
if keys.length == 1
|
130
|
+
return [keys.first, COMPONENT_HASH[keys.first]]
|
131
|
+
else
|
132
|
+
puts "Please be more specific, multiple matches:", keys
|
133
|
+
exit 1
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
data/lib/spec_query.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "spec_query/query/query"
|
2
|
+
require "spec_query/run/simple_cmd"
|
3
|
+
require "spec_query/search/search"
|
4
|
+
require "spec_query/search/grep"
|
5
|
+
require "spec_query/version"
|
6
|
+
|
7
|
+
module SpecQuery
|
8
|
+
class SpecRunner
|
9
|
+
def run(env)
|
10
|
+
query_maker = SpecQuery::Query.new()
|
11
|
+
query_maker.other_help = ["Available options:"] +
|
12
|
+
search_strategy.available_options.map{|k,v| "#{k} #{v}"}
|
13
|
+
searcher = search_strategy.new(query_maker.query(env))
|
14
|
+
spec_files = searcher.get_files
|
15
|
+
runner = run_strategy.new(spec_files)
|
16
|
+
runner.spec
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# implement other strategy for non-unix
|
22
|
+
def search_strategy
|
23
|
+
if SpecQuery::Grep.available?
|
24
|
+
SpecQuery::Grep
|
25
|
+
else
|
26
|
+
puts "not implemented, sorry"
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# implement a more sophisticated strategy
|
32
|
+
def run_strategy
|
33
|
+
SpecQuery::SimpleCmd
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SpecQuery
|
2
|
+
class Query
|
3
|
+
# require *_query_ext.rb files from spec directory
|
4
|
+
@@modules = []
|
5
|
+
Dir.new("spec").entries.select{|f| f.end_with?("_query_ext.rb")}.each do |mdl|
|
6
|
+
@@modules << (require "spec/#{mdl}")
|
7
|
+
end if File.exists?("spec")
|
8
|
+
|
9
|
+
# include specific modules
|
10
|
+
@@modules.each do |mdl|
|
11
|
+
include Object.const_get(mdl.first) unless mdl == true
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :env, :other_help
|
15
|
+
def query(environment)
|
16
|
+
self.env = environment
|
17
|
+
unless env_condition
|
18
|
+
puts help
|
19
|
+
exit 1
|
20
|
+
else
|
21
|
+
query = make_query
|
22
|
+
end
|
23
|
+
if query.blank?
|
24
|
+
puts "No query supplied"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
query
|
28
|
+
end
|
29
|
+
|
30
|
+
def help
|
31
|
+
["Please supply query q=query parameter for this rake task",
|
32
|
+
"Sample use: rake q:spec q='keyword1&&keyword2||keyword3&&keyword4'"] + (other_help ? other_help : [])
|
33
|
+
end
|
34
|
+
|
35
|
+
def env_condition
|
36
|
+
env["q"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_query
|
40
|
+
puts "Running specs for: #{env['q']}"
|
41
|
+
env["q"]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SpecQuery
|
2
|
+
class SimpleCmd
|
3
|
+
attr_accessor :files
|
4
|
+
def initialize(files)
|
5
|
+
self.files = files
|
6
|
+
end
|
7
|
+
|
8
|
+
def spec
|
9
|
+
if files.present?
|
10
|
+
puts "Matched specs: #{files.size}"
|
11
|
+
puts files
|
12
|
+
system "ruby -Itest -Ispec #{files.join(' ')}"
|
13
|
+
else
|
14
|
+
puts "No maches"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module SpecQuery
|
2
|
+
class Grep < Search
|
3
|
+
attr_accessor :grep_opts
|
4
|
+
GREP_TMP_FILE = ".tests.tmp"
|
5
|
+
|
6
|
+
def self.available?
|
7
|
+
system("grep --v > /dev/null")
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.available_options
|
11
|
+
parent_options = super()
|
12
|
+
parent_options[" --r"] = "Use grep regexp subset: https://help.ubuntu.com/community/grep"
|
13
|
+
parent_options
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO parse self.options to grep options
|
17
|
+
def parse_options
|
18
|
+
self.grep_opts = ""
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_files_with_regex(regex, options)
|
22
|
+
# find all file names in spec/ by regular expression
|
23
|
+
# -r => recursive
|
24
|
+
# -l => file names with matches
|
25
|
+
# write to GREP_TMP_FILE file
|
26
|
+
res = system "grep -r -l #{grep_opts} '#{regex}' spec/* | grep _spec.rb > #{GREP_TMP_FILE}"
|
27
|
+
read_tmp_file(res, GREP_TMP_FILE)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_with_keyword(keyword, options)
|
31
|
+
# find all file names in spec/ that contain keyword.
|
32
|
+
# -F => fixed string, not regexp
|
33
|
+
# -r => recursive
|
34
|
+
# -l => file names with matches
|
35
|
+
# -i => ingore case
|
36
|
+
# write to GREP_TMP_FILE file
|
37
|
+
self.grep_opts += options.include?("--c") ? "" : " -i "
|
38
|
+
res = system "grep -F -r -l #{grep_opts} '#{keyword}' spec/* | grep _spec.rb > #{GREP_TMP_FILE}"
|
39
|
+
read_tmp_file(res, GREP_TMP_FILE)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def read_tmp_file(res, file_name)
|
45
|
+
unless res
|
46
|
+
puts "No maches"
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
begin
|
50
|
+
file = File.open(file_name, "rb")
|
51
|
+
contents = file.read
|
52
|
+
file.close
|
53
|
+
rescue => e
|
54
|
+
puts "Exception: #{e}"
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
cleanup
|
58
|
+
contents.split("\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
def cleanup
|
62
|
+
system "rm #{GREP_TMP_FILE}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module SpecQuery
|
2
|
+
class Search
|
3
|
+
# original options, original query
|
4
|
+
attr_accessor :options, :query
|
5
|
+
|
6
|
+
def self.available_options
|
7
|
+
{" --c" => "Case sensitive", " --r" => "Use regexp"}
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(query)
|
11
|
+
self.query, self.options = split_query(query)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_files
|
15
|
+
parse_options
|
16
|
+
if options.include?("--r")
|
17
|
+
get_files_with_regex(query, options)
|
18
|
+
else
|
19
|
+
get_files_with_keywords(query, options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
# TODO
|
26
|
+
# * use some library for parsing this
|
27
|
+
def split_query(original_query)
|
28
|
+
options = []
|
29
|
+
query = original_query
|
30
|
+
self.class.available_options.keys.each do |o|
|
31
|
+
if original_query.include?(o)
|
32
|
+
query = query.gsub(o, "")
|
33
|
+
options << o.strip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
[query, options]
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_files_with_keywords(keywords, options)
|
40
|
+
files = []
|
41
|
+
# keyword1&&keyword2||keyword3&&keyword4
|
42
|
+
keywords.split("||").each do |keywords_and|
|
43
|
+
# [keyword1&&keyword2, keyword3&&keyword4]
|
44
|
+
files_and = []
|
45
|
+
keywords_and.split("&&").each_with_index do |k, i|
|
46
|
+
# [[keyword1, keyword2], [keyword3, keyword4]]
|
47
|
+
if i == 0 # first time just add
|
48
|
+
files_and = get_with_keyword(k, options)
|
49
|
+
else # use & for getting only what we were requested
|
50
|
+
files_and = files_and & get_with_keyword(k, options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
files << files_and
|
54
|
+
end
|
55
|
+
files.flatten.uniq
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# created by Titas Norkūnas
|
2
|
+
# run specs by file contents
|
3
|
+
# searches all spec files for keywords and runs only those specs, that contain them.
|
4
|
+
# you can use || as OR and && as AND.
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "spec_query" # do not load environment == faster
|
8
|
+
|
9
|
+
namespace :q do
|
10
|
+
# TODO
|
11
|
+
# * add more options
|
12
|
+
# ** add option to search in filenames, not only contents
|
13
|
+
# * make this work on non-unix
|
14
|
+
desc "Query spec: searches all spec files for keywords and runs only those specs, that contain them"
|
15
|
+
task :spec do
|
16
|
+
spec_runner = SpecQuery::SpecRunner.new
|
17
|
+
spec_runner.run(ENV)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/spec_query.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "spec_query/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "spec_query"
|
7
|
+
s.version = SpecQuery::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Titas Norkūnas"]
|
10
|
+
s.email = ["titas.norkunas@gmail.com"]
|
11
|
+
s.homepage = "http://www.assembla.com/profile/titas.norkunas"
|
12
|
+
s.summary = %q{Run specs by keywords they contain}
|
13
|
+
s.description = %q{This is a small utility to query specs for Ruby on Rails projects}
|
14
|
+
|
15
|
+
s.rubyforge_project = "spec_query"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
22
|
+
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spec_query
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Titas Nork\xC5\xABnas"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-28 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: This is a small utility to query specs for Ruby on Rails projects
|
23
|
+
email:
|
24
|
+
- titas.norkunas@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- README
|
35
|
+
- Rakefile
|
36
|
+
- init.rb
|
37
|
+
- lib/extentions/README
|
38
|
+
- lib/extentions/examples/breakout_query_ext.rb
|
39
|
+
- lib/spec_query.rb
|
40
|
+
- lib/spec_query/query/query.rb
|
41
|
+
- lib/spec_query/run/simple_cmd.rb
|
42
|
+
- lib/spec_query/search/grep.rb
|
43
|
+
- lib/spec_query/search/search.rb
|
44
|
+
- lib/spec_query/version.rb
|
45
|
+
- lib/tasks/spec_query.rake
|
46
|
+
- spec_query.gemspec
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://www.assembla.com/profile/titas.norkunas
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project: spec_query
|
77
|
+
rubygems_version: 1.3.7
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Run specs by keywords they contain
|
81
|
+
test_files: []
|
82
|
+
|