acts_as_qa 1.0.8

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,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: []