delta_test 0.2.0 → 1.0.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 (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