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