retest 0.6.0 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1d5cde47e268fbb49f94510bb8bde3398974672fae9ad770dbe85f542764e6d
4
- data.tar.gz: db1d76a1b2329a2e1619a34778c305280cbc50d2b99fd87998ae0c1b3406fb1b
3
+ metadata.gz: 91733d40e95f4722f63219c301063e4bb74fe6f543f9cdb709795bdb432ec7a0
4
+ data.tar.gz: 7796cbfb877e2065a7ede16e80bbd41f8f0f106f105cbde1c28d734239da084e
5
5
  SHA512:
6
- metadata.gz: 9ed11c05236d2f50d54b644d02fa1c37c9d928f7a6b452e60a5ea9c23deab95d6e7a3e178f3047b3dcbce945c0cf9bee3e31682fd9b53d1f7df4b01a2303d476
7
- data.tar.gz: 417d8fb0439869a1be651efa2daece0cf1a1fab705495a4bc72b9827355fb054f34e3c93d92177be8a43aba028b36c2c876bc70801ba71083ca832da9efda731
6
+ metadata.gz: fbc2dc22da11f0aeaaf0e8616caa1ca68f05074298506144ef510acb53ea7a8dba96252e40f7755c826a1d2f4f30648e7a0bf6016829d62681afbea50e08f494
7
+ data.tar.gz: 14400ccfe165b8c7d2ce20824bd1b7e742eaa6a42c1c5d3d5e42b80f280a51c7ddb26ec8b6ddf20ab50a7d124c16521a045d2eb688e362822de28854619e9749
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- retest (0.6.0)
4
+ retest (0.8.0)
5
5
  listen (~> 3.2)
6
6
  string-similarity (~> 2.1)
7
+ tty-option (~> 0.1)
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
@@ -61,7 +62,7 @@ GEM
61
62
  ffi (1.13.1)
62
63
  i18n (1.8.5)
63
64
  concurrent-ruby (~> 1.0)
64
- listen (3.3.1)
65
+ listen (3.4.1)
65
66
  rb-fsevent (~> 0.10, >= 0.10.3)
66
67
  rb-inotify (~> 0.9, >= 0.9.10)
67
68
  middleware (0.1.0)
@@ -85,6 +86,7 @@ GEM
85
86
  ffi (>= 1.0.0)
86
87
  thor (1.0.1)
87
88
  thread_safe (0.3.6)
89
+ tty-option (0.1.0)
88
90
  tzinfo (1.2.7)
89
91
  thread_safe (~> 0.1)
90
92
  zeitwerk (2.4.0)
data/README.md CHANGED
@@ -16,29 +16,46 @@ For fully fledged solutions, some cli tools already exists: [autotest](https://g
16
16
  Install it on your machine with:
17
17
 
18
18
  $ gem install retest
19
+ $ retest 'bundle exec rspec <test>'
19
20
 
20
21
  ## Usage
21
22
 
22
23
  Launch `retest` in your terminal after accessing your ruby project folder.
23
24
 
24
- Pass the test command surrounded by quotes. Use the placeholder `<test>` in your command to let `retest` find the matching test and replace the placeholder with the path of the test file.
25
+ Pass the test command surrounded by quotes. Use the placeholder `<test>` in your command to tell `retest` where to put the path of the test file in your command. Example: `retest 'bundle exec rspec <test>'`. When a file is changed `retest` will find its matching test and run it.
25
26
 
26
- ```bash
27
- # Let retest find the test file and replace the placeholder with the path of the test file
28
- $ retest 'bundle exec rake test TEST=<test>'
29
- $ retest 'rails test <test>'
30
- $ retest 'rspec <test>'
31
- $ retest 'ruby <test>'
32
- $ retest 'docker-compose exec web bundle exec rails test <test>'
33
-
34
- # Run the same command after a file change like all the spec files
35
- $ retest 'bundle exec rake test'
36
- $ retest 'rails test'
37
- $ retest 'rspec'
38
- $ retest 'docker-compose exec web bundle exec rails test'
39
-
40
- # Hardcode a test file to run independently from the file you change
41
- $ retest 'ruby all_tests.rb'
27
+ Learn more by running `retest -h`
28
+
29
+ ```
30
+ Usage: retest [OPTIONS] [COMMAND]
31
+
32
+ Watch a file change and run it matching spec.
33
+
34
+ Arguments:
35
+ COMMAND The test command to rerun when a file changes.
36
+ Use <test> placeholder to tell retest where to put the matching
37
+ spec.
38
+
39
+
40
+ Options:
41
+ --all Run all the specs of a specificied ruby setup
42
+ -h, --help Print usage
43
+ --rails Shortcut for 'bundle exec rails test <test>'
44
+ --rake Shortcut for 'bundle exec rake test TEST=<test>'
45
+ --rspec Shortcut for 'bundle exec rspec <test>'
46
+ --ruby Shortcut for 'bundle exec ruby <test>'
47
+
48
+ Examples:
49
+ Runs a matching rails test after a file change
50
+ $ retest 'bundle exec rails test <test>'
51
+ $ retest --rails
52
+
53
+ Runs all rails tests after a file change
54
+ $ retest 'bundle exec rails test'
55
+ $ retest --rails --all
56
+
57
+ Runs a hardcoded command after a file change
58
+ $ retest 'ruby lib/bottles_test.rb'
42
59
  ```
43
60
 
44
61
  The gem works as follows:
@@ -47,25 +64,23 @@ The gem works as follows:
47
64
  * When a test file is changed, retest will run the file test.
48
65
  * When multiple matching test files are found, retest asks you to confirm the file and save the answer.
49
66
  * When a test file is not found, retest runs the last run command or throw a 404.
50
- * Works with RSpec, MiniTest, Rake commands & bash commands (not aliases).
51
- * Works when installed and run in a Docker container.
52
67
 
53
68
  ### Docker
54
69
 
55
- Installing & launching the gem in a Docker container seems to work
70
+ Retest works in Docker too. You can install the gem and launch retest in your container while refactoring.
56
71
  ```bash
57
- $ docker-compose run web bash
72
+ $ docker-compose run web bash # enter your container
58
73
  $ gem install retest
59
74
  $ retest 'bundle exec rails test <test>'
60
75
  ```
61
76
 
62
- **Disclaimer:**
77
+ ### Disclaimer
63
78
  * If an error comes in try using `bundle exec` like so: `$ retest 'bundle exec rake test <test>'`
64
79
  * Aliases saved on ~/.bashrc or ~/.zshrc cannot be run that way with the `retest` command
65
80
 
66
81
  ## Ruby Support
67
82
 
68
- Retest supports ruby 2.5 and above.
83
+ Retest supports ruby 2.4 and above.
69
84
 
70
85
  ## Roadmap
71
86
 
data/exe/retest CHANGED
@@ -4,12 +4,10 @@ require 'retest'
4
4
 
5
5
  $stdout.sync = true
6
6
 
7
- puts "Launching Retest..."
7
+ options = Retest::Options.new(ARGV)
8
8
 
9
- Retest
10
- .build(command: Retest::Command.for(ARGV.join))
11
- .start # not blocking
9
+ return puts options.help if options.help?
12
10
 
13
- puts "Ready to refactor! You can make file changes now"
11
+ Retest.start(options.command) # not blocking
14
12
 
15
13
  sleep
data/lib/retest.rb CHANGED
@@ -2,23 +2,39 @@ require 'listen'
2
2
  require 'string/similarity'
3
3
 
4
4
  require "retest/version"
5
- require "retest/command"
5
+ require "retest/runner"
6
6
  require "retest/repository"
7
7
  require "retest/test_options"
8
- require "retest/listen_options"
8
+ require "retest/options"
9
+ require "retest/version_control"
9
10
 
10
11
  module Retest
11
12
  class Error < StandardError; end
12
13
 
13
- def self.build(command:)
14
- Listen.to('.', ListenOptions.to_h) do |modified, added, removed|
15
- begin
16
- if modified.any?
14
+ class << self
15
+ def start(command)
16
+ puts "Launching Retest..."
17
+
18
+ build(
19
+ runner: Runner.for(command),
20
+ repository: Repository.new(files: VersionControl.files)
21
+ ).start
22
+
23
+ puts "Ready to refactor! You can make file changes now"
24
+ end
25
+
26
+ def build(runner:, repository:)
27
+ Listen.to('.', only: /\.rb$/, relative: true) do |modified, added, removed|
28
+ begin
29
+ repository.add(added)
30
+ repository.remove(removed)
31
+ runner.remove(removed)
17
32
  system('clear 2>/dev/null') || system('cls 2>/dev/null')
18
- command.run(modified.first.strip)
33
+
34
+ runner.run repository.find_test (modified + added).first
35
+ rescue => e
36
+ puts "Something went wrong: #{e.message}"
19
37
  end
20
- rescue => e
21
- puts "Something went wrong: #{e.message}"
22
38
  end
23
39
  end
24
40
  end
@@ -0,0 +1,114 @@
1
+ require 'tty-option'
2
+
3
+ module Retest
4
+ class Options
5
+ include TTY::Option
6
+
7
+ RSPEC_COMMAND = "bundle exec rspec <test>"
8
+ RAILS_COMMAND = "bundle exec rails test <test>"
9
+ RAKE_COMMAND = "bundle exec rake test TEST=<test>"
10
+ RUBY_COMMAND = "bundle exec ruby <test>"
11
+ NO_COMMAND = "echo You have no command assigned"
12
+
13
+ ALL_RAKE_COMMAND = "bundle exec rake test"
14
+ ALL_RAILS_COMMAND = "bundle exec rails test"
15
+ ALL_RSPEC_COMMAND = "bundle exec rspec"
16
+
17
+ usage do
18
+ program "retest"
19
+
20
+ command nil
21
+
22
+ desc "Watch a file change and run it matching spec."
23
+
24
+ example <<~EOS
25
+ Runs a matching rails test after a file change
26
+ $ retest 'bundle exec rails test <test>'
27
+ $ retest --rails
28
+ EOS
29
+
30
+ example <<~EOS
31
+ Runs all rails tests after a file change
32
+ $ retest 'bundle exec rails test'
33
+ $ retest --rails --all
34
+ EOS
35
+
36
+ example <<~EOS
37
+ Runs a hardcoded command after a file change
38
+ $ retest 'ruby lib/bottles_test.rb'
39
+ EOS
40
+ end
41
+
42
+ argument :command do
43
+ optional
44
+ desc <<~EOS
45
+ The test command to rerun when a file changes.
46
+ Use <test> placeholder to tell retest where to put the matching spec.
47
+ EOS
48
+ end
49
+
50
+ flag :all do
51
+ long "--all"
52
+ desc "Run all the specs of a specificied ruby setup"
53
+ end
54
+
55
+ flag :help do
56
+ short "-h"
57
+ long "--help"
58
+ desc "Print usage"
59
+ end
60
+
61
+ flag :rspec do
62
+ long "--rspec"
63
+ desc "Shortcut for '#{RSPEC_COMMAND}'"
64
+ end
65
+
66
+ flag :rake do
67
+ long "--rake"
68
+ desc "Shortcut for '#{RAKE_COMMAND}'"
69
+ end
70
+
71
+ flag :rails do
72
+ long "--rails"
73
+ desc "Shortcut for '#{RAILS_COMMAND}'"
74
+ end
75
+
76
+ flag :ruby do
77
+ long "--ruby"
78
+ desc "Shortcut for '#{RUBY_COMMAND}'"
79
+ end
80
+
81
+ attr_reader :args
82
+
83
+ def self.command(args)
84
+ new(args).command
85
+ end
86
+
87
+ def initialize(args = [])
88
+ self.args = args
89
+ end
90
+
91
+ def command
92
+ if params[:rspec]
93
+ params[:all] ? ALL_RSPEC_COMMAND : RSPEC_COMMAND
94
+ elsif params[:rake]
95
+ params[:all] ? ALL_RAKE_COMMAND : RAKE_COMMAND
96
+ elsif params[:rails]
97
+ params[:all] ? ALL_RAILS_COMMAND : RAILS_COMMAND
98
+ elsif params[:ruby]
99
+ params[:all] ? NO_COMMAND : RUBY_COMMAND
100
+ else
101
+ params[:command] || NO_COMMAND
102
+ end
103
+ end
104
+
105
+ def args=(args)
106
+ @args = args
107
+ parse args
108
+ end
109
+
110
+ def help?
111
+ params[:help]
112
+ end
113
+ end
114
+ end
@@ -2,17 +2,37 @@ module Retest
2
2
  class Repository
3
3
  attr_accessor :files, :cache, :input_stream, :output_stream
4
4
 
5
- def initialize(files: nil, cache: {}, input_stream: nil, output_stream: nil)
5
+ def initialize(files: [], cache: {}, input_stream: nil, output_stream: nil)
6
6
  @cache = cache
7
- @files = files || default_files
7
+ @files = files
8
8
  @input_stream = input_stream || STDIN
9
9
  @output_stream = output_stream|| STDOUT
10
10
  end
11
11
 
12
12
  def find_test(path)
13
+ return unless path
14
+ return if path.empty?
15
+
13
16
  cache[path] ||= select_from TestOptions.for(path, files: files)
14
17
  end
15
18
 
19
+ def add(added)
20
+ return if added && added.empty?
21
+
22
+ files.push(*added)
23
+ files.sort!
24
+ end
25
+
26
+ def remove(removed)
27
+ return if removed && removed.empty?
28
+
29
+ if removed.is_a?(Array)
30
+ removed.each { |file| files.delete(file) }
31
+ else
32
+ files.delete(removed)
33
+ end
34
+ end
35
+
16
36
  private
17
37
 
18
38
  def select_from(tests)
@@ -25,10 +45,6 @@ module Retest
25
45
  end
26
46
  end
27
47
 
28
- def default_files
29
- @default_files ||= Dir.glob('**/*') - Dir.glob('{tmp,node_modules}/**/*')
30
- end
31
-
32
48
  def ask_question(tests)
33
49
  output_stream.puts <<~QUESTION
34
50
  We found few tests matching:
@@ -0,0 +1,70 @@
1
+ module Retest
2
+ class Runner
3
+ def self.for(test_command)
4
+ if test_command.include? '<test>'
5
+ VariableRunner
6
+ else
7
+ HardcodedRunner
8
+ end.new test_command
9
+ end
10
+
11
+ class VariableRunner
12
+ attr_reader :command
13
+
14
+ def initialize(command)
15
+ @command = command
16
+ @cached_test_file = nil
17
+ end
18
+
19
+ def ==(obj)
20
+ command == obj.command
21
+ end
22
+
23
+ def cached_test_file
24
+ @cached_test_file
25
+ end
26
+
27
+ def cached_test_file=(value)
28
+ @cached_test_file = value || @cached_test_file
29
+ end
30
+
31
+ def run(test_file = nil)
32
+ self.cached_test_file = test_file
33
+
34
+ if cached_test_file
35
+ puts "Test File Selected: #{cached_test_file}"
36
+ system command.gsub('<test>', cached_test_file)
37
+ else
38
+ puts <<~ERROR
39
+ 404 - Test File Not Found
40
+ Retest could not find a matching test file to run.
41
+ ERROR
42
+ end
43
+ end
44
+
45
+ def remove(purged)
46
+ return if purged.empty?
47
+
48
+ if purged.is_a? Array
49
+ purge_cache if purged.include? cached_test_file
50
+ elsif purged.is_a? String
51
+ purge_cache if purged == cached_test_file
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def purge_cache
58
+ @cached_test_file = nil
59
+ end
60
+ end
61
+
62
+ HardcodedRunner = Struct.new(:command) do
63
+ def run(_ = nil)
64
+ system command
65
+ end
66
+
67
+ def remove(_ = nil); end
68
+ end
69
+ end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Retest
2
- VERSION = "0.6.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,38 @@
1
+ module Retest
2
+ class VersionControl
3
+ def self.files
4
+ [Git, NoVersionControl].select(&:installed?).first.new.files
5
+ end
6
+
7
+ def name; end
8
+ alias :to_s :name
9
+
10
+ class NoVersionControl
11
+ def self.installed?
12
+ true
13
+ end
14
+
15
+ def name
16
+ 'default'
17
+ end
18
+
19
+ def files
20
+ Dir.glob('**/*') - Dir.glob('{tmp,node_modules}/**/*')
21
+ end
22
+ end
23
+
24
+ class Git
25
+ def self.installed?
26
+ system "git -C . rev-parse 2>/dev/null"
27
+ end
28
+
29
+ def name
30
+ 'git'
31
+ end
32
+
33
+ def files
34
+ `git ls-files`.split("\n")
35
+ end
36
+ end
37
+ end
38
+ end
data/retest.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ["lib"]
28
28
  spec.add_runtime_dependency "string-similarity", ["~> 2.1"]
29
29
  spec.add_runtime_dependency "listen", ["~> 3.2"]
30
+ spec.add_runtime_dependency "tty-option", ["~> 0.1"]
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Barret
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-18 00:00:00.000000000 Z
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: string-similarity
@@ -38,7 +38,21 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
- description:
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-option
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ description:
42
56
  email:
43
57
  - alex@abletech.nz
44
58
  executables:
@@ -59,11 +73,12 @@ files:
59
73
  - bin/setup
60
74
  - exe/retest
61
75
  - lib/retest.rb
62
- - lib/retest/command.rb
63
- - lib/retest/listen_options.rb
76
+ - lib/retest/options.rb
64
77
  - lib/retest/repository.rb
78
+ - lib/retest/runner.rb
65
79
  - lib/retest/test_options.rb
66
80
  - lib/retest/version.rb
81
+ - lib/retest/version_control.rb
67
82
  - retest.gemspec
68
83
  homepage: https://github.com/AlexB52/retest
69
84
  licenses:
@@ -71,7 +86,7 @@ licenses:
71
86
  metadata:
72
87
  homepage_uri: https://github.com/AlexB52/retest
73
88
  source_code_uri: https://github.com/AlexB52/retest
74
- post_install_message:
89
+ post_install_message:
75
90
  rdoc_options: []
76
91
  require_paths:
77
92
  - lib
@@ -87,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
102
  version: '0'
88
103
  requirements: []
89
104
  rubygems_version: 3.0.3
90
- signing_key:
105
+ signing_key:
91
106
  specification_version: 4
92
107
  summary: A simple command line tool to watch file change and run its matching spec.
93
108
  test_files: []
@@ -1,46 +0,0 @@
1
- module Retest
2
- class Command
3
- def self.for(test_command)
4
- if test_command.include? '<test>'
5
- VariableCommand
6
- else
7
- HardcodedCommand
8
- end.new test_command
9
- end
10
-
11
- class VariableCommand
12
- attr_reader :command, :repository, :cached_test_file
13
-
14
- def initialize(command, repository: nil)
15
- @repository = repository || Repository.new
16
- @command = command
17
- end
18
-
19
- def ==(obj)
20
- command == obj.command
21
- end
22
-
23
- def run(file_changed)
24
- if @cached_test_file = test_file(file_changed)
25
- puts "Test File Selected: #{cached_test_file}"
26
- system command.gsub('<test>', cached_test_file)
27
- else
28
- puts <<~ERROR
29
- 404 - Test File Not Found
30
- Retest could not find a matching test file to run.
31
- ERROR
32
- end
33
- end
34
-
35
- def test_file(file_changed)
36
- repository.find_test(file_changed) || cached_test_file
37
- end
38
- end
39
-
40
- HardcodedCommand = Struct.new(:command) do
41
- def run(_)
42
- system command
43
- end
44
- end
45
- end
46
- end
@@ -1,36 +0,0 @@
1
- module Retest
2
- class ListenOptions
3
- IGNORE_REGEX = /node_modules|tmp|\.sqlite|\.byebug_history/
4
-
5
- class << self
6
- def to_h(tool = GitTool.new)
7
- return {ignore: IGNORE_REGEX, relative: true} unless tool.installed?
8
-
9
- {only: regex_for(tool.files), relative: true}
10
- end
11
-
12
- private
13
-
14
- def regex_for(files)
15
- Regexp.new files.split("\n").join('|')
16
- end
17
- end
18
- end
19
-
20
- class GitTool
21
- attr_reader :name
22
- alias :to_s :name
23
-
24
- def initialize
25
- @name = 'git'
26
- end
27
-
28
- def installed?
29
- system "git -C . rev-parse 2>/dev/null"
30
- end
31
-
32
- def files
33
- `git ls-files`
34
- end
35
- end
36
- end