acts_as_qa 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +200 -0
- data/Rakefile +23 -0
- data/lib/acts_as_qa.rb +31 -0
- data/lib/acts_as_qa/acts_as_qa.rb +324 -0
- data/lib/acts_as_qa/array.rb +16 -0
- data/lib/acts_as_qa/railtie.rb +11 -0
- data/lib/acts_as_qa/report.rb +27 -0
- data/lib/acts_as_qa/result.rb +69 -0
- data/lib/acts_as_qa/templates/coverage.css +10 -0
- data/lib/acts_as_qa/templates/index.html.erb +17 -0
- data/lib/tasks/acts_as_qa.rake +155 -0
- data/rails/init.rb +2 -0
- metadata +72 -0
data/MIT-LICENSE
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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
|
data/lib/acts_as_qa.rb
ADDED
@@ -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,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
|
data/rails/init.rb
ADDED
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: []
|