delta_test 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +22 -34
  4. data/Rakefile +5 -2
  5. data/bin/delta_test +1 -1
  6. data/circle.yml +5 -1
  7. data/delta_test.gemspec +1 -1
  8. data/lib/delta_test/cli/command_base.rb +114 -0
  9. data/lib/delta_test/cli/exec_command.rb +95 -0
  10. data/lib/delta_test/cli/help_command.rb +38 -0
  11. data/lib/delta_test/cli/specs_command.rb +43 -0
  12. data/lib/delta_test/cli/stats_clean_command.rb +20 -0
  13. data/lib/delta_test/cli/stats_save_command.rb +67 -0
  14. data/lib/delta_test/cli/stats_show_command.rb +46 -0
  15. data/lib/delta_test/cli/version_command.rb +13 -0
  16. data/lib/delta_test/cli.rb +22 -296
  17. data/lib/delta_test/configuration.rb +57 -42
  18. data/lib/delta_test/errors.rb +24 -0
  19. data/lib/delta_test/generator.rb +4 -24
  20. data/lib/delta_test/git.rb +161 -80
  21. data/lib/delta_test/profiler.rb +8 -0
  22. data/lib/delta_test/related_spec_list.rb +14 -9
  23. data/lib/delta_test/stats.rb +41 -0
  24. data/lib/delta_test/version.rb +2 -2
  25. data/lib/delta_test.rb +14 -9
  26. data/spec/lib/delta_test/cli/command_base_spec.rb +164 -0
  27. data/spec/lib/delta_test/cli/exec_command_spec.rb +128 -0
  28. data/spec/lib/delta_test/cli/help_command_spec.rb +17 -0
  29. data/spec/lib/delta_test/cli/specs_command_spec.rb +54 -0
  30. data/spec/lib/delta_test/cli/stats_clean_command_spec.rb +39 -0
  31. data/spec/lib/delta_test/cli/stats_save_command_spec.rb +207 -0
  32. data/spec/lib/delta_test/cli/stats_show_command_spec.rb +52 -0
  33. data/spec/lib/delta_test/cli/version_command_spec.rb +17 -0
  34. data/spec/lib/delta_test/cli_spec.rb +47 -386
  35. data/spec/lib/delta_test/configuration_spec.rb +99 -47
  36. data/spec/lib/delta_test/dependencies_table_spec.rb +1 -1
  37. data/spec/lib/delta_test/generator_spec.rb +3 -3
  38. data/spec/lib/delta_test/git_spec.rb +291 -50
  39. data/spec/lib/delta_test/profiler_spec.rb +3 -3
  40. data/spec/lib/delta_test/related_spec_list_spec.rb +12 -14
  41. data/spec/lib/delta_test/stats_spec.rb +89 -0
  42. data/spec/lib/delta_test/utils_spec.rb +4 -4
  43. data/spec/lib/delta_test_spec.rb +13 -4
  44. data/spec/rails/Gemfile.lock +5 -2
  45. data/spec/rails/app/models/category.rb +4 -0
  46. data/spec/rails/delta_test.yml +4 -3
  47. data/spec/rails/spec/models/category_spec.rb +4 -0
  48. data/spec/spec_helper.rb +9 -2
  49. data/spec/supports/create_table_file.rb +11 -1
  50. data/visual.jpg +0 -0
  51. metadata +32 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 94f59b2f95b133bb72a50361d428a93ac6f62c23
4
- data.tar.gz: 97c3fee8fcbafa082f24e21bfcb8aada5d251834
3
+ metadata.gz: 0ba461c2b9065403b53937eb258a5ea5849109c6
4
+ data.tar.gz: db45db67cd4da906b56449943c1b2fc4cf4d485e
5
5
  SHA512:
6
- metadata.gz: 639090edc53958e9aa7ced6cd476d1c5f974c4e1a6e84ec92bdfebace65d12f9e444535cdffb9145d2edc775d8cd6b46f42ea7807d0119d001d22fd875f11aaa
7
- data.tar.gz: 3383686308e0d32881943b213a33b86adc4bbff700275c2a24f9ec97a9e3b03e490af7ddebbc41d7f28f81564813ae4be5e00582d77b58034af6839c5880e8b0
6
+ metadata.gz: b02c8a6c10ccc5306dff37b8033f6cf523a06eee8a83e34937da8e423c71ab3ff009157766a13d45e8aab5d9eb01cfe1f8f298d810702f9d26dd0424d53849ee
7
+ data.tar.gz: 842057a457c81171430e51a5409fdbe8564b152c31ae2c746e82d500e7ea8b8610156f8352036170b811d48792ae9f442fbf354009432edca975339c1f767467
data/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ master
7
7
  N/A
8
8
 
9
9
 
10
+ 1.0.0
11
+ -----
12
+
13
+ - [feature] #25 Versioning table files. Including many refactorings and bug fixes
14
+
15
+
10
16
  0.2.0
11
17
  -----
12
18
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- :warning: **currently in development**
1
+ ![delta test](./visual.jpg)
2
2
 
3
3
  delta_test
4
4
  ==========
@@ -24,7 +24,7 @@ Setup
24
24
  Add this line to your Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'delta_test', group: :test
27
+ gem 'delta_test'
28
28
  ```
29
29
 
30
30
  ### Configuration
@@ -60,19 +60,12 @@ end
60
60
  Usage
61
61
  -----
62
62
 
63
- For the first time and whenever on master, it'll run full test cases to create **dependencies table**:
64
-
65
- ```bash
66
- $ git checkout master
67
- $ delta_test exec rspec
68
- ```
69
-
70
- And on other branch, it'll run only related tests for your changes from master:
71
-
72
63
  ```bash
73
- $ git checkout -b feature/something_awesome
74
- $ # Make changes & create commits...
75
- $ delta_test exec rspec
64
+ $ git clone git@example.com:sample/sample_stats.git tmp/delta_test_stats
65
+ $ delta_test stats:clean
66
+ $ delta_test exec rspec spec/models
67
+ $ delta_test exec rspec spec/controllers
68
+ $ delta_test stats:save
76
69
  ```
77
70
 
78
71
 
@@ -82,34 +75,28 @@ Advanced usage
82
75
  ### Command
83
76
 
84
77
  ```
85
- usage: delta_test <command> [--base=<base>] [--head=<head>] [--verbose] [<args>]
86
- [-v|--version]
78
+ usage: delta_test <command> [--verbose] [<args>]
87
79
 
88
80
  options:
89
- --base=<base> A branch or a commit id to diff from.
90
- <head> is default to master.
81
+ --verbose Print more output.
91
82
 
92
- --head=<head> A branch or a commit id to diff to.
93
- <head> is default to HEAD. (current branch you're on)
83
+ commands:
84
+ exec [--force-run] <script> -- <files...>
85
+ Execute test script using delta_test.
86
+ --force-run to force DeltaTest to run full test cases.
94
87
 
95
- --verbose Print more output.
88
+ specs List related spec files for changes.
96
89
 
97
- -v, --version Show version.
90
+ stats:clean Clean up temporary files.
98
91
 
99
- commands:
100
- list List related spec files for changes between base and head.
101
- head is default to master; base is to the current branch.
92
+ stats:show Show dependencies table.
102
93
 
103
- table Show dependencies table.
94
+ stats:save [--no-sync]
95
+ Save and sync a table file.
104
96
 
105
- exec <script> [-- <files>]
106
- Execute test script using delta_test.
107
- if <base> and <head> is the same commit or no dependencies table is found,
108
- it'll run full test cases with a profile mode to create a table.
109
- Otherwise, it'll run test script with only related spec files
110
- passed by its arguments, like `delta_test list | xargs script'.
97
+ version Show version.
111
98
 
112
- clear Clean up tables and caches.
99
+ help Show this.
113
100
  ```
114
101
 
115
102
  #### `exec` example
@@ -147,7 +134,8 @@ $ bundle exec delta_test exec parallel_test -t rspec -n 4 -- spec/features
147
134
  ### Configurations
148
135
 
149
136
  ```yaml
150
- table_file: tmp/.delta_test_dt
137
+ stats_path: tmp/delta_test_stats
138
+ stats_life: 1000
151
139
 
152
140
  patterns:
153
141
  - lib/**/*.rb
data/Rakefile CHANGED
@@ -21,8 +21,11 @@ namespace :rails do
21
21
  desc 'Run rails tests'
22
22
  task :test do
23
23
  Bundler.with_clean_env do
24
- s = system('cd spec/rails && DELTA_TEST_ACTIVE=true DELTA_TEST_VERBOSE=true bundle exec rspec')
25
- exit $? unless s
24
+ s = system('cd spec/rails && bundle exec delta_test stats:clean')
25
+ s &&= system('cd spec/rails && bundle exec delta_test exec --verbose rspec --tty')
26
+ s &&= system('cd spec/rails && bundle exec delta_test stats:save --no-sync')
27
+ s &&= system('cd spec/rails && bundle exec delta_test stats:show')
28
+ exit $?.exitstatus unless s
26
29
  end
27
30
  end
28
31
  end
data/bin/delta_test CHANGED
@@ -9,4 +9,4 @@ require 'delta_test/cli'
9
9
 
10
10
  DeltaTest.config.auto_configure!
11
11
 
12
- DeltaTest::CLI.new.run(ARGV)
12
+ DeltaTest::CLI.new(ARGV).run
data/circle.yml CHANGED
@@ -5,9 +5,13 @@ machine:
5
5
  dependencies:
6
6
  cache_directories:
7
7
  - spec/rails/vendor/bundle
8
+ pre:
9
+ - git config --global user.email 'yuki@creasty.com'
10
+ - git config --global user.name 'Yuki Iwanaga'
8
11
  post:
9
- - cd spec/rails && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3)
10
12
  - bundle exec rake compile
13
+ - cd spec/rails && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3)
14
+ - cd spec/rails && git clone git@github.com:creasty/delta_test_stats_sample.git tmp/delta_test_stats
11
15
 
12
16
  database:
13
17
  override:
data/delta_test.gemspec CHANGED
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'pry'
28
28
  spec.add_development_dependency 'rake', '~> 10.0'
29
29
  spec.add_development_dependency 'rake-compiler'
30
- spec.add_development_dependency 'rspec', '>= 3.0'
30
+ spec.add_development_dependency 'rspec', '>= 3.4'
31
31
  end
@@ -0,0 +1,114 @@
1
+ require 'open3'
2
+ require 'shellwords'
3
+ require 'thread'
4
+ require 'thwait'
5
+
6
+ module DeltaTest
7
+ class CLI
8
+ class CommandBase
9
+
10
+ DEFAULT_OPTIONS = {
11
+ 'verbose' => false,
12
+ 'force-run' => false,
13
+ 'no-sync' => false,
14
+ }.freeze
15
+
16
+ attr_reader(*%i[
17
+ args
18
+ options
19
+ ])
20
+
21
+ def initialize(args)
22
+ @args = args.dup
23
+ @options = parse_options!(@args)
24
+
25
+ DeltaTest.verbose = !!@options['verbose']
26
+ end
27
+
28
+ def invoke!
29
+ raise 'Not implemented'
30
+ end
31
+
32
+ def invoke
33
+ begin
34
+ invoke!
35
+ rescue => e
36
+ if DeltaTest.verbose?
37
+ raise e
38
+ else
39
+ exit_with_message(1, '[%s] %s' % [e.class.name, e.message])
40
+ end
41
+ end
42
+ end
43
+
44
+ ###
45
+ # Parse option arguments
46
+ #
47
+ # @return {Hash<String, Boolean|String>}
48
+ ###
49
+ def parse_options!(args)
50
+ options = {}
51
+
52
+ args.reject! do |arg|
53
+ case arg
54
+ when /^-([a-z0-9])$/i, /^--([a-z0-9][a-z0-9-]*)$/i
55
+ options[$1] = true
56
+ when /^--([a-z0-9][a-z0-9-]*)=(.+)$/i
57
+ options[$1] = $2
58
+ else
59
+ break
60
+ end
61
+ end
62
+
63
+ DEFAULT_OPTIONS.merge(options)
64
+ end
65
+
66
+ ###
67
+ # Print message and exit with a status
68
+ #
69
+ # @params {Integer} status - exit code
70
+ # @params {Object} *args
71
+ ###
72
+ def exit_with_message(status, *args)
73
+ if status.zero?
74
+ puts(*args)
75
+ else
76
+ $stderr.puts(*args)
77
+ end
78
+
79
+ exit status
80
+ end
81
+
82
+ ###
83
+ # Exec command with data passed as stdin
84
+ #
85
+ # @params {String} args
86
+ # @params {Array} ary
87
+ # @params {Integer|Nil} status
88
+ ###
89
+ def exec_with_data(args, ary, status = nil)
90
+ Open3.popen3(args) do |i, o, e, w|
91
+ i.write(ary.join("\n")) if ary
92
+ i.close
93
+
94
+ threads = []
95
+ threads << Thread.new { o.each { |l| puts l } }
96
+ threads << Thread.new { e.each { |l| $stderr.puts l } }
97
+
98
+ ThreadsWait.all_waits(*threads)
99
+ exit(status.nil? ? w.value.exitstatus : status)
100
+ end
101
+ end
102
+
103
+ ###
104
+ # Check bundler existance
105
+ #
106
+ # @return {Boolean}
107
+ ###
108
+ def bundler_enabled?
109
+ Object.const_defined?(:Bundler) || !!Utils.find_file_upward('Gemfile')
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,95 @@
1
+ require_relative 'command_base'
2
+ require_relative '../stats'
3
+ require_relative '../related_spec_list'
4
+
5
+ module DeltaTest
6
+ class CLI
7
+ class ExecCommand < CommandBase
8
+
9
+ BUNDLE_EXEC = ['bundle', 'exec'].map(&:freeze).freeze
10
+ SPLITTER = '--'.freeze
11
+
12
+ def invoke!
13
+ if stats.base_commit
14
+ puts 'Base commit: %s' % [stats.base_commit]
15
+ puts
16
+ end
17
+
18
+ spec_files = nil
19
+ args = []
20
+
21
+ begin
22
+ unless profile_mode?
23
+ list.load_table!(stats.table_file_path)
24
+ list.retrive_changed_files!(stats.base_commit)
25
+
26
+ spec_files = list.related_spec_files.to_a
27
+
28
+ if spec_files.empty?
29
+ exit_with_message(0, 'Nothing to test')
30
+ end
31
+ end
32
+ rescue TableNotFoundError
33
+ # force profile mode cuz we don't have a table
34
+ @profile_mode = true
35
+ end
36
+
37
+ @args.map! { |arg| Shellwords.escape(arg) }
38
+
39
+ if (splitter = @args.index(SPLITTER))
40
+ files = @args.drop(splitter + 1)
41
+ @args = @args.take(splitter)
42
+
43
+ if files && files.any?
44
+ if spec_files
45
+ pattern = files.map { |file| Regexp.escape(file) }
46
+ pattern = '^(%s)' % pattern.join('|')
47
+ spec_files = spec_files.grep(pattern)
48
+ else
49
+ spec_files = files
50
+ end
51
+ end
52
+ end
53
+
54
+ if profile_mode?
55
+ args << ('%s=%s' % [VERBOSE_FLAG, true]) if DeltaTest.verbose?
56
+ args << ('%s=%s' % [ACTIVE_FLAG, true])
57
+ end
58
+
59
+ if spec_files
60
+ args.unshift('cat', '|')
61
+ args << 'xargs'
62
+ end
63
+
64
+ if bundler_enabled? && BUNDLE_EXEC != @args.take(2)
65
+ args += BUNDLE_EXEC
66
+ end
67
+
68
+ args += @args
69
+
70
+ $stdout.sync = true
71
+
72
+ exec_with_data(args.join(' '), spec_files)
73
+ end
74
+
75
+ def stats
76
+ @stats ||= Stats.new
77
+ end
78
+
79
+ def list
80
+ @list ||= RelatedSpecList.new
81
+ end
82
+
83
+ ###
84
+ # Whether run full test or not
85
+ #
86
+ # @return {Boolean}
87
+ ###
88
+ def profile_mode?
89
+ return @profile_mode if defined?(@profile_mode)
90
+ @profile_mode = !stats.base_commit && !@options['force-run']
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'command_base'
2
+
3
+ module DeltaTest
4
+ class CLI
5
+ class HelpCommand < CommandBase
6
+
7
+ TEXT = <<HELP
8
+ usage: delta_test <command> [--verbose] [<args>]
9
+
10
+ options:
11
+ --verbose Print more output.
12
+
13
+ commands:
14
+ exec [--force-run] <script> -- <files...>
15
+ Execute test script using delta_test.
16
+ --force-run to force DeltaTest to run full test cases.
17
+
18
+ specs List related spec files for changes.
19
+
20
+ stats:clean Clean up temporary files.
21
+
22
+ stats:show Show dependencies table.
23
+
24
+ stats:save [--no-sync]
25
+ Save and sync a table file.
26
+
27
+ version Show version.
28
+
29
+ help Show this.
30
+ HELP
31
+
32
+ def invoke!
33
+ puts TEXT
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ require_relative 'command_base'
2
+ require_relative '../stats'
3
+ require_relative '../related_spec_list'
4
+
5
+ module DeltaTest
6
+ class CLI
7
+ class SpecsCommand < CommandBase
8
+
9
+ def invoke!
10
+ if stats.base_commit
11
+ puts 'Base commit: %s' % [stats.base_commit]
12
+ puts
13
+ else
14
+ raise StatsNotFoundError
15
+ end
16
+
17
+ list.load_table!(stats.table_file_path)
18
+ list.retrive_changed_files!(stats.base_commit)
19
+
20
+ print_specs
21
+ end
22
+
23
+ def stats
24
+ @stats ||= Stats.new
25
+ end
26
+
27
+ def list
28
+ @list ||= RelatedSpecList.new
29
+ end
30
+
31
+ def print_specs
32
+ files = list.related_spec_files.to_a
33
+
34
+ if files.any?
35
+ puts files
36
+ else
37
+ puts '(no spec files to run)'
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ require 'fileutils'
2
+
3
+ require_relative 'command_base'
4
+
5
+ module DeltaTest
6
+ class CLI
7
+ class StatsCleanCommand < CommandBase
8
+
9
+ def invoke!
10
+ cleanup_tmp_table_files
11
+ end
12
+
13
+ def cleanup_tmp_table_files
14
+ tmp_dir = DeltaTest.config.tmp_table_file.parent
15
+ FileUtils.rm_rf(tmp_dir) if File.directory?(tmp_dir)
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,67 @@
1
+ require 'fileutils'
2
+
3
+ require_relative 'command_base'
4
+ require_relative '../dependencies_table'
5
+ require_relative '../stats'
6
+
7
+ module DeltaTest
8
+ class CLI
9
+ class StatsSaveCommand < CommandBase
10
+
11
+ def invoke!
12
+ load_tmp_table_files
13
+ cleanup_tmp_table_files
14
+ save_table_file
15
+
16
+ stage_table_file
17
+ sync_table_file unless @options['no-sync']
18
+ end
19
+
20
+ def load_tmp_table_files
21
+ tmp_table_files.each do |tmp_table_file|
22
+ tmp_table = DependenciesTable.load(tmp_table_file)
23
+ table.reverse_merge!(tmp_table)
24
+ end
25
+ end
26
+
27
+ def cleanup_tmp_table_files
28
+ tmp_dir = DeltaTest.config.tmp_table_file.parent
29
+ FileUtils.rm_rf(tmp_dir) if File.directory?(tmp_dir)
30
+ end
31
+
32
+ def save_table_file
33
+ table.dump(stats.table_file_path)
34
+ end
35
+
36
+ def stage_table_file
37
+ status = true
38
+ status &&= stats.stats_git.add(stats.table_file_path)
39
+ status &&= stats.stats_git.commit(stats.base_commit)
40
+ raise TableFileStageError unless status
41
+ end
42
+
43
+ def sync_table_file
44
+ return unless stats.stats_git.has_remote?
45
+ status = true
46
+ status &&= stats.stats_git.pull
47
+ status &&= stats.stats_git.push
48
+ raise StatsRepositorySyncError unless status
49
+ end
50
+
51
+ def tmp_table_files
52
+ return @tmp_table_files if defined?(@tmp_table_files)
53
+ tmp_table_files_pattern ||= DeltaTest.config.tmp_table_file.parent.join('*')
54
+ @tmp_table_files = Dir.glob(tmp_table_files_pattern)
55
+ end
56
+
57
+ def table
58
+ @table ||= DependenciesTable.new
59
+ end
60
+
61
+ def stats
62
+ @stats ||= Stats.new(head: true)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,46 @@
1
+ require_relative 'command_base'
2
+ require_relative '../stats'
3
+ require_relative '../related_spec_list'
4
+
5
+ module DeltaTest
6
+ class CLI
7
+ class StatsShowCommand < CommandBase
8
+
9
+ def invoke!
10
+ if stats.base_commit
11
+ puts 'Base commit: %s' % [stats.base_commit]
12
+ puts
13
+ else
14
+ raise StatsNotFoundError
15
+ end
16
+
17
+ list.load_table!(stats.table_file_path)
18
+ print_table
19
+ end
20
+
21
+ def stats
22
+ @stats ||= Stats.new
23
+ end
24
+
25
+ def list
26
+ @list ||= RelatedSpecList.new
27
+ end
28
+
29
+ def print_table
30
+ if list.table.any?
31
+ list.table.each do |spec_file, dependencies|
32
+ puts spec_file
33
+ puts
34
+ dependencies.each do |dependency|
35
+ puts "\t#{dependency}"
36
+ end
37
+ puts
38
+ end
39
+ else
40
+ puts '(no entry)'
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'command_base'
2
+
3
+ module DeltaTest
4
+ class CLI
5
+ class VersionCommand < CommandBase
6
+
7
+ def invoke!
8
+ puts 'DeltaTest v%s' % VERSION
9
+ end
10
+
11
+ end
12
+ end
13
+ end