delta_test 0.1.0

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.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +4 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +165 -0
  8. data/Rakefile +17 -0
  9. data/bin/delta_test +12 -0
  10. data/circle.yml +12 -0
  11. data/delta_test.gemspec +30 -0
  12. data/lib/delta_test/analyzer.rb +47 -0
  13. data/lib/delta_test/cli.rb +224 -0
  14. data/lib/delta_test/configuration.rb +173 -0
  15. data/lib/delta_test/dependencies_table.rb +83 -0
  16. data/lib/delta_test/errors.rb +55 -0
  17. data/lib/delta_test/generator.rb +101 -0
  18. data/lib/delta_test/git.rb +88 -0
  19. data/lib/delta_test/related_spec_list.rb +64 -0
  20. data/lib/delta_test/spec_helpers.rb +42 -0
  21. data/lib/delta_test/utils.rb +93 -0
  22. data/lib/delta_test/version.rb +9 -0
  23. data/lib/delta_test.rb +47 -0
  24. data/spec/fixtures/sample/alpha.rb +19 -0
  25. data/spec/fixtures/sample/beta.rb +15 -0
  26. data/spec/fixtures/sample/gamma.rb +9 -0
  27. data/spec/lib/delta_test/analyzer_spec.rb +126 -0
  28. data/spec/lib/delta_test/cli_spec.rb +422 -0
  29. data/spec/lib/delta_test/configuration_spec.rb +353 -0
  30. data/spec/lib/delta_test/dependencies_table_spec.rb +129 -0
  31. data/spec/lib/delta_test/generator_spec.rb +201 -0
  32. data/spec/lib/delta_test/git_spec.rb +178 -0
  33. data/spec/lib/delta_test/related_spec_list_spec.rb +182 -0
  34. data/spec/lib/delta_test/spec_helpers_spec.rb +72 -0
  35. data/spec/lib/delta_test/utils_spec.rb +244 -0
  36. data/spec/lib/delta_test_spec.rb +119 -0
  37. data/spec/rails/.gitignore +19 -0
  38. data/spec/rails/.rspec +3 -0
  39. data/spec/rails/Gemfile +15 -0
  40. data/spec/rails/Gemfile.lock +163 -0
  41. data/spec/rails/README.rdoc +28 -0
  42. data/spec/rails/Rakefile +6 -0
  43. data/spec/rails/app/controllers/application_controller.rb +5 -0
  44. data/spec/rails/app/controllers/concerns/.keep +0 -0
  45. data/spec/rails/app/helpers/application_helper.rb +2 -0
  46. data/spec/rails/app/mailers/.keep +0 -0
  47. data/spec/rails/app/models/.keep +0 -0
  48. data/spec/rails/app/models/concerns/.keep +0 -0
  49. data/spec/rails/app/views/layouts/application.html.haml +7 -0
  50. data/spec/rails/bin/bundle +3 -0
  51. data/spec/rails/bin/rails +4 -0
  52. data/spec/rails/bin/rake +4 -0
  53. data/spec/rails/bin/setup +29 -0
  54. data/spec/rails/config/application.rb +35 -0
  55. data/spec/rails/config/boot.rb +3 -0
  56. data/spec/rails/config/database.yml +25 -0
  57. data/spec/rails/config/environment.rb +5 -0
  58. data/spec/rails/config/environments/development.rb +41 -0
  59. data/spec/rails/config/environments/production.rb +79 -0
  60. data/spec/rails/config/environments/test.rb +42 -0
  61. data/spec/rails/config/initializers/assets.rb +11 -0
  62. data/spec/rails/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/rails/config/initializers/cookies_serializer.rb +3 -0
  64. data/spec/rails/config/initializers/filter_parameter_logging.rb +4 -0
  65. data/spec/rails/config/initializers/inflections.rb +16 -0
  66. data/spec/rails/config/initializers/mime_types.rb +4 -0
  67. data/spec/rails/config/initializers/session_store.rb +3 -0
  68. data/spec/rails/config/initializers/wrap_parameters.rb +14 -0
  69. data/spec/rails/config/locales/en.yml +23 -0
  70. data/spec/rails/config/routes.rb +56 -0
  71. data/spec/rails/config/secrets.yml +22 -0
  72. data/spec/rails/config.ru +4 -0
  73. data/spec/rails/db/seeds.rb +7 -0
  74. data/spec/rails/delta_test.yml +5 -0
  75. data/spec/rails/lib/assets/.keep +0 -0
  76. data/spec/rails/lib/tasks/.keep +0 -0
  77. data/spec/rails/log/.keep +0 -0
  78. data/spec/rails/public/404.html +67 -0
  79. data/spec/rails/public/422.html +67 -0
  80. data/spec/rails/public/500.html +66 -0
  81. data/spec/rails/public/favicon.ico +0 -0
  82. data/spec/rails/public/robots.txt +5 -0
  83. data/spec/rails/spec/features/sample_spec.rb +7 -0
  84. data/spec/rails/spec/spec_helper.rb +16 -0
  85. data/spec/rails/vendor/assets/javascripts/.keep +0 -0
  86. data/spec/rails/vendor/assets/stylesheets/.keep +0 -0
  87. data/spec/spec_helper.rb +39 -0
  88. data/spec/supports/create_table_file.rb +21 -0
  89. metadata +283 -0
data/lib/delta_test.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'pathname'
2
+
3
+ require_relative 'delta_test/version'
4
+ require_relative 'delta_test/errors'
5
+ require_relative 'delta_test/configuration'
6
+
7
+ module DeltaTest
8
+
9
+ ACTIVE_FLAG = 'DELTA_TEST_ACTIVE'
10
+ VERBOSE_FLAG = 'DELTA_TEST_VERBOSE'
11
+
12
+ class << self
13
+
14
+ attr_reader :config
15
+
16
+ attr_writer *%i[
17
+ active
18
+ verbose
19
+ ]
20
+
21
+ def setup
22
+ @config = Configuration.new
23
+ @config.auto_configure! if active?
24
+ end
25
+
26
+ def configure(&block)
27
+ @config.update(&block)
28
+ end
29
+
30
+ def active?
31
+ return !!@active unless @active.nil?
32
+ @active = (!ENV[ACTIVE_FLAG].nil? && ENV[ACTIVE_FLAG] !~ /0|false/i)
33
+ end
34
+
35
+ def verbose?
36
+ return !!@verbose unless @verbose.nil?
37
+ @verbose = (!ENV[VERBOSE_FLAG].nil? && ENV[VERBOSE_FLAG] !~ /0|false/i)
38
+ end
39
+
40
+ def log(*args)
41
+ puts *args if verbose?
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+ DeltaTest.setup
@@ -0,0 +1,19 @@
1
+ require_relative "beta"
2
+
3
+ module Sample
4
+ class Alpha
5
+
6
+ def alpha
7
+ self
8
+ end
9
+
10
+ def beta
11
+ Beta.new.beta
12
+ end
13
+
14
+ def beta_gamma
15
+ beta.gamma
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "gamma"
2
+
3
+ module Sample
4
+ class Beta
5
+
6
+ def beta
7
+ self
8
+ end
9
+
10
+ def gamma
11
+ Gamma.new.gamma
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Sample
2
+ class Gamma
3
+
4
+ def gamma
5
+ self
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,126 @@
1
+ require 'delta_test/analyzer'
2
+
3
+ describe DeltaTest::Analyzer do
4
+
5
+ let(:analyzer) { DeltaTest::Analyzer.new }
6
+
7
+ after do
8
+ RubyProf.stop if RubyProf.running?
9
+ end
10
+
11
+ describe '#new' do
12
+
13
+ it 'should initialize new instance' do
14
+ expect { analyzer }.not_to raise_error
15
+ end
16
+
17
+ end
18
+
19
+ describe '#start' do
20
+
21
+ it 'should start ruby-prof' do
22
+ expect(RubyProf.running?).to be(false)
23
+
24
+ expect {
25
+ analyzer.start
26
+ }.not_to raise_error
27
+
28
+ expect(RubyProf.running?).to be(true)
29
+ end
30
+
31
+ end
32
+
33
+ describe '#stop' do
34
+
35
+ it 'should not raise error if `start` is not yet called' do
36
+ expect {
37
+ analyzer.stop
38
+ }.not_to raise_error
39
+ end
40
+
41
+ it 'should set result' do
42
+ analyzer.start
43
+
44
+ expect(analyzer.result).to be_nil
45
+
46
+ expect {
47
+ analyzer.stop
48
+ }.not_to raise_error
49
+
50
+ expect(analyzer.result).not_to be_nil
51
+ end
52
+
53
+ end
54
+
55
+ describe '#related_source_files' do
56
+
57
+ it 'should retrun nil if not yet started' do
58
+ expect(analyzer.related_source_files).to be_nil
59
+ end
60
+
61
+ it 'should return an empty set unless stop' do
62
+ analyzer.start
63
+ expect(analyzer.related_source_files).to be_empty
64
+ end
65
+
66
+ it 'should return a set of source files after stopped' do
67
+ analyzer.start
68
+ analyzer.stop
69
+ expect(analyzer.related_source_files).not_to be_empty
70
+ end
71
+
72
+ describe 'Source files' do
73
+
74
+ context 'Instantiated class in a file' do
75
+
76
+ it 'should not include the file' do
77
+ analyzer.start
78
+ Sample::Alpha.new
79
+ analyzer.stop
80
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/alpha.rb'))
81
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/beta.rb'))
82
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/gamma.rb'))
83
+ end
84
+
85
+ end
86
+
87
+ context 'Called some instance methods of a class in the file' do
88
+
89
+ it 'should include the file' do
90
+ analyzer.start
91
+ Sample::Alpha.new.alpha
92
+ analyzer.stop
93
+ expect(analyzer.related_source_files).to include(fixture_path('sample/alpha.rb'))
94
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/beta.rb'))
95
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/gamma.rb'))
96
+ end
97
+
98
+ end
99
+
100
+ context 'Called methods that uses extarnal classes' do
101
+
102
+ it 'should include a extarnal file' do
103
+ analyzer.start
104
+ Sample::Alpha.new.beta
105
+ analyzer.stop
106
+ expect(analyzer.related_source_files).to include(fixture_path('sample/alpha.rb'))
107
+ expect(analyzer.related_source_files).to include(fixture_path('sample/beta.rb'))
108
+ expect(analyzer.related_source_files).not_to include(fixture_path('sample/gamma.rb'))
109
+ end
110
+
111
+ it 'should include extarnal files even if nested' do
112
+ analyzer.start
113
+ Sample::Alpha.new.beta_gamma
114
+ analyzer.stop
115
+ expect(analyzer.related_source_files).to include(fixture_path('sample/alpha.rb'))
116
+ expect(analyzer.related_source_files).to include(fixture_path('sample/beta.rb'))
117
+ expect(analyzer.related_source_files).to include(fixture_path('sample/gamma.rb'))
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+
126
+ end
@@ -0,0 +1,422 @@
1
+ require 'delta_test/cli'
2
+ require 'delta_test/git'
3
+
4
+ describe DeltaTest::CLI do
5
+
6
+ let(:cli) { DeltaTest::CLI.new }
7
+
8
+ before do
9
+ DeltaTest::CLI.class_eval do
10
+ attr_writer :args
11
+ attr_writer :options
12
+ attr_writer :command
13
+ attr_reader :list
14
+ end
15
+
16
+ # ignore outputs
17
+ allow($stdout).to receive(:puts).with(any_args).and_return(nil)
18
+ allow($stderr).to receive(:puts).with(any_args).and_return(nil)
19
+ end
20
+
21
+ describe '#run' do
22
+
23
+ before do
24
+ allow(cli).to receive(:invoke).with(no_args).and_return(nil)
25
+ end
26
+
27
+ it 'should set the first argument as command' do
28
+ args = ['command', 'foo', 'bar']
29
+ cli.run(args)
30
+ expect(cli.command).to eq(args[0])
31
+ end
32
+
33
+ it 'should call `parse_options!` and `invoke`' do
34
+ expect(cli).to receive(:parse_options!).with(no_args).and_return({}).once.ordered
35
+ expect(cli).to receive(:invoke).with(no_args).once.ordered
36
+
37
+ args = ['command', 'foo', 'bar']
38
+ cli.run(args)
39
+ end
40
+
41
+ end
42
+
43
+ describe '#parse_options!' do
44
+
45
+ it 'should parse short options' do
46
+ cli.args = ['-a', '-b']
47
+
48
+ options = cli.parse_options!
49
+
50
+ expect(cli.args).to be_empty
51
+ expect(options).to be_a(Hash)
52
+ expect(options['a']).to be(true)
53
+ expect(options['b']).to be(true)
54
+ end
55
+
56
+ it 'should parse long options' do
57
+ cli.args = ['--long-a', '--long-b']
58
+
59
+ options = cli.parse_options!
60
+
61
+ expect(cli.args).to be_empty
62
+ expect(options).to be_a(Hash)
63
+ expect(options['long-a']).to be(true)
64
+ expect(options['long-b']).to be(true)
65
+ end
66
+
67
+ it 'should parse long options with value' do
68
+ cli.args = ['--long-a=value-of-a', '--long-b=value-of-b']
69
+
70
+ options = cli.parse_options!
71
+
72
+ expect(cli.args).to be_empty
73
+ expect(options).to be_a(Hash)
74
+ expect(options['long-a']).to eq('value-of-a')
75
+ expect(options['long-b']).to eq('value-of-b')
76
+ end
77
+
78
+ it 'should not parse options after once non-option args appears' do
79
+ cli.args = ['-a', '--long-a', 'non-option', '--long-b=value-of-b']
80
+
81
+ options = cli.parse_options!
82
+
83
+ expect(cli.args).to eq(['non-option', '--long-b=value-of-b'])
84
+ expect(options).to be_a(Hash)
85
+ expect(options['a']).to be(true)
86
+ expect(options['long-a']).to be(true)
87
+ expect(options['long-b']).to be_nil
88
+ end
89
+
90
+ describe 'Defaults' do
91
+
92
+ it 'should set default options' do
93
+ cli.args = []
94
+
95
+ options = cli.parse_options!
96
+
97
+ expect(options).to be_a(Hash)
98
+
99
+ expect(options['base']).to eq('master')
100
+ expect(options['head']).to eq('HEAD')
101
+ end
102
+
103
+ it 'should be able to overwrite default options' do
104
+ cli.args = ['--base=develop', '--head=feature/foo']
105
+
106
+ options = cli.parse_options!
107
+
108
+ expect(options).to be_a(Hash)
109
+
110
+ expect(options['base']).to eq('develop')
111
+ expect(options['head']).to eq('feature/foo')
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+
118
+ describe '#exit_with_message' do
119
+
120
+ let(:message) { 'a message' }
121
+ let(:message_regexp) { /a message/ }
122
+
123
+ context 'With status code of zero' do
124
+
125
+ let(:status) { 0 }
126
+
127
+ it 'should print a message to stdout and exit' do
128
+ expect {
129
+ begin
130
+ cli.exit_with_message(status, message)
131
+ rescue SystemExit => e
132
+ expect(e.status).to eq(status)
133
+ end
134
+ }.to output(message_regexp).to_stdout
135
+ end
136
+
137
+ end
138
+
139
+ context 'With status code of non-zero' do
140
+
141
+ let(:status) { 1 }
142
+
143
+ it 'should print a message to stderr and exit' do
144
+ expect {
145
+ begin
146
+ cli.exit_with_message(status, message)
147
+ rescue SystemExit => e
148
+ expect(e.status).to eq(status)
149
+ end
150
+ }.to output(message_regexp).to_stderr
151
+ end
152
+
153
+ end
154
+
155
+ end
156
+
157
+ describe '#run_full_tests?' do
158
+
159
+ let(:map) do
160
+ {
161
+ 'master' => '0000000000000000000000000000000000000000',
162
+ 'feature/foo' => '1111111111111111111111111111111111111111',
163
+ }
164
+ end
165
+
166
+ before do
167
+ map.each do |name, commit_id|
168
+ allow(DeltaTest::Git).to receive(:rev_parse).with(name).and_return(commit_id)
169
+ end
170
+ end
171
+
172
+ context 'When base and head is the same commit' do
173
+
174
+ before do
175
+ cli.options = {
176
+ 'base' => 'master',
177
+ 'head' => 'master',
178
+ }
179
+ end
180
+
181
+ it 'should return true' do
182
+ expect(cli.run_full_tests?).to be(true)
183
+ end
184
+
185
+ end
186
+
187
+ context 'When base and head is a different commit' do
188
+
189
+ before do
190
+ cli.options = {
191
+ 'base' => 'master',
192
+ 'head' => 'feature/foo',
193
+ }
194
+ end
195
+
196
+ it 'should return false' do
197
+ expect(cli.run_full_tests?).to be(false)
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+
204
+ context 'Commands' do
205
+
206
+ describe '#do_table' do
207
+
208
+ let(:table) do
209
+ {
210
+ 'spec/foo_spec.rb' => ['lib/foo.rb']
211
+ }
212
+ end
213
+
214
+ before do
215
+ allow(cli).to receive(:invoke).with(no_args).and_return(nil)
216
+
217
+ cli.run([])
218
+
219
+ allow(cli.list).to receive(:load_table!).with(no_args).and_return(nil)
220
+ allow(cli.list).to receive(:table).with(no_args).and_return(table)
221
+ end
222
+
223
+ it 'should load a table file' do
224
+ expect(cli.list).to receive(:load_table!).with(no_args).once.ordered
225
+ expect(cli.list).to receive(:table).with(no_args).once.ordered
226
+
227
+ expect {
228
+ cli.do_table
229
+ }.not_to raise_error
230
+ end
231
+
232
+ it 'should show the table contents' do
233
+ expect(cli.list).to receive(:load_table!).with(no_args).once.ordered
234
+ expect(cli.list).to receive(:table).with(no_args).once.ordered
235
+
236
+ expect {
237
+ cli.do_table
238
+ }.to output(/foo_spec\.rb/).to_stdout
239
+ end
240
+
241
+ end
242
+
243
+ describe '#do_list' do
244
+
245
+ let(:related_spec_files) do
246
+ [
247
+ 'spec/foo_spec.rb',
248
+ ]
249
+ end
250
+
251
+ before do
252
+ allow(cli).to receive(:invoke).with(no_args).and_return(nil)
253
+
254
+ cli.run([])
255
+
256
+ allow(cli.list).to receive(:load_table!).with(no_args).and_return(nil)
257
+ allow(cli.list).to receive(:retrive_changed_files!).with(any_args).and_return(nil)
258
+ allow(cli.list).to receive(:related_spec_files).with(no_args).and_return(related_spec_files)
259
+ end
260
+
261
+ it 'should load a table file and retrive changed files' do
262
+ expect(cli.list).to receive(:load_table!).with(no_args).once.ordered
263
+ expect(cli.list).to receive(:retrive_changed_files!).with(any_args).once.ordered
264
+
265
+ expect {
266
+ cli.do_list
267
+ }.not_to raise_error
268
+ end
269
+
270
+ it 'should show a list of related spec files' do
271
+ expect(cli.list).to receive(:load_table!).with(no_args).once.ordered
272
+ expect(cli.list).to receive(:retrive_changed_files!).with(any_args).once.ordered
273
+ expect(cli.list).to receive(:related_spec_files).with(no_args).once.ordered
274
+
275
+ expect {
276
+ cli.do_list
277
+ }.to output(/foo_spec\.rb/).to_stdout
278
+ end
279
+
280
+ end
281
+
282
+ describe '#do_exec' do
283
+
284
+ let(:args) do
285
+ ['exec', 'bundle', 'exec', 'rspec']
286
+ end
287
+
288
+ let(:related_spec_files) do
289
+ [
290
+ 'spec/foo_spec.rb',
291
+ ]
292
+ end
293
+
294
+ before do
295
+ allow(cli).to receive(:invoke).with(no_args).and_return(nil)
296
+
297
+ cli.run(args)
298
+
299
+ allow(cli.list).to receive(:load_table!).with(no_args).and_return(nil)
300
+ allow(cli.list).to receive(:retrive_changed_files!).with(any_args).and_return(nil)
301
+ allow(cli.list).to receive(:related_spec_files).with(no_args).and_return(related_spec_files)
302
+
303
+ allow(Open3).to receive(:popen3).with(any_args).and_return(nil)
304
+ end
305
+
306
+ context 'Full tests' do
307
+
308
+ before do
309
+ expect(cli).to receive(:run_full_tests?).with(no_args).and_return(true)
310
+ end
311
+
312
+ it 'should run script with a flag' do
313
+ expect(cli.list).not_to receive(:related_spec_files).with(no_args)
314
+
315
+ _args = ['%s=%s' % [DeltaTest::ACTIVE_FLAG, true], *args[1..-1]].join(' ')
316
+ expect(Open3).to receive(:popen3).with(_args)
317
+
318
+ expect {
319
+ cli.do_exec
320
+ }.not_to raise_error
321
+ end
322
+
323
+ end
324
+
325
+ context 'Partial tests' do
326
+
327
+ before do
328
+ expect(cli).to receive(:run_full_tests?).with(no_args).and_return(false)
329
+ end
330
+
331
+ context 'Any related files' do
332
+
333
+ it 'should run script with related spec files' do
334
+ expect(cli.list).to receive(:related_spec_files).with(no_args)
335
+
336
+ _args = ['cat', '|', 'xargs', *args[1..-1]].join(' ')
337
+ expect(Open3).to receive(:popen3).with(_args)
338
+
339
+ expect {
340
+ cli.do_exec
341
+ }.not_to raise_error
342
+ end
343
+
344
+ end
345
+
346
+ context 'No related files' do
347
+
348
+ let(:related_spec_files) { [] }
349
+
350
+ it 'should not run script and exit with a message' do
351
+ expect(cli.list).to receive(:related_spec_files).with(no_args)
352
+
353
+ expect {
354
+ begin
355
+ cli.do_exec
356
+ rescue SystemExit => e
357
+ expect(e.status).to eq(0)
358
+ end
359
+ }.to output(/Nothing/).to_stdout
360
+ end
361
+
362
+ end
363
+
364
+ end
365
+
366
+ end
367
+
368
+ describe '#do_help' do
369
+
370
+ it 'should print help' do
371
+ expect {
372
+ cli.do_help
373
+ }.to output(/usage/).to_stdout
374
+ end
375
+
376
+ end
377
+
378
+ describe '#do_version' do
379
+
380
+ it 'should print gem version' do
381
+ expect {
382
+ cli.do_version
383
+ }.to output(/v\d+\.\d+.\d+/).to_stdout
384
+ end
385
+
386
+ end
387
+
388
+ end
389
+
390
+ describe '#invoke' do
391
+
392
+ let(:commands) do
393
+ {
394
+ 'list' => 'do_list',
395
+ 'table' => 'do_table',
396
+ 'exec' => 'do_exec',
397
+ 'help' => 'do_help',
398
+ '-v' => 'do_version',
399
+ }
400
+ end
401
+
402
+ before do
403
+ commands.each do |_, action|
404
+ allow(cli).to receive(action).with(no_args).and_return(nil)
405
+ end
406
+ end
407
+
408
+ it 'should invoke method for a command' do
409
+ commands.each do |command, action|
410
+ expect(cli).to receive(action).with(no_args)
411
+
412
+ cli.command = command
413
+
414
+ expect {
415
+ cli.invoke
416
+ }.not_to raise_error
417
+ end
418
+ end
419
+
420
+ end
421
+
422
+ end