assert_generator 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 65c081e83d976a9f0120deeedaa3d6ebb395784aa678d51cf12c5e81803a1baf
4
+ data.tar.gz: 6b3a772c932245b571b3dfdf1f22b49bfdb07f41faaa95f6860e54c5b4ace8a7
5
+ SHA512:
6
+ metadata.gz: 631a95c52aee8e6446ec26b808db9a98a7104a0ed78bebe5913a76df2331144d9b034941409ece16b7d78920c4ff2a31f572ddd2d104ea36b49df7e369df3a29
7
+ data.tar.gz: 6ee2a4b51a2ef2d86fc69ee0849a61294b81dbc601d67c1463970524c3c714e903a43395bdf2c85e5b3507117fcd9013f59085e8a284e0c334ee99b732aa104c
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module AssertGenerator
6
+ # Generate asserts based on some actual output from an object under test
7
+ # Outputs executable code to stdout with the assert statements, which can be pasted into the test
8
+ # The user needs to ensure that values are deterministic and do not change between test invocations
9
+ #
10
+ # @overload generate_asserts(source, source_expr)
11
+ # Generate asserts for a source object supplying an expression to access that object,
12
+ # e.g: `generate_asserts(res, 'res' )
13
+ # @param source [Object] an object to generate asserts that the object contains the values as recorded
14
+ # when this got called
15
+ # @param source_expr [String] the source expression that created the object, will be repeated into the asserts
16
+ #
17
+ # @overload generate_asserts { block }
18
+ # Generate asserts for a source object defined in a block - reflect the block to get the source to output
19
+ # to access the object
20
+ # @param relative_dates [String] adjust dates to be relative to the supplied date as a string expression
21
+ # - use with date dependent fixtures
22
+ # @yield a block which when evaluated returns the source object
23
+ #
24
+ def self.generate_asserts(source = nil, source_expr = nil, relative_dates: nil, &block)
25
+ AssertGenerator::Klass.new.send(:generate_asserts, source, source_expr, relative_dates, block)
26
+ end
27
+
28
+ class Klass
29
+ attr_accessor :relative_dates, :relative_date_today
30
+
31
+ def generate_asserts(source, source_expr, relative_dates, block)
32
+ if block
33
+ unless !defined?(Rails) || Rails.env.test?
34
+ raise 'AssertGenerator must only be used in the test context'
35
+ end
36
+
37
+ source_expr = block.call.to_s
38
+ # rubocop:disable Security/Eval
39
+ source ||= eval(source_expr, block.binding)
40
+ # rubocop:enable Security/Eval
41
+ end
42
+
43
+ unless source_expr
44
+ raise 'generate_asserts wants a source expression or a block'
45
+ end
46
+
47
+ if relative_dates
48
+ raise 'relative_dates needs block syntax' unless block
49
+
50
+ self.relative_dates = relative_dates
51
+ # rubocop:disable Security/Eval
52
+ self.relative_date_today = eval(relative_dates, block.binding)
53
+ # rubocop:enable Security/Eval
54
+ end
55
+
56
+ if source.is_a?(Hash)
57
+ generate_asserts_hash(source, source_expr)
58
+ return self
59
+ end
60
+
61
+ if defined?(ActiveRecord::Base) && source.is_a?(ActiveRecord::Base)
62
+ generate_asserts_ar(source, source_expr)
63
+ return self
64
+ end
65
+
66
+ if source.is_a?(Enumerable)
67
+ generate_asserts_enum(source, source_expr)
68
+ return self
69
+ end
70
+
71
+ generate_assert_drillable_item(source, ->(_c) { source_expr }, source)
72
+ self
73
+ end
74
+
75
+ def generate_asserts_ar(h, p)
76
+ h.attributes.each do |k, v|
77
+ generate_assert_drillable_item(v, ->(meth) { "#{p}.#{meth}" }, k)
78
+ end
79
+ end
80
+
81
+ def generate_asserts_hash(h, p)
82
+ h.each do |k, v|
83
+ generate_assert_drillable_item(v, ->(sym) { "#{p}[:#{sym}]" }, k)
84
+ end
85
+ end
86
+
87
+ def generate_asserts_enum(a, p)
88
+ generate_assert_drillable_item(a.count, ->(_c) { "#{p}.count" }, p)
89
+
90
+ a.each_with_index do |v, idx|
91
+ generate_assert_drillable_item(v, ->(index) { "#{p}[#{index}]" }, idx)
92
+ end
93
+ end
94
+
95
+ def generate_assert_drillable_item(v, make_accessor, *accessor_params)
96
+ accessor = make_accessor.call(*accessor_params)
97
+ if drillable_object(v)
98
+ generate_asserts(v, accessor, nil, nil)
99
+ else
100
+ if v.nil?
101
+ out "assert_nil #{accessor}"
102
+ elsif v.is_a?(true.class)
103
+ out "assert #{accessor}"
104
+ elsif v.is_a?(false.class)
105
+ out "refute #{accessor}"
106
+
107
+ elsif v.is_a?(DateTime) || (defined?(ActiveSupport::TimeWithZone) && v.is_a?(ActiveSupport::TimeWithZone))
108
+ generate_date_time_assert(v, accessor)
109
+ elsif v.is_a?(Date)
110
+ generate_date_assert(v, accessor)
111
+ else
112
+ out "assert_equal #{v.inspect}, #{make_accessor.call(*accessor_params)}"
113
+ end
114
+ end
115
+ end
116
+
117
+ def out(s)
118
+ puts(s)
119
+ end
120
+
121
+ def drillable_object(v)
122
+ v.is_a?(Enumerable) || (defined?(ActiveRecord::Base) && v.is_a?(ActiveRecord::Base))
123
+ end
124
+
125
+ def generate_date_assert(v, accessor)
126
+ if relative_dates
127
+ date_diff = v - relative_date_today
128
+ if date_diff.to_i == 0
129
+ out "assert_equal #{relative_dates}, #{accessor}"
130
+ else
131
+ out "assert_equal #{relative_dates} + #{date_diff}.days, #{accessor}"
132
+ end
133
+ else
134
+ out "assert_equal Date.new(#{v.year}, #{v.month}, #{v.day}), #{accessor}"
135
+ end
136
+ end
137
+
138
+ def generate_date_time_assert(v, accessor)
139
+ out "assert_equal DateTime.new(#{v.year}, #{v.month}, #{v.day}, " \
140
+ + "#{v.hour}, #{v.min}, #{v.sec}, '#{v.zone}'), #{accessor}"
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AssertGenerator
4
+ VERSION = '0.1.1'
5
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: assert_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Richard Parratt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.76'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.76'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.17'
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 0.17.1
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: '0.17'
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.17.1
117
+ description: |
118
+ Generate assert code from a result inside a unit or integration test.
119
+ This is useful if you have code that you've spiked or eyeballed as 'working' and you'd like to produce some assertions,
120
+ without editing the output of pretty-inspect manually or making it all up.
121
+ email:
122
+ - richard.parratt@sharesight.co.nz
123
+ executables: []
124
+ extensions: []
125
+ extra_rdoc_files: []
126
+ files:
127
+ - lib/assert_generator.rb
128
+ - lib/assert_generator/version.rb
129
+ homepage:
130
+ licenses:
131
+ - MIT
132
+ metadata:
133
+ source_code_uri: https://github.com/sharesight/assert_generator
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubygems_version: 3.0.3
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: An assert generating gem.
153
+ test_files: []