acts_as_qa 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,200 @@
1
+ ActsAsQA
2
+ ==========
3
+
4
+ ActsAsQa checks all the actions defined in the application and their responses. It returns success if response is success, redirect or
5
+ page not found otherwise it returns false.
6
+
7
+ Requirement
8
+ ============
9
+
10
+ Rails 3
11
+
12
+ Install as Gem
13
+ ==============
14
+
15
+ Open 'Gemfile' and add the following line:
16
+
17
+ gem 'acts_as_qa'
18
+
19
+ Now run:
20
+
21
+ bundle install
22
+
23
+
24
+ Install as plugin
25
+ =================
26
+
27
+ To install as plugin run:
28
+
29
+ rails plugin install git@github.com:sapnasolutions/sapna-acts_as_qa.git
30
+
31
+ Getting started
32
+ ===============
33
+
34
+ Run the rake task
35
+
36
+ rake acts_as_qa:setup
37
+
38
+ This adds parameters for each action in a controller. This rake task also creates a new environment 'acts_as_qa'. this task also adds a
39
+ before_filter in application_controller.rb to create a logged in user. Open each controller and supply parameters according to requirement of
40
+ action.
41
+
42
+ Formats of Parameters
43
+ =====================
44
+
45
+ (This step can be skipped initially)
46
+
47
+ Following are the formats of the parameters:
48
+
49
+ #QA :a => 'b'
50
+
51
+ so for show action for posts controller:
52
+
53
+ #QA :id => Post.first.id
54
+
55
+ or
56
+
57
+ #QA :id => :post
58
+
59
+ or
60
+
61
+ #QA :id => :integer
62
+
63
+ When a symbol is passed like ':post' or ':integer', it automatically generates values for parameter. when the symbol is a name of model it first
64
+ generates attribute of some random model instance. For Example if its ':author_id => :post' then it finds some random but existing 'author_id'
65
+ from 'Post' Model and then it also generates some random integer, date string, float etc. By this way valid and invalid values can be passed
66
+ to action which helps to test different type conditions. The possible data types are:
67
+
68
+ :boolean
69
+ :date
70
+ :datetime
71
+ :decimal
72
+ :float
73
+ :integer
74
+ :string
75
+
76
+ When an array is passed in parameters it hits the action one by one using each value in array.
77
+
78
+ #QA :name => ["foo", "bar"]
79
+
80
+ In the above example it hits the action 2 times with ":name => 'foo'" and ":name => 'bar'". Similarly To test a action for user logged in and
81
+ logged out add :user in parameters.
82
+
83
+ #QA :user => [:user, :admin, nil]
84
+
85
+ so the values are ':user' when normal user is logged in ':admin' when an administrator is logged in and 'nil' when user is not logged in.
86
+ To make this work add logic inside 'set_current_user_for_qa' filter in application_controller.rb, generated by ActsAsQa.
87
+
88
+ Add ':format' in parameters to test different formats of a action
89
+
90
+ #QA :format => ['js', 'json', 'xml']
91
+
92
+ Also to hit the action multiple times with different random data add '*repeat'. For example to repeat 3 times add '*3' at the end of parameters.
93
+
94
+ #QA :a => 'b', c => 'd' *3
95
+
96
+ Create Logged in user
97
+ ======================
98
+
99
+ (This step can be skipped initially)
100
+
101
+ To test the conditions when user is logged in a user must be set in session before hitting the desired action. To do so open
102
+ 'application_controller.rb' where following code is automatically generated by the gem:
103
+
104
+ #Generated by acts as qa
105
+ before_filter :set_current_user_for_qa
106
+
107
+ def set_current_user_for_qa
108
+ if Rails.env=='acts_as_qa'
109
+ #session[:user_id]=1
110
+ end
111
+ end
112
+
113
+ Add logic to create a user session before hitting the action. Modify this code according to functionality of user login. For example:
114
+
115
+ def set_current_user_for_qa
116
+ session[:user_id]=1 params[:user]=='admin'
117
+ session[:user_id]=2 params[:user]=='user'
118
+ end
119
+
120
+ or
121
+
122
+ def set_current_user_for_qa
123
+ session[:user]=User.find(1) params[:user]=='admin'
124
+ session[:user]=User.find(2) params[:user]=='user'
125
+ end
126
+
127
+ Where ':user_id' or ':user' should exist in database. Similarly if devise gem is used for authentication Add following line in the code:
128
+
129
+ session["warden.user.user.key"] = ["User", [15], "$2a$10$RSVEtVgr4UGwwnbGNPn9se"]
130
+
131
+ Initialize Database
132
+ ===================
133
+
134
+ WARNING : ActsAsQa can edit/delete/update records of database
135
+
136
+ As ActsAsQa can edit/delete/update records of database so there are two option to proceed.
137
+
138
+ OPTION 1:
139
+
140
+ + Take a dump of development database.
141
+ + Run server in 'development' environment.
142
+ + Run 'rake acts_as_qa:hit_paths[ROOT_URL,repeat]'
143
+ + Copy back the old database.
144
+
145
+ OPTION 2:
146
+
147
+ + 'rake acts_as_qa:setup' task creates 'acts_as_qa' environment and '{YOUR_APP_NAME}_acts_as_qa' database. Run
148
+ 'rake db:migrate RATLS_ENV=acts_as_qa'
149
+ + Add Records to '{YOUR_APP_NAME}_acts_as_qa' database by coping data from fixtures or development database
150
+ + Run server in 'acts_as_qa' environment
151
+ + Run 'rake acts_as_qa:hit_paths[ROOT_URL,repeat]'
152
+
153
+ Where ROOT_URL can be 'http://localhost:3000' and repeat is a integer 1,2,3.... Which is no of times a action should be hit by ActsAsQa.
154
+ If number of times to hit a action is already supplied in parameters (*3 or *4 in parameters) then it overwrites the 'repeat' for that action
155
+
156
+ Result
157
+ ========
158
+
159
+ Response from each action has the following format:
160
+
161
+ GET: /admin/lessons/:lesson_id/videos/new [OK] if parameters are {}
162
+ GET: /admin/lessons/:lesson_id/videos [OK] if parameters are {}
163
+ GET: /admin/lessons/:lesson_id/videos/11 [OK] if parameters are {:id=>11}
164
+ GET: /admin/lessons/:lesson_id/videos/112 [OK] if parameters are {:id=>112}
165
+ POST: /admin/lessons/:lesson_id/videos/sort [OK] if parameters are {}
166
+ GET: /annotations [NOTFOUND] if parameters are {}
167
+ GET: /users/confirmation/new [FAIL] FAILS WITH STATUS Net::HTTPBadGateway] if parameters are {}
168
+ POST: /users/confirmation [FAIL] FAILS WITH STATUS Net::HTTPBadGateway] if parameters are {}
169
+ GET: /users/confirmation [FAIL] FAILS WITH STATUS Net::HTTPBadGateway] if parameters are {:id=>""}
170
+ GET: /crib_sheets [NOTFOUND] if parameters are {}
171
+ GET: /crib_sheets/24 [NOTFOUND] if parameters are {:id=>24}
172
+ GET: /crib_sheets/16 [NOTFOUND] if parameters are {:id=>16}
173
+
174
+ Uninstall
175
+ ===========
176
+
177
+ To uninstall first run:
178
+
179
+ rake acts_as_qa:remove
180
+
181
+ This task removes all the parameters added in controller, 'acts_as_qa' environment and the filter added in application_controller.rb
182
+ Remove the following line in 'Gemfile'
183
+
184
+ gem 'acts_as_qa'
185
+
186
+ or remove the plugin from '/vendor/plugins/'
187
+
188
+ Note
189
+ ====
190
+
191
+ Add necessary logic in set_current_user_for_qa filter if server is in development mode as set_current_user_for_qa is a before filter it
192
+ overwrites the user session. One solution is to pass ":acts_as_qa => 'true'" in parameters and set user session only if 'params[:acts_as_qa]' is
193
+ true. So...
194
+
195
+ def set_current_user_for_qa
196
+ if params[:acts_as_qa]==true
197
+ session[:user_id]=1 params[:user]=='admin'
198
+ session[:user_id]=2 params[:user]=='user'
199
+ end
200
+ end
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the acts_as_qa plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the acts_as_qa plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'ActsAsQa'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
@@ -0,0 +1,31 @@
1
+ # ActsAsQa
2
+ require 'random_data'
3
+ require 'acts_as_qa/railtie'
4
+ require 'acts_as_qa/acts_as_qa'
5
+ require 'acts_as_qa/result'
6
+ require 'acts_as_qa/report'
7
+ require 'acts_as_qa/array'
8
+ require 'coverage'
9
+ require 'fileutils'
10
+ require 'erb'
11
+ require 'cgi'
12
+ require 'net/http'
13
+
14
+ def fetch_controllers
15
+ folder_name, controller_files = File.expand_path('controllers', "#{Rails.root}/app/"), []
16
+ inspect_directory(folder_name, controller_files)
17
+ controller_files.each_index{|i| controller_files[i]=controller_files[i].split('/controllers/').last}
18
+ controller_files
19
+ end
20
+
21
+ private
22
+
23
+ def inspect_directory(folder_name, controller_files)
24
+ directory = Dir.open(folder_name)
25
+ directory.each do |file_name|
26
+ inspect_directory(file_name, controller_files) if File.directory?(file_name) && file_name != "." && file_name != ".."
27
+ controller_files << folder_name+'/'+file_name if file_name.include?("_controller")
28
+ inspect_directory(folder_name+"/"+file_name, controller_files) if File.directory?(folder_name+"/"+file_name) and file_name != '.' and file_name != '..'
29
+ end
30
+ controller_files
31
+ end
@@ -0,0 +1,324 @@
1
+ module ActsAsQA
2
+ def self.included(klass)
3
+ klass.extend AAQA
4
+ end
5
+
6
+ class Generate
7
+
8
+ # Creates a list of parameters
9
+ def self.qa(params, repeat)
10
+ parameters, path_list = {}, []
11
+ params.each{|k, v| parameters[k.to_sym] = v}
12
+ parameters_multiply(path_list, parameters, repeat||1) #By default repeat is 1.
13
+ path_list
14
+ end
15
+
16
+ # Generates a list of actions with different combinations of values for parameters.
17
+ def self.parameters_multiply(path_list, parameters, repeat)
18
+ count=0
19
+ evaluate_object(parameters[:parameters])
20
+ # Generates 'repeat' no of values for each variable parameters. So there will be '(repeat)^(no of variable parameters)' no of combinations.
21
+ flag = self.multiply_all(count, path_list, parameters, repeat) unless count >= repeat
22
+ path_list << parameters if flag==0
23
+ end
24
+
25
+ # Generates different values for parameters.
26
+ # If a parameter is a symbol or an array then it will generate different values for parameters otherwise it will take the value of parameter as it is.
27
+ def self.multiply_all(count, path_list, parameters, repeat)
28
+ done, flag = [], 0
29
+ Hash[[parameters[:parameters].select{|k, v| v.class==Symbol or v.class==Array}.first]].each do |k, v|
30
+ flag=1
31
+ v.class==Symbol ? self.multiply_if_symbol(count, path_list, parameters, repeat, k, v, flag, done) : self.generate_if_array(path_list, repeat, k,v,parameters)
32
+ end
33
+ flag
34
+ end
35
+
36
+ def self.multiply_if_symbol(count, path_list, parameters, repeat, k, v, flag, done)
37
+ value = v.to_s.split('_').collect{|x| x.capitalize!}.join('')
38
+ # Check if the parameter is a model name or a datatype and generates the random value.
39
+ if self.datatypes.include?(v)
40
+ done, count = self.generate_if_datatype(path_list, repeat, parameters, done, count, k, v)
41
+ elsif (eval(value).descends_from_active_record? rescue false)
42
+ count = self.generate_if_active_record(path_list, repeat, parameters, count, k, v, value)
43
+ end
44
+ done, count = self.generate_random(path_list, repeat, parameters,count, done, k, v)
45
+ end
46
+
47
+ def self.generate_if_datatype(path_list, repeat, parameters, done, count, k, v)
48
+ list_value = parameters.dup
49
+ list_value[:parameters] = parameters[:parameters].dup
50
+ list_value[:parameters][k]=random_value(v)
51
+ parameters_multiply(path_list, list_value, repeat)
52
+ [done+[k], count+1]
53
+ end
54
+
55
+ def self.generate_if_active_record(path_list, repeat, parameters, count, k, v, value)
56
+ list_value = parameters.dup
57
+ list_value[:parameters] = parameters[:parameters].dup
58
+ value = eval(value)
59
+ list_value[:parameters][k]=(eval("#{value}.all.map(&:#{k.to_s})").rand rescue eval("#{value}.all.map(&:id)").rand)
60
+ parameters_multiply(path_list, list_value, repeat)
61
+ count+1
62
+ end
63
+
64
+ # Generates more random data based on the value of 'repeat'.
65
+ def self.generate_random(path_list, repeat, parameters,count, done, k, v)
66
+ (repeat-count).times do
67
+ dt = (self.datatypes-done).rand
68
+ done << dt
69
+ list_value = parameters.dup
70
+ list_value[:parameters] = parameters[:parameters].dup
71
+ list_value[:parameters][k]=random_value(dt)
72
+ count+=1
73
+ parameters_multiply(path_list, list_value, repeat)
74
+ end
75
+ [done, count]
76
+ end
77
+
78
+ # If parameter is an array then it will use one by one the value of array as parameter value.
79
+ def self.generate_if_array(path_list, repeat, k, v ,parameters)
80
+ v.each do |vc|
81
+ list_value = parameters.dup
82
+ list_value[:parameters] = parameters[:parameters].dup
83
+ list_value[:parameters][k] = parameters[:parameters][k].dup
84
+ list_value[:parameters][k]=vc ? vc.to_s : nil
85
+ parameters_multiply(path_list, list_value, repeat)
86
+ end
87
+ end
88
+
89
+ # Evaluates the object. So if it's written ':object => :user' then it will find a random user and replace object with its attributes.
90
+ # This way final result will be :id => 1, :name => 'Bob' ...
91
+ def self.evaluate_object(params)
92
+ if params[:object]
93
+ value = eval(params[:object].to_s.capitalize)
94
+ params.merge!(value.all.rand.attributes)
95
+ params.delete(:object)
96
+ end
97
+ params.each{|k, v| evaluate_object(v) if v.instance_of?(Hash) }
98
+ end
99
+
100
+ # Different datatypes which can be used as value for a parameter.
101
+ def self.datatypes
102
+ return [:boolean, :datetime, :decimal, :float, :integer, :string, :nil, :blank]
103
+ end
104
+
105
+ # Generates random values based on datatype/
106
+ def self.random_value(data_type)
107
+ case data_type
108
+ when :boolean
109
+ Random.boolean
110
+ when :date
111
+ Random.date
112
+ when :decimal
113
+ Random.number(100000)
114
+ when :integer
115
+ Random.number(100000)
116
+ when :float
117
+ rand
118
+ when :string
119
+ Random.alphanumeric
120
+ when :nil
121
+ nil
122
+ when :blank
123
+ ""
124
+ end
125
+ end
126
+ end
127
+
128
+ # Display the colored text.
129
+ class Display
130
+ def self.colorize(text, color_code)
131
+ "\e[#{color_code}m#{text}\e[0m"
132
+ end
133
+ end
134
+
135
+ module AAQA
136
+ @@result = {}
137
+
138
+ # Generates a routes file so that it can compare the routes with actual routes.
139
+ def generate_routes_file
140
+ home_directory = File.expand_path(".acts_as_qa", Rails.root)
141
+ unless Dir.exists?(home_directory)
142
+ status = Dir.mkdir('.acts_as_qa', 0777)
143
+ status == 0 ? puts("Home Directory created") : puts("Home Directory could not be created.")
144
+ else
145
+ puts "Home directory exists."
146
+ end
147
+ filename = File.expand_path('routes.txt', "#{Rails.root}/.acts_as_qa")
148
+ status=system("rake routes > #{filename}") ? puts('Routes Loaded') : puts("Something went wrong")
149
+ end
150
+
151
+ # Fetch the list of all the controllers in the application.
152
+ # def fetch_controllers
153
+ # folder_name, controller_files = File.expand_path('controllers', "#{Rails.root}/app/"), []
154
+ # inspect_directory(folder_name, controller_files)
155
+ # controller_files.each_index{|i| controller_files[i]=controller_files[i].split('/controllers/').last}
156
+ # controller_files
157
+ # end
158
+
159
+ # def inspect_directory(folder_name, controller_files)
160
+ # directory = Dir.open(folder_name)
161
+ # directory.each do |file_name|
162
+ # inspect_directory(file_name, controller_files) if File.directory?(file_name) && file_name != "." && file_name != ".."
163
+ # controller_files << folder_name+'/'+file_name if file_name.include?("_controller")
164
+ # inspect_directory(folder_name+"/"+file_name, controller_files) if File.directory?(folder_name+"/"+file_name) and file_name != '.' and file_name != '..'
165
+ # end
166
+ # controller_files
167
+ # end
168
+
169
+ # Fetch all the QA parameters defined in the controller and generates the path.
170
+ def fetch_controller_parameters
171
+ generate_routes_file
172
+ controller_files, paths_to_hit = fetch_controllers, []
173
+ controller_files.each do |file_name|
174
+ file, controller = File.expand_path(file_name, "#{Rails.root}/app/controllers"), file_name.split('_controller').first
175
+ paths_to_hit+=read_file_and_find_paths(file, controller)
176
+ end # end of controller_files iterator
177
+ paths_to_hit
178
+ end # end of method
179
+
180
+ def read_file_and_find_paths(file, controller)
181
+ paths_to_hit = []
182
+ File.open(file, 'r') do |f|
183
+ action=''
184
+ while(line = f.gets)
185
+ action = line.split('def').last.split(';').first.strip if line.include?('def')
186
+ if line.include?('#QA')
187
+ parameters, times = line.split('#QA ').last.strip.split('*')
188
+ paths_to_hit << "qa({:controller => '#{controller}', :action => '#{action}', :parameters => {#{parameters}}}, #{times||@@repeat_global})"
189
+ end
190
+ end # end of while
191
+ end # end of file open
192
+ paths_to_hit
193
+ end
194
+
195
+ # Finds the parameters and send the request and catch the request.
196
+ def hit_path(root_url, repeat_global)
197
+ @@repeat_global=repeat_global
198
+ puts "please enter root_url (example: http://localhost)" and return unless root_url
199
+ paths_to_hit = fetch_controller_parameters
200
+ paths_to_hit.each do |path|
201
+ begin
202
+ generate_parameters_and_hit_path(root_url, path)
203
+ rescue Exception => e
204
+ puts ActsAsQA::Display.colorize("Wrong parameters for #{path}. Error: #{e}", 31)
205
+ end
206
+ end # end of paths to hit
207
+ show_result
208
+ end
209
+
210
+ def generate_parameters_and_hit_path(root_url, path)
211
+ parameters_list = ActsAsQA::Generate.instance_eval(path.chomp)
212
+ parameters_list.each do |parameters|
213
+ validate_parameters_and_hit_path(parameters, root_url, path)
214
+ end
215
+ end
216
+
217
+ def validate_parameters_and_hit_path(parameters, root_url, path)
218
+ File.open("#{Rails.root}/.acts_as_qa/routes.txt", 'r') do |f|
219
+ path_details = []
220
+ while(line = f.gets)
221
+ path_details << line if (line.include?(":controller=>\"#{parameters[:controller]}\"") && line.include?(":action=>\"#{parameters[:action]}\""))
222
+ end # end of while
223
+ if path_details.empty?
224
+ display_error(path)
225
+ next
226
+ end
227
+ hit_valid_paths(path_details, parameters, root_url, path)
228
+ end# end of file open
229
+ end
230
+
231
+ def hit_valid_paths(path_details, parameters, root_url, path)
232
+ path_details.each do |path_detail|
233
+ path_specifications = path_detail.split().inspect unless path_detail.blank?
234
+ send_request(JSON.parse(path_specifications), parameters, root_url)
235
+ end
236
+ end
237
+
238
+ # Send the request
239
+ def send_request(specifications, parameters, root_url)
240
+ puts "please enter root_url (example: http://localhost)" and return unless root_url
241
+ method = (specifications.length <= 4 ? 'GET' : specifications[1])
242
+ response, path, p = get_response(specifications, parameters, root_url, method)
243
+ check_response(response, parameters, method, path, p)
244
+ end
245
+
246
+ def check_response(response, parameters, method, path, p)
247
+ if(response.class.ancestors.include?(Net::HTTPOK) || response.class.ancestors.include?(Net::HTTPFound))
248
+ request_add_to_result(parameters[:controller], parameters[:action], method, true)
249
+ puts(ActsAsQA::Display.colorize("#{method}: #{path} [OK] if parameters are #{p}", 32))
250
+ elsif(response.class.ancestors.include?(Net::HTTPNotFound))
251
+ request_add_to_result(parameters[:controller], parameters[:action], method, true)
252
+ puts(ActsAsQA::Display.colorize("#{method}: #{path} [NOTFOUND] if parameters are #{p}", 36))
253
+ else
254
+ request_add_to_result(parameters[:controller], parameters[:action], method, false)
255
+ puts(ActsAsQA::Display.colorize("#{method}: #{path} [FAIL] FAILS WITH STATUS #{response.class}] if parameters are #{p}", 31))
256
+ end
257
+ end
258
+
259
+ def get_response(specifications, parameters, root_url, method)
260
+ p = path = nil
261
+ specifications.length <= 4 ? path = specifications[1] : path = specifications[2]
262
+ p, data = (parameters[:parameters] || []), []
263
+ p.each{|k,v| path.match(":#{k}") ? (path.gsub!(":#{k}", v.to_s)) : data << "#{k}=#{v}"}
264
+ data, path = data.join('&'), path.split("(.:format")[0].gsub(/\(|\)/, '')
265
+ uri = URI.parse("#{root_url}#{path}")
266
+ http = Net::HTTP.new(uri.host, uri.port)
267
+ request = form_request(method, uri, p, data)
268
+ response = http.request(request)
269
+ [response, path, p]
270
+ end
271
+
272
+ def form_request(method, uri, p, data)
273
+ case method
274
+ when 'POST'
275
+ request = Net::HTTP::Post.new(uri.path)
276
+ request.set_form_data(p)
277
+ when 'PUT'
278
+ request = Net::HTTP::Put.new(uri.path)
279
+ request.set_form_data(p)
280
+ when 'GET'
281
+ request = Net::HTTP::Get.new(uri.path+"?"+data)
282
+ when 'DELETE'
283
+ request = Net::HTTP::Delete.new(uri.path+"?"+data)
284
+ end
285
+ request
286
+ end
287
+
288
+ # creates no of requests, pass/fail result set for all paths.
289
+ def request_add_to_result(controller, action, method, pass)
290
+ if !@@result[controller]
291
+ @@result.merge!({controller => {action => {method => {:requests => 1, :pass => (pass ? 1 : 0), :fail => (pass ? 0 : 1)}}}})
292
+ elsif !@@result[controller][action]
293
+ @@result[controller].merge!({action => {method => {:requests => 1, :pass => (pass ? 1 : 0), :fail => (pass ? 0 : 1)}}})
294
+ elsif !@@result[controller][action][method]
295
+ @@result[controller][action].merge!({method => {:requests => 1, :pass => (pass ? 1 : 0), :fail => (pass ? 0 : 1)}})
296
+ else
297
+ @@result[controller][action][method][:requests] += 1
298
+ @@result[controller][action][method][pass ? :pass : :fail] += 1
299
+ end
300
+ end
301
+
302
+ # Show the result.
303
+ def show_result
304
+ puts "-"*145+"\n Controller"+" "*40+"Action"+" "*24+"Method"+" "*14+"Total Requests"+" "*6+"Pass Requests"+" "*7+"Fail Requests\n"+"-"*145
305
+ total=pass=fail=0
306
+ @@result.each do |controller, x|
307
+ x.each do |action, y|
308
+ y.each do |method, z|
309
+ total+=z[:requests]
310
+ pass+=z[:pass]
311
+ fail+=z[:fail]
312
+ puts controller+" "*(50-controller.length)+action+" "*(30-action.length)+method+" "*(20-method.length)+z[:requests].to_s+" "*(20-z[:requests].to_s.length)+z[:pass].to_s+" "*(20-z[:pass].to_s.length)+z[:fail].to_s
313
+ end
314
+ end
315
+ end
316
+ puts "-"*145+"\n"+" "*100+total.to_s+" "*(20-total.to_s.length)+pass.to_s+" "*(20-pass.to_s.length)+fail.to_s+" "*(20-fail.to_s.length)+"\n"+"-"*145
317
+ end
318
+
319
+ # Error message if path doesn't exixt.
320
+ def display_error(path)
321
+ puts ActsAsQA::Display.colorize("PATH DOES NOT EXIST IN ROUTES #{path.inspect}", 31)
322
+ end
323
+ end
324
+ end
@@ -0,0 +1,16 @@
1
+ class Array
2
+
3
+ def aaq_sum
4
+ inject( nil ) { |sum,x| sum ? sum+x : x }
5
+ end
6
+
7
+ def aaq_percentage
8
+ return 100 if self.aaq_sum.nil?
9
+ self.aaq_sum*100/self.length
10
+ end
11
+
12
+ def aaq_avg
13
+ self.aaq_sum/self.length
14
+ end
15
+
16
+ end
@@ -0,0 +1,11 @@
1
+ require 'acts_as_qa'
2
+ module AAQA
3
+ if defined? Rails::Railtie
4
+ require 'rails'
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |rake| load rake }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ class Report
2
+ attr_accessor :name
3
+ attr_accessor :filename
4
+ attr_accessor :percentage
5
+ attr_accessor :coverage_report
6
+
7
+ def initialize(name, filename, coverage_report)
8
+ self.name=name
9
+ self.filename=filename
10
+ self.coverage_report=coverage_report
11
+ self.percentage=coverage_report.compact.aaq_percentage
12
+ end
13
+
14
+ def generate_html_report(coverage_dir)
15
+ FileUtils.mkpath(coverage_dir+"/"+self.name.split('/')[0..-2].join('/')) if self.name.split('/').length>1
16
+ file = File.new(coverage_dir+"/"+self.name+".html", "w+")
17
+ file.puts('<html><head><link href="'+ Result.css+'" media="screen" rel="stylesheet" type="text/css" /></head><body><h1>'+self.name+'</h1><div class="content">')
18
+ File.open(filename, 'r') do |f|
19
+ lines = f.readlines
20
+ lines.each_index do |i|
21
+ file.puts('<div class="covered_'+self.coverage_report[i].to_s+'"><pre><code>'+CGI::escapeHTML(lines[i])+'</code></pre></div>')
22
+ end
23
+ end
24
+ file.puts('</div></body></html>')
25
+ end
26
+
27
+ end
@@ -0,0 +1,69 @@
1
+ class Result
2
+ attr_accessor :controllers
3
+ attr_accessor :coverage_result
4
+ attr_accessor :coverage_dir
5
+ attr_accessor :root
6
+
7
+ def initialize(root)
8
+ self.root=root
9
+ c = fetch_controllers
10
+ c.each do |file|
11
+ require file
12
+ end
13
+ self.coverage_result=Coverage.result
14
+ self.coverage_dir=root+'/aaq_coverage'
15
+ self.find_controllers_with_percentage(c)
16
+ end
17
+
18
+ def find_controllers_with_percentage(c)
19
+ self.controllers=[]
20
+ self.coverage_result.each do |k,v|
21
+ controller=k.split('controllers/')[1]
22
+ if(c.include?(controller))
23
+ self.controllers.push(Report.new(controller, k, v))
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.show(root)
29
+ @result = Result.new(root)
30
+ @result.display_results
31
+ @result.open_result_page
32
+ end
33
+
34
+ def display_results
35
+ create_coverage_dir
36
+ generate_index_page
37
+ generate_result_pages
38
+ open_result_page
39
+ end
40
+
41
+ def create_coverage_dir
42
+ FileUtils.mkdir_p self.coverage_dir
43
+ end
44
+
45
+ def self.css
46
+ File.join(File.dirname(__FILE__), 'templates', 'coverage.css')
47
+ end
48
+
49
+ def generate_index_page
50
+ index = File.new(self.coverage_dir+"/index.html", "w+")
51
+ index.puts(self.template('index.html.erb').result(binding))
52
+ end
53
+
54
+ def generate_result_pages
55
+ self.controllers.each do |controller|
56
+ controller.generate_html_report(self.coverage_dir)
57
+ end
58
+ end
59
+
60
+ def template(file)
61
+ ERB.new(File.read(File.join(File.dirname(__FILE__), 'templates', file)))
62
+ end
63
+
64
+ def open_result_page
65
+ link=self.coverage_dir+"/index.html"
66
+ p link
67
+ system("start #{link}")
68
+ end
69
+ end
@@ -0,0 +1,10 @@
1
+ body{background-color: #FFC;color: white;}
2
+ h1, h2, h3, h4, h5{color: #006;margin-left:5%}
3
+ .green, .covered_1{background-color: #060;}
4
+ .red, .covered_0{background-color: #7d0000;}
5
+ a{text-decoration: none;color: white;}
6
+ pre{margin: 0;}
7
+ .content{margin:5%;background-color: #000000;color: white;}
8
+ table{width:100%}
9
+ table tr{}
10
+ table td{padding:5px 10px;}
@@ -0,0 +1,17 @@
1
+ <html>
2
+ <head>
3
+ <title>Acts As QA</title>
4
+ <link href="<%= Result.css %>" media="screen" rel="stylesheet" type="text/css" />
5
+ </head>
6
+ <body>
7
+ <h1>Acts As QA Coverage Report</h1>
8
+ <div class="content">
9
+ <table>
10
+ <tr class="total_coverage"><td>TOTAL COVERAGE</td><td><%= @controllers.collect(&:percentage).aaq_avg %>%</td></tr>
11
+ <% @controllers.each do |controller| %>
12
+ <tr class="<%= controller.percentage==100 ? 'green' : 'red' %>"><td><a href='<%= controller.name %>.html'><%= controller.name %>%</a></td><td><%= controller.percentage %></td></tr>
13
+ <% end %>
14
+ </table>
15
+ </div>
16
+ </body>
17
+ </html>
@@ -0,0 +1,155 @@
1
+ namespace :acts_as_qa do
2
+ desc "creates the first set of min max data for when the database is reloaded from scratch."
3
+ task :hit_paths, [:root_url,:repeat] => :environment do |t, args|
4
+ # Coverage.start
5
+ # require 'simplecov'
6
+ # p Rails.root.to_path+"app/controllers"
7
+ # SimpleCov.start do
8
+ # add_group "Controllers", Rails.root.to_path+"/app/controllers"
9
+ # end
10
+ ApplicationController.send :include, ActsAsQA
11
+ ApplicationController.hit_path(args[:root_url], args[:repeat])
12
+ # Result.show(Rails.root.to_path)
13
+ end
14
+
15
+ desc "Add parameters for each action"
16
+ task :setup, [:controller_name] => :environment do |t, args|
17
+ ApplicationController.send :include, ActsAsQA
18
+ controller_files = args[:controller_name] ? [args[:controller_name], "application_controller.rb"] : fetch_controllers
19
+ controller_files.each{|file_name| file_name.match('application_controller') ? add_filter : add_parameters(file_name)}
20
+ create_new_env
21
+ modify_database_yaml
22
+ system("rake db:create RAILS_ENV=acts_as_qa")
23
+ puts "========================================================================="
24
+ puts "Please follow the following instructions:"
25
+ puts " STEP 1: Modify parameters for each action."
26
+ puts " STEP 2: Modify 'set_current_user_for_qa' filter in application_controller.rb."
27
+ puts " STEP 3: Follow the one the following option:"
28
+ puts " OPTION 1:"
29
+ puts " STEP 3a: Take a dump of development datacase as acts_as_qa add/delete/update the records."
30
+ puts " STEP 3b: Run your server in development environment."
31
+ puts " STEP 3c: Run 'Rake acts_as_qa:hit_paths[http://localhost:3000]'."
32
+ puts " STEP 3d: Copy back the old database."
33
+ puts " OPTION2:"
34
+ puts " STEP 3a: If you don't want to modify your local database you can follow option 2. acts_as_qa environment and {YOUR_APP_NAME}_acts_as_qa database has already been created. Run rake db:migrate RATLS_ENV=acts_as_qa"
35
+ puts " STEP 3b: Add Records to {YOUR_APP_NAME}_acts_as_qa database by coping data from fixtures or development database"
36
+ puts " STEP 3c: Run your server in acts_as_qa environment"
37
+ puts " STEP 3d: Now Run 'Rake acts_as_qa:hit_paths[http://localhost:3000]'."
38
+ puts "=========================================================================="
39
+ end# end of task
40
+
41
+ desc "remove parameters at for each action"
42
+ task :remove => :environment do
43
+ system("rake db:drop RAILS_ENV=acts_as_qa")
44
+ File.delete("#{Rails.root}/db/data.yml") rescue nil
45
+ ApplicationController.send :include, ActsAsQA
46
+ controller_files = fetch_controllers
47
+ controller_files.each{|file_name| file_name.match('application_controller') ? remove_filter : remove_parameters(file_name)}
48
+ remove_env
49
+ remove_from_database
50
+ end
51
+
52
+ def create_new_env
53
+ unless File.exist?("#{Rails.root}/config/environments/acts_as_qa.rb")
54
+ acts_as_qa = File.new("#{Rails.root}/config/environments/acts_as_qa.rb", "w")
55
+ content = ""
56
+ File.open("#{Rails.root}/config/environments/development.rb", 'r') do |f|
57
+ while(line = f.gets)
58
+ content << line
59
+ content << "\n config.action_controller.allow_forgery_protection = false\n" if line.match('.configure')
60
+ end
61
+ end
62
+ File.open("#{Rails.root}/config/environments/acts_as_qa.rb", 'w'){|f| f.write(content)}
63
+ puts "New environment 'acts_as_qa' has been created"
64
+ end
65
+ end
66
+
67
+ def remove_env
68
+ File.delete("#{Rails.root}/config/environments/acts_as_qa.rb") rescue nil
69
+ end
70
+
71
+ def modify_database_yaml
72
+ content=""
73
+ db = YAML.load_file("#{Rails.root}/config/database.yml")
74
+ unless db["acts_as_qa"]
75
+ db["acts_as_qa"] = db["development"].dup
76
+ db["acts_as_qa"]["database"]=db["acts_as_qa"]["database"].split('_')[0..-2].join('_')+'_acts_as_qa'
77
+ File.open("#{Rails.root}/config/database.yml", 'w'){|f| f.write(db.to_yaml)}
78
+ end
79
+ end
80
+
81
+ def remove_from_database
82
+ db = YAML.load_file("#{Rails.root}/config/database.yml")
83
+ db.delete("acts_as_qa")
84
+ File.open("#{Rails.root}/config/database.yml", 'w'){|f| f.write(db.to_yaml)}
85
+ end
86
+
87
+ def add_filter
88
+ content = ""
89
+ file = File.expand_path('application_controller.rb', "#{Rails.root}/app/controllers")
90
+ File.open(file, 'r') do |f|
91
+ lines = f.readlines
92
+ unless lines.join.match('set_current_user_for_qa')
93
+ lines.each do |line|
94
+ content << line if line
95
+ content << "\n #Generated by acts as qa\n before_filter :set_current_user_for_qa\n\n def set_current_user_for_qa\n if Rails.env=='acts_as_qa'\n #session[:user_id]='1'\n end\n end\n\n" if line.include?('ApplicationController')
96
+ end # end of each
97
+ File.open(file, 'w'){|f| f.write(content)}
98
+ end#end of unless
99
+ end # end of file open
100
+ end
101
+
102
+ def remove_filter
103
+ file = File.expand_path('application_controller.rb', "#{Rails.root}/app/controllers")
104
+ flag=false
105
+ content=""
106
+ File.open(file, 'r') do |f|
107
+ while(line = f.gets)
108
+ flag=true if line.match('def set_current_user_for_qa')
109
+ content << line unless flag or line.match('before_filter :set_current_user_for_qa') or line.match('acts as qa')
110
+ flag = false if flag and line.match(/^ end/)
111
+ end # end of while
112
+ end # end of file open
113
+ File.open(file, 'w'){|f| f.write(content)}
114
+ end
115
+
116
+ def add_parameters(file_name)
117
+ content=""
118
+ file = File.expand_path(file_name, "#{Rails.root}/app/controllers")
119
+ File.open(file, 'r') do |f|
120
+ controller_name = file_name.split('_controller')[0]
121
+ controller = file_name.split('/').collect{|x| x.split('_').collect{|y| y.capitalize}.join('')}.join('::').split('.')[0]
122
+ model_name = controller_name.split('/').last.singularize
123
+ lines = f.readlines
124
+ content=add_qa_comments(lines, controller, model_name)
125
+ end # end of file open
126
+ File.open(file, 'w'){|f| f.write(content)}
127
+ end
128
+
129
+ def add_qa_comments(lines, controller, model_name)
130
+ content=""
131
+ lines.each_index do |i|
132
+ line = lines[i]
133
+ content << line
134
+ if line.include?('def') && !lines[i+1].include?('#QA')
135
+ action = line.split('def').last.split(';').first.strip
136
+ if eval(controller).public_instance_methods.include?(action.to_sym)
137
+ parameters = action.match(/edit|update|destroy|show/) ? ":id => :#{model_name}" : ''
138
+ content << "#{line.split('def')[0]} #QA #{parameters}\n"
139
+ end
140
+ end
141
+ end # end of each_index
142
+ content
143
+ end
144
+
145
+ def remove_parameters(file_name)
146
+ file = File.expand_path(file_name, "#{Rails.root}/app/controllers")
147
+ content = ""
148
+ File.open(file, 'r') do |f|
149
+ while(line = f.gets)
150
+ content << line unless line.match('#QA')
151
+ end # end of while
152
+ end # end of file open
153
+ File.open(file, 'w'){|f| f.write(content)}
154
+ end
155
+ end
@@ -0,0 +1,2 @@
1
+ # Include hook code here
2
+ require 'acts_as_qa'
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_qa
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - SapnaSolutions
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-04 00:00:00.000000000 +05:30
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: random_data
17
+ requirement: &2157566000 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2157566000
26
+ description: Check all the actions for all the controller of a Rails Application
27
+ email: contact@sapnasolutions.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - lib/acts_as_qa/acts_as_qa.rb
33
+ - lib/acts_as_qa/array.rb
34
+ - lib/acts_as_qa/railtie.rb
35
+ - lib/acts_as_qa/report.rb
36
+ - lib/acts_as_qa/result.rb
37
+ - lib/acts_as_qa/templates/coverage.css
38
+ - lib/acts_as_qa/templates/index.html.erb
39
+ - lib/acts_as_qa.rb
40
+ - lib/tasks/acts_as_qa.rake
41
+ - rails/init.rb
42
+ - Rakefile
43
+ - README.md
44
+ - MIT-LICENSE
45
+ has_rdoc: true
46
+ homepage:
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 1.6.2
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: ActsAsQa checks all the actions defined in the application and their responses.
70
+ It returns success if response is success, redirect or page not found otherwise
71
+ it returns false.
72
+ test_files: []