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.
@@ -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
+