spec_query 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in spec_query.gemspec
4
+ gemspec
5
+
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
+
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
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
+
@@ -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,4 @@
1
+ module SpecQuery
2
+ VERSION = "0.0.1"
3
+ end
4
+
@@ -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
+
@@ -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
+