test_generator 1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e7909cf0b3c6a8fdf7e19e25ffd386e52ffdbce97924609d33d7c9b26046d6f9
4
+ data.tar.gz: 2a103ab5ac36e823cda0bd6d312523440765c8d0983a92d194e16e08e9ab3a0c
5
+ SHA512:
6
+ metadata.gz: 5421450d717d4fe6044cb9d2dbf79ab389e1a16322123d4c40fec91fe49e19155053acacf566beaf4929fd6e187f1a1ffc570d059551218476ff56a6dceac4a8
7
+ data.tar.gz: bbf3b9d80c25c4c69a85d991cb092401b1f415bf841fa9e56058bcafcb52367a661754e9cdf2c9f9482d25535e4d083897839e9d5c47bff971ace4f34896fbd6
data/lib/ext/string.rb ADDED
@@ -0,0 +1,47 @@
1
+ class String
2
+ # strings de cada classe de equivalência para testes
3
+ INT_STRING = "3"
4
+ EMAIL_STRING = "genaina@email.com"
5
+ FLOAT_STRING = "3.14"
6
+ PHONE_STRING = "(61) 98999-9999"
7
+ DATE_STRING = "12/01/1997"
8
+
9
+ CUSTOM_METHODS = %w(is_i? is_email? is_float? is_phone? is_date?)
10
+
11
+ EQUIVALENCE_CLASSES = {
12
+ "is_i?" => "INTEGER",
13
+ "is_email?" => "EMAIL",
14
+ "is_float?" => "FLOAT",
15
+ "is_phone?" => "PHONE",
16
+ "is_date?" => "DATE",
17
+ }
18
+
19
+ STRINGS_EQUIVALENCE_CLASSES = {
20
+ "is_i?" => String::INT_STRING,
21
+ "is_email?" => String::EMAIL_STRING,
22
+ "is_float?" => String::FLOAT_STRING,
23
+ "is_phone?" => String::PHONE_STRING,
24
+ "is_date?" => String::DATE_STRING,
25
+ }
26
+
27
+ def is_i?
28
+ /\A[-+]?\d+\z/ === self
29
+ end
30
+
31
+ def is_email?
32
+ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i === self
33
+ end
34
+
35
+ def is_float?
36
+ self.to_f.to_s === self
37
+ end
38
+
39
+ def is_phone?
40
+ /^\([1-9]{2}\) (?:[2-8]|9[1-9])[0-9]{3}\-[0-9]{4}$/ === self ||
41
+ /^\([1-9]{2}\)(?:[2-8]|9[1-9])[0-9]{3}\-[0-9]{4}$/ === self
42
+ end
43
+
44
+ def is_date?
45
+
46
+ end
47
+ end
@@ -0,0 +1,64 @@
1
+ require 'rails/generators/base'
2
+ class EquivalenceClassGenerator < Rails::Generators::Base
3
+ def create_equivalence_class_tests
4
+ require 'json'
5
+ require 'reflector'
6
+ class_name = args[0]
7
+ file_name = class_name.downcase
8
+ puts "criando testes unitarios para #{class_name}..."
9
+ is_controller = /.*Controller$/.match?(class_name)
10
+ class_type = "model"
11
+
12
+ template = %Q{require 'rails_helper'
13
+
14
+ RSpec.describe #{class_name}, :type => :#{class_type} do
15
+ }
16
+ equivalence_class_counter = {}
17
+ File.readlines("#{Rails.root}/tmp/#{class_name}.rb").each do |line|
18
+ json_string = JSON.parse(line.strip)
19
+ puts "\nReflecting..."
20
+ reflector = Reflect::Reflector.new
21
+ klass = json_string["klass"]
22
+ meth = json_string["method"]
23
+ cs = json_string["current_state"]
24
+ args = json_string["args"]
25
+ class_and_method_name = "#{klass}::#{meth}"
26
+
27
+ equivalence_class_counter[meth] ||= {}
28
+ args.each do |arg|
29
+ String::CUSTOM_METHODS.each do |equivalence_class_method|
30
+ respond_to_eq_class = arg.send(equivalence_class_method) # testa pra ver se responde à alguma classe de equivalencia
31
+ if respond_to_eq_class # se responder à classe, adiciona 1 ao contador daquela classe
32
+ if equivalence_class_counter[meth][equivalence_class_method].nil?
33
+ equivalence_class_counter[meth][equivalence_class_method] = 1
34
+ else
35
+ equivalence_class_counter[meth][equivalence_class_method] += 1
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ equivalence_class_counter.each do |method,stats| # pega o hash com os métodos e as estatísticas de cada
44
+ probabily_class = stats.max_by{|k,v| v}
45
+ template_aux = %Q{
46
+ describe '##{method}_equivalence_class' do
47
+ # #{probabily_class.last} entries with this class
48
+ it "arguments should belong to #{String::EQUIVALENCE_CLASSES[probabily_class.first]} equivalence class" do
49
+ expect(#{class_name.capitalize}).to receive(:#{method}).with("#{String::STRINGS_EQUIVALENCE_CLASSES[probabily_class.first]}")
50
+ User.find_by_email_address("#{String::STRINGS_EQUIVALENCE_CLASSES[probabily_class.first]}")
51
+ end
52
+ end
53
+ }
54
+ template.concat(template_aux)
55
+ end
56
+ puts equivalence_class_counter
57
+
58
+ template.concat(%Q{
59
+ end
60
+ })
61
+
62
+ create_file "spec/#{class_type}s/#{file_name}_equiv_spec.rb", template
63
+ end
64
+ end
@@ -0,0 +1,120 @@
1
+ require 'rails/generators/base'
2
+ class UnitTestGenerator < Rails::Generators::Base
3
+ def create_unit_tests
4
+ require 'json'
5
+ require 'reflector'
6
+ class_name = args[0]
7
+ file_name = class_name.downcase
8
+ puts "criando testes unitarios para #{class_name}..."
9
+ is_controller = /.*Controller$/.match?(class_name)
10
+ class_type = "model"
11
+ first_line = File.open("#{Rails.root}/tmp/#{class_name}.rb", &:readline)
12
+ sample_object = JSON.parse(first_line)["current_state"]
13
+
14
+ executed_methods = []
15
+ executed_arguments = {}
16
+ if is_controller
17
+ class_type = "controller"
18
+ template = %Q{require 'rails_helper'
19
+
20
+ RSpec.describe #{class_name}, :type => :#{class_type} do
21
+ }
22
+ File.readlines("#{Rails.root}/tmp/#{class_name}.rb").each do |line|
23
+ json_string = JSON.parse(line.strip)
24
+ puts "\nReflecting..."
25
+ reflector = Reflect::Reflector.new
26
+ klass = json_string["klass"]
27
+ meth = json_string["method"]
28
+ cs = json_string["current_state"]
29
+ args = json_string["args"]
30
+ class_and_method_name = "#{klass}::#{meth}"
31
+ if executed_methods.include?(class_and_method_name)
32
+ if executed_arguments[class_and_method_name.to_sym].include?(args)
33
+ # do nothing, same test
34
+ else
35
+ # same test with other arguments
36
+ executed_arguments[class_and_method_name.to_sym].push(args)
37
+ end
38
+ else # other test for other method
39
+ executed_methods.push(class_and_method_name)
40
+ executed_arguments[class_and_method_name.to_sym] = []
41
+ puts "Executando #{klass}::#{meth} com argumentos #{args} no objeto #{sample_object}"
42
+ reflection = reflector.reflect(klass, meth, sample_object, args)
43
+ puts "Resultado: #{reflection}"
44
+ print "\n"
45
+
46
+ template_aux = %Q{
47
+ describe 'GET #{meth}' do
48
+ it 'returns a successful response' do
49
+ get :#{meth}
50
+ expect(response).to be_successful
51
+ end
52
+
53
+ it 'renders the #{meth} template' do
54
+ get :#{meth}
55
+ expect(response).to render_template("#{meth}")
56
+ end
57
+ end
58
+ }
59
+ template.concat(template_aux)
60
+ end
61
+ end
62
+
63
+ template.concat(%Q{
64
+ end
65
+ })
66
+ else
67
+ template = %Q{require 'rails_helper'
68
+
69
+ RSpec.describe #{class_name}, :type => :#{class_type} do
70
+ let(:#{file_name}) { #{class_name}.new(#{sample_object}) }
71
+
72
+ it "is valid with valid attributes" do
73
+ expect(#{file_name}).to be_valid
74
+ end
75
+ }
76
+ File.readlines("#{Rails.root}/tmp/#{class_name}.rb").each do |line|
77
+ json_string = JSON.parse(line.strip)
78
+ puts "\nReflecting..."
79
+ reflector = Reflect::Reflector.new
80
+ klass = json_string["klass"]
81
+ meth = json_string["method"]
82
+ cs = json_string["current_state"]
83
+ args = json_string["args"]
84
+ class_and_method_name = "#{klass}::#{meth}"
85
+ if executed_methods.include?(class_and_method_name)
86
+ if executed_arguments[class_and_method_name.to_sym].include?(args)
87
+ # do nothing, same test
88
+ else
89
+ # same test with other arguments
90
+ executed_arguments[class_and_method_name.to_sym].push(args)
91
+ end
92
+ else # other test for other method
93
+ executed_methods.push(class_and_method_name)
94
+ executed_arguments[class_and_method_name.to_sym] = []
95
+ puts "Executando #{klass}::#{meth} com argumentos #{args} no objeto #{sample_object}"
96
+ reflection = reflector.reflect(klass, meth, sample_object, args)
97
+ puts "Resultado: #{reflection}"
98
+ print "\n"
99
+
100
+ template_aux = %Q{
101
+ describe '##{meth}' do
102
+ it "should return valid string for method #{meth}" do
103
+ expect(#{class_name.downcase}.#{meth}(#{args.join(', ')})).to eq "#{reflection}"
104
+ end
105
+ end
106
+ }
107
+ template.concat(template_aux)
108
+ end
109
+ end
110
+
111
+ template.concat(%Q{
112
+ end
113
+ })
114
+ end
115
+
116
+ create_file "spec/#{class_type}s/#{file_name.sub('controller', '_controller')}_spec.rb", template
117
+
118
+ puts "Testes criados."
119
+ end
120
+ end
data/lib/reflector.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Reflect
2
+ class Reflector
3
+ def reflect(klass, method, attributes, args)
4
+ if attributes.nil?
5
+ @instance = Object.const_get(klass).new
6
+ else
7
+ @instance = Object.const_get(klass).new(attributes)
8
+ end
9
+ if Object.const_get(klass).respond_to?(method) # class method
10
+ Object.const_get(klass).send(method, *args)
11
+ else
12
+ @instance.send(method, *args)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ require 'aquarium'
2
+ include Aquarium::Aspects
3
+
4
+ # Load Rails constants
5
+ Rails.application.eager_load!
6
+
7
+ # Get Rails models and controllers classes
8
+ controllers = ApplicationController.subclasses
9
+ models = ApplicationRecord.subclasses
10
+
11
+ puts "Aspects initialized"
12
+
13
+ Aspect.new(:around,
14
+ calls_to: :all_methods,
15
+ for_types: models + controllers,
16
+ method_options: [:exclude_ancestor_methods, :class]) do |jp, obj, *args|
17
+ begin
18
+ # Get class
19
+ klass = jp.target_type.name.constantize
20
+ # puts klass
21
+
22
+ # List all klass public instance methods
23
+ if models.include? klass
24
+ public_instance_methods = (klass.public_instance_methods - Object.public_instance_methods).sort
25
+ # puts public_instance_methods
26
+ end
27
+
28
+ # Get method
29
+ method = jp.method_name.to_sym
30
+ # puts method
31
+
32
+ # Get object current state
33
+ if models.include? klass
34
+ if obj.class == Class
35
+ else
36
+ current_state = obj.attributes
37
+ end
38
+ # puts current_state
39
+ end
40
+
41
+ # Create temp file
42
+ file_name ="#{Rails.root}/tmp/#{klass.to_s}.rb"
43
+
44
+ file = File.new(file_name, 'a')
45
+
46
+ str = "{ \"klass\": \"#{klass}\", \"method\": \"#{method}\", \"args\": #{args.inspect}, \"current_state\": #{current_state.to_json} }"
47
+
48
+ unless File.open(file_name).each_line.any? { |line| line.include?(str)}
49
+ file.puts str
50
+ end
51
+
52
+ jp.proceed
53
+ ensure
54
+ if file
55
+ file.close
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators/base'
2
+
3
+ module TestGenerator
4
+ class InstallGenerator < Rails::Generators::Base
5
+ desc "Creates a aspects initializer file."
6
+ def create_aspect_initialize_file
7
+ template = File.read('./templates/aspects.rb')
8
+ create_file "config/initializers/aspects.rb", template
9
+
10
+ puts "Aspects Initializer created."
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: test_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas Marques
8
+ - Rafael Fernandes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-07-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 3.2.0
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 3.2.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: cucumber-rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec-rails
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: aquarium
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: This gem will track everything users do in the system and map it into
71
+ controllers and model methods beeing called, and generate tests for them
72
+ email:
73
+ - nnmarques97@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - lib/ext/string.rb
79
+ - lib/generators/equivalence_class_generator.rb
80
+ - lib/generators/unit_test_generator.rb
81
+ - lib/reflector.rb
82
+ - lib/templates/aspects.rb
83
+ - lib/test_generator.rb
84
+ homepage: https://github.com/NickNish09/TestGenerator
85
+ licenses: []
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubygems_version: 3.0.6
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Auto generate tests based on system usage and BDD.
106
+ test_files: []