test_launcher 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.md +101 -18
  4. data/Rakefile +6 -0
  5. data/bin/test_launcher +8 -35
  6. data/lib/test_launcher.rb +22 -0
  7. data/lib/test_launcher/cli/input_parser.rb +73 -0
  8. data/lib/test_launcher/frameworks.rb +32 -0
  9. data/lib/test_launcher/frameworks/base.rb +54 -0
  10. data/lib/test_launcher/frameworks/implementation/collection.rb +27 -0
  11. data/lib/test_launcher/{tests/minitest → frameworks/implementation}/consolidator.rb +30 -32
  12. data/lib/test_launcher/frameworks/implementation/locator.rb +74 -0
  13. data/lib/test_launcher/frameworks/implementation/test_case.rb +65 -0
  14. data/lib/test_launcher/frameworks/minitest.rb +67 -0
  15. data/lib/test_launcher/frameworks/rspec.rb +50 -0
  16. data/lib/test_launcher/rubymine.rb +26 -0
  17. data/lib/test_launcher/rubymine/launcher.rb +55 -0
  18. data/lib/test_launcher/search/git.rb +64 -0
  19. data/lib/test_launcher/shell/runner.rb +19 -22
  20. data/lib/test_launcher/version.rb +1 -1
  21. data/test/install +3 -0
  22. data/test/test_helper.rb +32 -17
  23. data/test/test_launcher/fixtures/minitest/test/class_1_test.rb +17 -0
  24. data/test/test_launcher/fixtures/minitest/test/class_2_test.rb +5 -0
  25. data/test/test_launcher/fixtures/minitest/test/different_root/bin/spring +1 -0
  26. data/test/test_launcher/fixtures/minitest/test/different_root/test/different_root_test.rb +2 -0
  27. data/test/test_launcher/fixtures/rspec/spec/class_1_spec.rb +16 -0
  28. data/test/test_launcher/fixtures/rspec/spec/class_2_spec.rb +6 -0
  29. data/test/test_launcher/fixtures/rspec/spec/different_root/spec/different_root_spec.rb +2 -0
  30. data/test/test_launcher/minitest_integration_test.rb +67 -0
  31. data/test/test_launcher/rspec_integration_test.rb +67 -0
  32. data/test/test_launcher/rubymine_test.rb +48 -0
  33. data/test_launcher.gemspec +2 -3
  34. metadata +39 -44
  35. data/bin/test_runner +0 -1
  36. data/lib/test_launcher/searchers/git_searcher.rb +0 -38
  37. data/lib/test_launcher/tests/minitest/finder.rb +0 -50
  38. data/lib/test_launcher/tests/minitest/wrappers/multiple_files.rb +0 -23
  39. data/lib/test_launcher/tests/minitest/wrappers/multiple_roots.rb +0 -23
  40. data/lib/test_launcher/tests/minitest/wrappers/single_file.rb +0 -29
  41. data/lib/test_launcher/tests/minitest/wrappers/single_root.rb +0 -27
  42. data/lib/test_launcher/tests/minitest/wrappers/single_test.rb +0 -37
  43. data/lib/test_launcher/utils/path.rb +0 -32
  44. data/lib/test_launcher/utils/pluralize.rb +0 -14
  45. data/test/test_launcher/searchers/git_searcher_test.rb +0 -50
  46. data/test/test_launcher/tests/minitest/consolidator_integration_test.rb +0 -191
  47. data/test/test_launcher/tests/minitest/finder_test.rb +0 -71
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 076fd8dd620db12cc980d5e0feb4e64bb0eb19d0
4
- data.tar.gz: e69f9e56de5f8dd4c952301387e382ea298c8862
3
+ metadata.gz: a5d53997bd88d7bff2231d598664f4a9d2c17534
4
+ data.tar.gz: 665cc8fafb6894917dd92c8c788e3312698df4a0
5
5
  SHA512:
6
- metadata.gz: ae02ab9956036df7e73ce62f6fad7ed39027eb0220c1e3516b726e47c60db3eb79f7522a8f8f8e0a5cbe0f8b8968a3b56aed6f8405e52319b04705f7471a131e
7
- data.tar.gz: 9a55b973f8896de1ccbfbc34d25cdff69efbd3007f2857b27d21c5ca866a02fec717350cd76a8a5a8c7ac6b5e505de4e1c489b4e0a685e6eca23fbc18d164436
6
+ metadata.gz: 195db1420d9e19aeef576839f018f5a9596f5ef873401ae46e0a695a4fc52de4cf948092e714d627a367e9dcf8d91388c723a06067f9b01eeca9f3c91cce6168
7
+ data.tar.gz: a70dd282dcd28bab87961be98c848cb1d5b8a825d89b7befae3c67270f1331c17dd7a473ad6e265ea0875de9214f9db20fcef9a97c784acae0414c14aa45ad01
data/Gemfile CHANGED
@@ -5,3 +5,4 @@ gemspec
5
5
 
6
6
  gem "minitest"
7
7
  gem "mocha"
8
+ gem "pry"
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  #Test Launcher -->
2
2
 
3
- Test Launcher takes some input and tries to figure out what test you want to run. It makes running tests on the command line much easier. Test Launcher works with Minitest and probably TestUnit. RSpec isn't supported. If you use RSpec and you think this would be handy, let me know!
3
+ Test Launcher takes some input and tries to figure out what test you want to run. It makes running tests on the command line much easier. Test Launcher works with Minitest. RSpec support is in its infancy. You should try it and let me know!
4
+
5
+ ### Usage
4
6
 
5
7
  Let's suppose you want to run the test `test_name` in your `blog_post_test.rb`.
6
8
 
@@ -13,7 +15,7 @@ ruby -I test test/models/blog_post_test.rb --name=test_blog_name_thing
13
15
  But with Test Launcher, you can just type this:
14
16
 
15
17
  ```
16
- t test_blog_name_thing
18
+ test_launcher test_blog_name_thing
17
19
 
18
20
  #=> ruby -I test test/models/blog_post_test.rb --name=test_blog_name_thing
19
21
  ```
@@ -21,7 +23,7 @@ t test_blog_name_thing
21
23
  What if you want to run a whole file? Just go for it!
22
24
 
23
25
  ```
24
- t blog_post_test
26
+ test_launcher blog_post_test
25
27
 
26
28
  #=> ruby -I test test/models/blog_post_test.rb
27
29
  ```
@@ -29,7 +31,7 @@ t blog_post_test
29
31
  What if you just have the class name for the test?
30
32
 
31
33
  ```
32
- t BlogPostTest
34
+ test_launcher BlogPostTest
33
35
 
34
36
  #=> ruby -I test test/models/blog_post_test.rb
35
37
  ```
@@ -37,14 +39,43 @@ t BlogPostTest
37
39
  But what if you aren't specific enough?
38
40
 
39
41
  ```
40
- t test_blog_na
42
+ test_launcher test_blog_na
41
43
 
42
44
  #=> Found 10 test methods in 3 files.
43
45
  #=> Running most recently edited. Run with '--all' to run all the tests.
44
46
  #=> ruby -I test test/models/blog_post_test.rb --name=test_blog_name_thing
45
47
  ```
46
48
 
47
- Super fun? OH YEAH!
49
+ What if you are very specific?
50
+ ```
51
+ test_launcher /Users/username/code/my_repo/test/models/blog_post_test.rb
52
+
53
+ #=> ruby -I test test/models/blog_post_test.rb
54
+ ```
55
+
56
+ ### Inline Gems
57
+
58
+ Test Launcher will automatically move to the correct subdirectory in order to run the tests. For example, if `thing_test.rb` is within your inline_gem, you can run:
59
+
60
+ ```
61
+ test_launcher thing_test
62
+
63
+ #=> cd /path/to/inline_gem && ruby -I test test/thing_test.rb
64
+ ```
65
+
66
+ You don't have to run Test Launcher from the root of your project either. It will figure things out.
67
+
68
+ ### Spring preloader
69
+
70
+ Test Launcher will check for the spring/testunit binstubs. If they are found in the app/gem/engine it will use spring:
71
+
72
+ ```
73
+ test_launcher springified_test
74
+
75
+ #=> cd /path/to/app && spring testunit test/springified_test.rb
76
+ ```
77
+
78
+ Test Launcher will not use spring if the `DISABLE_SPRING=1` environment variable is set.
48
79
 
49
80
  #Installation
50
81
 
@@ -54,27 +85,33 @@ To install:
54
85
  gem install test_launcher
55
86
  ```
56
87
 
88
+ Under the hood it uses git to search for files and to grep, so it will only work in git repositories.
89
+
90
+
57
91
  #Setup
58
92
 
59
- This gem installs one executable called `test_launcher`. That executable must be called with the `find` method, like so:
93
+ This gem installs one executable called `test_launcher`.
60
94
 
61
95
  ```
62
- test_launcher find test_name_to_find
96
+ test_launcher test_name_to_find
63
97
  ```
64
98
 
65
99
  For me, that's way too much to type, so I recommend adding an alias to your `.bash_profile` like so:
66
100
 
67
101
  ```
68
- alias t="test_launcher find"
102
+ alias t='test_launcher'
103
+
104
+ # If you are using RVM, use this: (see below for more details)
105
+ alias t='NOEXEC_DISABLE=1 test_launcher'
69
106
  ```
70
107
 
71
- Now you can just type `t` instead of `test_launcher find`. Much nicer!
108
+ Now you can just type `t` instead of `test_launcher`. Much nicer!
72
109
 
73
110
  #Usage
74
111
 
75
112
  Test Launcher searches for tests based on your input.
76
113
 
77
- Suppose you type `t thing`. It will run tests using this priority preference:
114
+ Suppose you type `test_launcher thing`. It will run tests using this priority preference:
78
115
 
79
116
  1. A single, specific test method name or partial name
80
117
  - `def test_the_thing`
@@ -88,20 +125,66 @@ Suppose you type `t thing`. It will run tests using this priority preference:
88
125
  1. Any test file based on a generic search
89
126
  - runs `stuff_test.rb` because it found the word `thing` inside of it
90
127
 
91
- Any time it matches multiple files, it will default to running the most recently edited file. You can append `--all` if you want to run all matching tests.
128
+ Any time it matches multiple files, it will default to running the most recently edited file. You can append `--all` if you want to run all matching tests, even if they are in different engines/gems!
92
129
 
93
- #Does it work with inline gems?
130
+ # RubyMine Support
94
131
 
95
- Yes!
132
+ When working with inline gems/engines, RubyMine has a hard time figuring out what `test` folders to push into the load path for Minitest. RubyMine also does not understand that in a project with inline engines, some of them may use Spring and some may not. When working with inline gems/engines/apps in RubyMine, you end up having to 'Edit Configurations...' many times a day. This is a bummer.
96
133
 
97
- Test Launcher will automatically move to the correct subdirectory in order to run the tests. For example, if `thing_test.rb` is within your inline_gem, you can run:
134
+ Test Launcher can be used from RubyMine to help alleviate these problems. Requiring the `test_launcher/rubymine` file in your run configurations will allow Test Launcher to fix RubyMine's test running to do what you want.
135
+
136
+ To use the RubyMine support:
98
137
 
138
+ 1. Open your project
139
+ 1. Click on Run -> 'Edit Configurations...'
140
+ 1. If you have any run configurations listed under 'Test::Unit/Shoulda/Minitest', use the minus button to remove them.
141
+ 1. Open the 'Defaults' and click on 'Test::Unit/Shoulda/Minitest'
142
+ 1. Under 'Ruby Arguments' change:
99
143
 
100
144
  ```
101
- t thing_test
145
+ -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)`
146
+ ```
147
+
148
+ Replace it with:
102
149
 
103
- #=> cd ./path/to/inline_gem && ruby -I test test/thing_test.rb
150
+ ```
151
+ -r test_launcher/rubymine
104
152
  ```
105
153
 
106
- You don't have to run Test Launcher from the root of your project either. It will figure things out.
154
+ 1. Run a test. Test Launcher should report that it is hijacking the test and it will output the command that it has decided to use.
155
+
156
+ ### Debugging Support
157
+
158
+ Using Test Launcher to hijack your RubyMine run configuration should allow you to debug any test as well without issue.
159
+
160
+ # Optimizing with RVM
161
+
162
+ By default, RVM installs a hook to remove the need to run `bundle exec`. When you run a gem command, it will search your bundle to see if that command is included in your bundle. If it is, it will run that version of the command. If it's not in your bundle, then it will fall back to the global gem. You can read more about it on [rubygems-bundler](https://github.com/rvm/rubygems-bundler).
163
+
164
+ Test Launcher is not installed in your bundle. This means that the time that Bundler spends resolving your Gemfile to check if there's a test\_launcher executable in your bundle is wasted. For most projects, the amount of time this takes is probably unnoticeable.
107
165
 
166
+ On projects with lots of dependencies, this wasted time can be significant.
167
+
168
+ For example, in a large project, we get a nice improvement:
169
+
170
+ ```
171
+ $:time test_launcher something_that_no_test_says
172
+ #=> Could not find any tests.
173
+
174
+ #=> real 0m2.214s
175
+ #=> user 0m1.407s
176
+ #=> sys 0m1.062s
177
+
178
+ $:time NOEXEC_DISABLE=1 test_launcher something_that_no_test_might_say
179
+ #=> Could not find any tests.
180
+
181
+ #=> real 0m1.412s
182
+ #=> user 0m0.745s
183
+ #=> sys 0m0.945s
184
+ ```
185
+
186
+ I suggest that if you are using RVM, you may as well make this your alias:
187
+
188
+ ```
189
+ alias t='NOEXEC_DISABLE=1 test_launcher'
190
+ ```
data/Rakefile CHANGED
@@ -1,2 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = Dir.glob("test/test_launcher/**/*_test.rb").reject {|f| f.match("fixtures")}
6
+ end
7
+
8
+ task :default => [:test]
@@ -1,39 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "thor"
4
- require "test_launcher/searchers/git_searcher"
5
- require "test_launcher/tests/minitest/finder"
6
- require "test_launcher/tests/minitest/consolidator"
7
- require "test_launcher/shell/runner"
3
+ require "test_launcher/cli/input_parser"
4
+ require "test_launcher"
8
5
 
9
- class CLI < Thor
6
+ input = TestLauncher::CLI::InputParser.new(ARGV)
10
7
 
11
- desc "find", <<-DESC
12
- Find tests and run them. By trying to match an individual test or the name of a test file(s).
13
- DESC
14
- option :all, type: :boolean, desc: %{Run all tests found!}, default: false
15
-
16
- def find(input)
17
- if input == '--help'
18
- `test_launcher --help find`
19
- exit
20
- end
21
-
22
- shell = TestLauncher::Shell::Runner.new(
23
- log_path: '/tmp/test_launcher.log',
24
- working_directory: '.',
25
-
26
- )
27
-
28
- searcher = TestLauncher::Searchers::GitSearcher.new(shell)
29
- search_results = TestLauncher::Tests::Minitest::Finder.find(input, searcher)
30
-
31
- test_wrapper = TestLauncher::Tests::Minitest::Consolidator.consolidate(search_results, shell, options[:all])
32
-
33
- shell.exec test_wrapper.to_command
34
- end
35
-
36
- default_task :find
37
- end
38
-
39
- CLI.start(ARGV)
8
+ TestLauncher.launch(
9
+ input.query,
10
+ run_all: input.options[:run_all],
11
+ framework: input.options[:framework]
12
+ )
@@ -1,4 +1,26 @@
1
1
  require "test_launcher/version"
2
2
 
3
+ require "test_launcher/shell/runner"
4
+ require "test_launcher/search/git"
5
+ require "test_launcher/frameworks"
6
+
3
7
  module TestLauncher
8
+ def self.launch(input, framework: "guess", run_all: false)
9
+ shell = Shell::Runner.new(log_path: '/tmp/test_launcher.log')
10
+ searcher = Searchers::Git.new(shell)
11
+
12
+ command = Frameworks.locate(
13
+ framework_name: framework,
14
+ shell: shell,
15
+ searcher: searcher,
16
+ input: input,
17
+ run_all: run_all
18
+ )
19
+
20
+ if command
21
+ shell.exec command
22
+ else
23
+ shell.warn "No tests found."
24
+ end
25
+ end
4
26
  end
@@ -0,0 +1,73 @@
1
+ require "test_launcher/version"
2
+ require "optparse"
3
+
4
+ module TestLauncher
5
+ module CLI
6
+ class InputParser
7
+ ParseError = Class.new(RuntimeError)
8
+
9
+ BANNER = <<-DESC
10
+ Find tests and run them by trying to match an individual test or the name of a test file(s).
11
+
12
+ See full README: https://github.com/petekinnecom/test_launcher
13
+
14
+ Usage: `test_launcher "search string" [--all]`
15
+
16
+ VERSION: #{TestLauncher::VERSION}
17
+
18
+ DESC
19
+
20
+ def initialize(args)
21
+ @query = args
22
+ @options = {}
23
+ option_parser.parse!(args)
24
+ rescue OptionParser::ParseError
25
+ puts "Invalid arguments"
26
+ puts "----"
27
+ puts option_parser
28
+ exit
29
+ end
30
+
31
+ def query
32
+ if @query.size == 0
33
+ puts option_parser
34
+ exit
35
+ elsif @query.size > 1
36
+ puts "Concatenating args to single string. (see https://github.com/petekinnecom/test_launcher)"
37
+ end
38
+
39
+ @query.join(" ")
40
+ end
41
+
42
+ def options
43
+ @options
44
+ end
45
+
46
+ private
47
+
48
+ def option_parser
49
+ OptionParser.new do |opts|
50
+ opts.banner = BANNER
51
+
52
+ opts.on("-a", "--all", "Run all matching tests. Defaults to false.") do
53
+ options[:run_all] = true
54
+ end
55
+
56
+ opts.on("-h", "--help", "Prints this help") do
57
+ puts opts
58
+ exit
59
+ end
60
+
61
+ opts.on("-v", "--version", "Display the version info") do
62
+ puts TestLauncher::VERSION
63
+ exit
64
+ end
65
+
66
+ opts.on("-f", "--framework framework", "The testing framework being used. Valid options: ['minitest', 'rspec', 'guess']. Defaults to 'guess'") do |framework|
67
+ options[:framework] = framework
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,32 @@
1
+ require "test_launcher/frameworks/base"
2
+ require "test_launcher/frameworks/minitest"
3
+ require "test_launcher/frameworks/rspec"
4
+
5
+ module TestLauncher
6
+ module Frameworks
7
+ def self.locate(framework_name:, input:, run_all:, shell:, searcher:)
8
+ frameworks = guess_frameworks(framework_name)
9
+
10
+ frameworks.each do |framework|
11
+ search_results = framework::Locator.new(input, searcher).prioritized_results
12
+ runner = framework::Runner.new
13
+
14
+ command = Implementation::Consolidator.consolidate(search_results, shell, runner, run_all)
15
+
16
+ return command if command
17
+ end
18
+
19
+ nil
20
+ end
21
+
22
+ def self.guess_frameworks(framework_name)
23
+ if framework_name == "rspec"
24
+ [RSpec]
25
+ elsif framework_name == "minitest"
26
+ [Minitest]
27
+ else
28
+ [Minitest, RSpec].select(&:active?)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ require "test_launcher/frameworks/implementation/locator"
2
+ require "test_launcher/frameworks/implementation/test_case"
3
+ require "test_launcher/frameworks/implementation/consolidator"
4
+
5
+ module TestLauncher
6
+ module Frameworks
7
+ module Base
8
+ class Locator < Implementation::Locator
9
+ def file_name_regex
10
+ # for ruby to match on file names
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def file_name_pattern
15
+ # for bash to match on file names
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def regex_pattern
20
+ # to match on examples
21
+ raise NotImplementedError
22
+ end
23
+ end
24
+
25
+ class Runner
26
+ def single_example(test_case)
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def one_or_more_files(test_cases)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def single_file(test_case)
35
+ one_or_more_files([test_case])
36
+ end
37
+
38
+ def multiple_files(collection)
39
+ collection
40
+ .group_by(&:app_root)
41
+ .map { |_root, test_cases| one_or_more_files(test_cases) }
42
+ .join("; cd -;\n\n")
43
+ end
44
+ end
45
+
46
+ class TestCase < Implementation::TestCase
47
+ def test_root_folder_name
48
+ # directory where tests are found
49
+ raise NotImplementedError
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end