retest 0.3.0 → 0.6.0.pre

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: b785b5164606d944a470b42899d1a7c6d4fa77f3d0d3a3850e4adc1e81d61db6
4
- data.tar.gz: d722fe7580cc3f24587322ee9d0dcc47efc4bded149d59461eb7408398f78b73
3
+ metadata.gz: 6d366f005d9765a2da827543e444b70898d9a7f94f5fd8c2ca5782b3fa5a0058
4
+ data.tar.gz: de7a1863a92188221e05955fa518a54c4f73fe3468ca15c47b7a6aa36f1baa66
5
5
  SHA512:
6
- metadata.gz: 9e7ebd3a5dd1eb6d1a09bcae184d749ac59b49cd928f845c3fcbf5d47e067e9623388167ffad4e7dc186e0aec22178444409e0da3978083107e57e7b7abcd453
7
- data.tar.gz: f0cd1516119abcc62c4dfb73d317097dc5f57d3ed741bc7ff44455c0518646c6c4ffcf44686e6ee939053a7bd435acd72fc8d4f6653123fa2816634e7abbb5a5
6
+ metadata.gz: 3277b79fce91040aac14f7e4980dc3687d6f02caed5ba47d629b106371780c65378e5dc1ecdcfa149c51e00f23022897aadb2c1cc249f3ca209ef267691f6f73
7
+ data.tar.gz: f8de2fc0468a666afe0e526b334147c5c32dbcb42a0621dbf7a0e7af084806500cba083dc19833174c6a3862715e2ed046dbe032576ef844823e1cdbd763153a
@@ -0,0 +1,35 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ main ]
13
+ pull_request:
14
+ branches: [ main ]
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ matrix:
21
+ ruby:
22
+ - 2.5
23
+ - 2.6
24
+ - 2.7
25
+ name: Ruby ${{ matrix.ruby }} test
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+ - name: Set up Ruby
29
+ uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: ${{ matrix.ruby }}
32
+ bundler-cache: true
33
+ - run: bundle install
34
+ - run: bundle exec rake
35
+ - run: bundle exec cucumber
@@ -0,0 +1 @@
1
+ 2.6.6
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in retest.gemspec
4
4
  gemspec
5
5
 
6
+ gem "cucumber", "~> 5.1"
7
+ gem "aruba", "~> 1.0"
6
8
  gem "rake", "~> 12.0"
7
9
  gem "minitest", "~> 5.0"
8
10
  gem "byebug"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- retest (0.3.0)
4
+ retest (0.6.0.pre)
5
5
  listen (~> 3.2)
6
6
  string-similarity (~> 2.1)
7
7
 
@@ -61,7 +61,7 @@ GEM
61
61
  ffi (1.13.1)
62
62
  i18n (1.8.5)
63
63
  concurrent-ruby (~> 1.0)
64
- listen (3.2.1)
64
+ listen (3.3.1)
65
65
  rb-fsevent (~> 0.10, >= 0.10.3)
66
66
  rb-inotify (~> 0.9, >= 0.9.10)
67
67
  middleware (0.1.0)
@@ -93,9 +93,9 @@ PLATFORMS
93
93
  ruby
94
94
 
95
95
  DEPENDENCIES
96
- aruba
96
+ aruba (~> 1.0)
97
97
  byebug
98
- cucumber
98
+ cucumber (~> 5.1)
99
99
  minitest (~> 5.0)
100
100
  rake (~> 12.0)
101
101
  retest!
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Retest
2
2
 
3
- Retest is a small gem to help refactor code by watching a file change and running its matching spec. You don't need a configuration file to start refactoring. It is advised to be one `cmd + z` away from green tests when refactoring. This means running tests after every line change. Let Retest rerun your tests after every file change you make.
3
+ Retest is a small command-line tool to help you refactor code by watching a file change and running its matching spec. Designed to be dev-centric and project independent, it can be used on the fly. No Gemfile updates, no commits to a repo or configuration files required to start refactoring. Works with every Ruby projects (at least that is the end goal)
4
4
 
5
- This is my take on solving tests rerun. It is meant to be simple and follow testing conventions encountered in Ruby projects. It is probably unstable and unflexible but covers my need. Give it a go you can uninstall it easily. For stable, yet more and fully fledged solutions, some cli tools already exists: [autotest](https://github.com/grosser/autotest), [guard](https://github.com/guard/guard), [zentest](https://github.com/seattlerb/zentest)
5
+ ## Why?
6
+ It is advised to be one `cmd + z` away from green tests when refactoring. This means running tests after every line change. Let Retest rerun your tests after every file change you make.
6
7
 
7
- This is a work in progress and the end goal is to have an executable that works as follow:
8
+ Retest gem is meant to be simple and follow testing conventions encountered in Ruby projects. Give it a go you can uninstall it easily. If you think the matching pattern could be improved please raise an issue.
8
9
 
9
- * Works with RSpec, MiniTest, Rake commands & bash commands (not aliases).
10
- * Works when run in a Docker container.
11
- * When a test file is not found run the last command again.
12
- * When multiple test files are found, ask which file to run and save the answer.
10
+ For fully fledged solutions, some cli tools already exists: [autotest](https://github.com/grosser/autotest), [guard](https://github.com/guard/guard), [zentest](https://github.com/seattlerb/zentest)
11
+
12
+ ![demo](https://alexbarret.com/images/external/retest-demo-26bcad04.gif)
13
13
 
14
14
  ## Installation
15
15
 
@@ -21,7 +21,7 @@ Install it on your machine with:
21
21
 
22
22
  Launch `retest` in your terminal after accessing your ruby project folder.
23
23
 
24
- Pass the test command surrounded with 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.
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
25
 
26
26
  ```bash
27
27
  # Let retest find the test file and replace the placeholder with the path of the test file
@@ -37,15 +37,24 @@ $ retest 'rails test'
37
37
  $ retest 'rspec'
38
38
  $ retest 'docker-compose exec web bundle exec rails test'
39
39
 
40
- # Hardcode a test file to run indepdendently from the file you change
40
+ # Hardcode a test file to run independently from the file you change
41
41
  $ retest 'ruby all_tests.rb'
42
42
  ```
43
43
 
44
+ The gem works as follows:
45
+
46
+ * When a file is changed, retest will run its matching file test.
47
+ * When a test file is changed, retest will run the file test.
48
+ * When multiple matching test files are found, retest asks you to confirm the file and save the answer.
49
+ * 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
+
44
53
  ### Docker
45
54
 
46
- Installing & launching the gem in the Docker container seem to work
55
+ Installing & launching the gem in a Docker container seems to work
47
56
  ```bash
48
- $ docker-compose run web bash
57
+ $ docker-compose run web bash
49
58
  $ gem install retest
50
59
  $ retest 'bundle exec rails test <test>'
51
60
  ```
@@ -54,12 +63,24 @@ $ retest 'bundle exec rails test <test>'
54
63
  * If an error comes in try using `bundle exec` like so: `$ retest 'bundle exec rake test <test>'`
55
64
  * Aliases saved on ~/.bashrc or ~/.zshrc cannot be run that way with the `retest` command
56
65
 
66
+ ## Ruby Support
67
+
68
+ Retest supports ruby 2.5 and above.
69
+
57
70
  ## Roadmap
58
71
 
59
72
  - [x] MVP
60
- - [x] Run withing Docker.
61
- - [ ] When a test file is not found run the last command again.
62
- - [ ] When multiple test files are found, ask which file to run and save the answer.
73
+ - [x] When multiple test files are found, ask which file to run and save the answer.
74
+ - [x] When a test file is not found run the last command again.
75
+ - [x] Run within Docker.
76
+ - [ ] Handle main Ruby setups
77
+ - [x] Bundler Gem
78
+ - [x] Rails
79
+ - [x] Ad-hoc scripts
80
+ - [x] Hanami
81
+ - [ ] Sinatra
82
+ - [ ] Cuba? Padrino?
83
+ - [ ] Handle other languages: Elixir, Node, Python, PHP
63
84
  - [ ] Aliases from oh-my-zsh and bash profiles?
64
85
 
65
86
  ## Development
@@ -75,4 +96,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/alexb5
75
96
 
76
97
  ## License
77
98
 
78
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
99
+ The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
Binary file
data/exe/retest CHANGED
@@ -1,21 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'retest'
4
- require 'listen'
5
4
 
6
- puts "Launching Retest..."
5
+ Retest.logger = STDOUT
7
6
 
8
- command = Retest::Command.for(ARGV.join)
7
+ Retest.log "Launching Retest..."
9
8
 
10
- listener = Listen.to('.', ignore: /node_modules|tmp/, relative: true) do |modified, added, removed|
11
- if modified.any?
12
- system("clear") || system("cls")
13
- command.run(modified.first.strip)
14
- end
15
- rescue => e
16
- puts "Something went wrong: #{e.message}"
17
- end
9
+ Retest
10
+ .build(command: Retest::Command.for(ARGV.join))
11
+ .start # not blocking
12
+
13
+ Retest.log "Ready to refactor! You can make file changes now"
18
14
 
19
- listener.start # not blocking
20
- puts "Ready to refactor! You can make file changes now"
21
15
  sleep
@@ -1,8 +1,27 @@
1
+ require 'listen'
2
+ require 'string/similarity'
3
+
1
4
  require "retest/version"
2
5
  require "retest/command"
3
6
  require "retest/repository"
4
- require 'string/similarity'
7
+ require "retest/test_options"
8
+ require "retest/listen_options"
9
+ require "retest/concerns/configurable"
5
10
 
6
11
  module Retest
12
+ include Configurable
7
13
  class Error < StandardError; end
14
+
15
+ def self.build(command:, clear_window: true)
16
+ Listen.to('.', ListenOptions.to_h) do |modified, added, removed|
17
+ begin
18
+ if modified.any?
19
+ system("clear") || system("cls") if clear_window
20
+ command.run(modified.first.strip)
21
+ end
22
+ rescue => e
23
+ puts "Something went wrong: #{e.message}"
24
+ end
25
+ end
26
+ end
8
27
  end
@@ -1,13 +1,13 @@
1
+ require 'open3'
2
+
1
3
  module Retest
2
4
  class Command
3
5
  def self.for(test_command)
4
- command_class = if test_command.include? '<test>'
6
+ if test_command.include? '<test>'
5
7
  VariableCommand
6
8
  else
7
9
  HardcodedCommand
8
- end
9
-
10
- command_class.new test_command
10
+ end.new test_command
11
11
  end
12
12
 
13
13
  class VariableCommand
@@ -24,10 +24,14 @@ module Retest
24
24
 
25
25
  def run(file_changed)
26
26
  if @cached_test_file = test_file(file_changed)
27
- puts "Test File Selected: #{cached_test_file}"
28
- system command.gsub('<test>', cached_test_file)
27
+ stdout_and_stderr_str, _ = Open3.capture2e command.gsub('<test>', cached_test_file)
28
+ Retest.log "Test File Selected: #{cached_test_file}"
29
+ Retest.log stdout_and_stderr_str
29
30
  else
30
- puts 'Could not find a file test matching'
31
+ Retest.log <<~ERROR
32
+ 404 - Test File Not Found
33
+ Retest could not find a matching test file to run.
34
+ ERROR
31
35
  end
32
36
  end
33
37
 
@@ -38,7 +42,8 @@ module Retest
38
42
 
39
43
  HardcodedCommand = Struct.new(:command) do
40
44
  def run(_)
41
- system command
45
+ stdout_and_stderr_str, _ = Open3.capture2e(command)
46
+ Retest.log stdout_and_stderr_str
42
47
  end
43
48
  end
44
49
  end
@@ -0,0 +1,30 @@
1
+ module Configurable
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ end
5
+
6
+ class Configuration
7
+ extend Forwardable
8
+
9
+ attr_accessor :logger
10
+
11
+ def_delegator :logger, :puts
12
+ alias :log :puts
13
+ end
14
+
15
+ module ClassMethods
16
+ extend Forwardable
17
+
18
+ attr_writer :configuration
19
+
20
+ def_delegators :configuration, :log, :logger, :logger=
21
+
22
+ def configuration
23
+ @configuration ||= Configuration.new
24
+ end
25
+
26
+ def configure
27
+ yield configuration
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
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>&1"
30
+ end
31
+
32
+ def files
33
+ `git ls-files`
34
+ end
35
+ end
36
+ end
@@ -1,30 +1,25 @@
1
1
  module Retest
2
2
  class Repository
3
- attr_accessor :files, :cache, :input_stream, :output_stream
3
+ attr_accessor :files, :cache, :input_stream
4
4
 
5
- def initialize(files: nil, cache: {}, input_stream: nil, output_stream: nil)
5
+ def initialize(files: nil, cache: {}, input_stream: nil)
6
6
  @cache = cache
7
7
  @files = files || default_files
8
8
  @input_stream = input_stream || STDIN
9
- @output_stream = output_stream|| STDOUT
10
9
  end
11
10
 
12
11
  def find_test(path)
13
- cache[path] ||= select_test(path)
12
+ cache[path] ||= select_from TestOptions.for(path, files: files)
14
13
  end
15
14
 
16
15
  private
17
16
 
18
- def select_test(path)
19
- tests = files.select { |file| regex(path) =~ file }
20
- .sort_by { |file| String::Similarity.levenshtein(path, file) }
21
- .reverse
22
-
17
+ def select_from(tests)
23
18
  case tests.count
24
19
  when 0, 1
25
20
  tests.first
26
21
  else
27
- ask_question tests.first(5)
22
+ ask_question tests
28
23
  tests[get_input]
29
24
  end
30
25
  end
@@ -33,19 +28,13 @@ module Retest
33
28
  @default_files ||= Dir.glob('**/*') - Dir.glob('{tmp,node_modules}/**/*')
34
29
  end
35
30
 
36
- def regex(path)
37
- extname = File.extname(path)
38
- basename = File.basename(path, extname)
39
- Regexp.new(".*#{basename}_(?:spec|test)#{extname}")
40
- end
41
-
42
31
  def ask_question(tests)
43
- output_stream.puts <<~QUESTION
44
- We found few tests matching:
45
- #{list_options(tests)}
32
+ Retest.log <<~QUESTION
33
+ We found few tests matching:
34
+ #{list_options(tests)}
46
35
 
47
- Which file do you want to use?
48
- Enter the file number now:
36
+ Which file do you want to use?
37
+ Enter the file number now:
49
38
  QUESTION
50
39
  end
51
40
 
@@ -0,0 +1,87 @@
1
+ require 'forwardable'
2
+
3
+ module Retest
4
+ class TestOptions
5
+ def self.for(path, files: [])
6
+ new(path, files: files).filtered_results
7
+ end
8
+
9
+ attr_reader :path, :files
10
+
11
+ def initialize(path, files: [])
12
+ @path = Path.new(path)
13
+ @files = files
14
+ end
15
+
16
+ def filtered_results
17
+ if path.test?
18
+ [path]
19
+ elsif namespace_screens.any?
20
+ namespace_screens
21
+ else
22
+ possible_tests
23
+ end.map(&:to_s)
24
+ end
25
+
26
+ private
27
+
28
+ def possible_tests
29
+ @possible_tests ||= filter_by_string_similarities(path, files)
30
+ .last(5)
31
+ .reverse
32
+ end
33
+
34
+ def filter_by_string_similarities(path, files)
35
+ files.select { |file| path.possible_test?(file) }
36
+ .sort_by { |file| [path.similarity_score(file), file] }
37
+ end
38
+
39
+ def namespace_screens
40
+ @namespace_screens ||= path
41
+ .reversed_dirnames
42
+ .each_with_index
43
+ .with_object(possible_tests.map { |file| Path.new(file) }) do |(reference, index), result|
44
+ unless [1, 0].include? result.count
45
+ result.keep_if { |path| path.reversed_dirnames[index] == reference }
46
+ end
47
+ end
48
+ end
49
+
50
+ class Path
51
+ extend Forwardable
52
+
53
+ def_delegators :pathname, :to_s, :basename, :extname, :dirname
54
+
55
+ attr_reader :pathname
56
+ def initialize(path)
57
+ @pathname = Pathname(path)
58
+ end
59
+
60
+ def reversed_dirnames
61
+ @reversed_dirnames ||= dirname.each_filename.to_a.reverse
62
+ end
63
+
64
+ def test?
65
+ test_regex =~ to_s
66
+ end
67
+
68
+ def possible_test?(file)
69
+ possible_test_regex =~ file
70
+ end
71
+
72
+ def similarity_score(file)
73
+ String::Similarity.levenshtein(to_s, file)
74
+ end
75
+
76
+ private
77
+
78
+ def test_regex
79
+ Regexp.new(".*(?:spec|test)#{extname}")
80
+ end
81
+
82
+ def possible_test_regex
83
+ Regexp.new(".*#{basename(extname)}_(?:spec|test)#{extname}")
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,3 +1,3 @@
1
1
  module Retest
2
- VERSION = "0.3.0"
2
+ VERSION = "0.6.0.pre"
3
3
  end
File without changes
@@ -27,6 +27,4 @@ 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_development_dependency "cucumber"
31
- spec.add_development_dependency "aruba"
32
30
  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.3.0
4
+ version: 0.6.0.pre
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-09-06 00:00:00.000000000 Z
11
+ date: 2020-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: string-similarity
@@ -38,35 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
- - !ruby/object:Gem::Dependency
42
- name: cucumber
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: aruba
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- description:
41
+ description:
70
42
  email:
71
43
  - alex@abletech.nz
72
44
  executables:
@@ -74,20 +46,26 @@ executables:
74
46
  extensions: []
75
47
  extra_rdoc_files: []
76
48
  files:
49
+ - ".github/workflows/ci.yml"
77
50
  - ".gitignore"
78
- - ".travis.yml"
51
+ - ".ruby-version"
79
52
  - Gemfile
80
53
  - Gemfile.lock
81
54
  - LICENSE.txt
82
55
  - README.md
56
+ - README/demo.gif
83
57
  - Rakefile
84
58
  - bin/console
85
59
  - bin/setup
86
60
  - exe/retest
87
61
  - lib/retest.rb
88
62
  - lib/retest/command.rb
63
+ - lib/retest/concerns/configurable.rb
64
+ - lib/retest/listen_options.rb
89
65
  - lib/retest/repository.rb
66
+ - lib/retest/test_options.rb
90
67
  - lib/retest/version.rb
68
+ - output.log
91
69
  - retest.gemspec
92
70
  homepage: https://github.com/AlexB52/retest
93
71
  licenses:
@@ -95,7 +73,7 @@ licenses:
95
73
  metadata:
96
74
  homepage_uri: https://github.com/AlexB52/retest
97
75
  source_code_uri: https://github.com/AlexB52/retest
98
- post_install_message:
76
+ post_install_message:
99
77
  rdoc_options: []
100
78
  require_paths:
101
79
  - lib
@@ -106,12 +84,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
84
  version: 2.3.0
107
85
  required_rubygems_version: !ruby/object:Gem::Requirement
108
86
  requirements:
109
- - - ">="
87
+ - - ">"
110
88
  - !ruby/object:Gem::Version
111
- version: '0'
89
+ version: 1.3.1
112
90
  requirements: []
113
91
  rubygems_version: 3.0.3
114
- signing_key:
92
+ signing_key:
115
93
  specification_version: 4
116
94
  summary: A simple command line tool to watch file change and run its matching spec.
117
95
  test_files: []
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- before_install: gem install bundler -v 2.1.4