test_launcher 1.5.0 → 1.5.1
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 +4 -4
- data/README.md +18 -0
- data/bin/test_launcher +2 -5
- data/lib/test_launcher/cli/input_parser.rb +37 -12
- data/lib/test_launcher/cli/query.rb +30 -0
- data/lib/test_launcher/cli/request.rb +61 -0
- data/lib/test_launcher/cli.rb +44 -0
- data/lib/test_launcher/frameworks/base.rb +26 -7
- data/lib/test_launcher/frameworks/elixir.rb +84 -0
- data/lib/test_launcher/frameworks/implementation/test_case.rb +4 -7
- data/lib/test_launcher/frameworks/minitest.rb +80 -23
- data/lib/test_launcher/frameworks/rspec.rb +38 -13
- data/lib/test_launcher/queries.rb +346 -0
- data/lib/test_launcher/rubymine/launcher.rb +1 -12
- data/lib/test_launcher/rubymine/request.rb +15 -0
- data/lib/test_launcher/rubymine.rb +20 -13
- data/lib/test_launcher/search/ag.rb +96 -0
- data/lib/test_launcher/search/git.rb +6 -2
- data/lib/test_launcher/search.rb +18 -0
- data/lib/test_launcher/shell/runner.rb +2 -1
- data/lib/test_launcher/version.rb +1 -1
- data/lib/test_launcher.rb +0 -26
- data/test/test_helper.rb +2 -1
- data/test/test_helpers/integration_helper.rb +40 -0
- data/test/test_helpers/mock.rb +59 -0
- data/test/test_helpers/mock_searcher.rb +1 -0
- data/test/test_helpers/mocks/searcher_mock.rb +82 -0
- data/test/test_helpers/mocks.rb +76 -0
- data/test/test_launcher/cli/input_parser_test.rb +72 -0
- data/test/test_launcher/frameworks/minitest/runner_test.rb +72 -0
- data/test/test_launcher/frameworks/minitest/searcher_test.rb +109 -0
- data/test/test_launcher/frameworks/rspec/runner_test.rb +76 -0
- data/test/test_launcher/frameworks/rspec/searcher_test.rb +54 -0
- data/test/test_launcher/minitest_integration_test.rb +31 -40
- data/test/test_launcher/queries/example_name_query_test.rb +217 -0
- data/test/test_launcher/queries/full_regex_query_test.rb +153 -0
- data/test/test_launcher/queries/generic_query_test.rb +23 -0
- data/test/test_launcher/queries/line_number_query_test.rb +107 -0
- data/test/test_launcher/queries/multi_term_query_test.rb +138 -0
- data/test/test_launcher/queries/path_query_test.rb +192 -0
- data/test/test_launcher/queries/search_query_test.rb +54 -0
- data/test/test_launcher/queries/single_term_query_test.rb +36 -0
- data/test/test_launcher/queries/specified_name_query_test.rb +112 -0
- data/test/test_launcher/rspec_integration_test.rb +27 -41
- data/test/test_launcher/search/git_test.rb +2 -0
- metadata +49 -10
- data/lib/test_launcher/frameworks/implementation/collection.rb +0 -36
- data/lib/test_launcher/frameworks/implementation/consolidator.rb +0 -83
- data/lib/test_launcher/frameworks/implementation/locator.rb +0 -118
- data/lib/test_launcher/frameworks.rb +0 -20
- data/lib/test_launcher/request.rb +0 -36
- data/test/test_launcher/frameworks/implementation/locator_test.rb +0 -166
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e18c5338873c55199563af9ddc95cf56e55efe76
|
4
|
+
data.tar.gz: 6c0f7ff4e88fe6cfbcc6feecae0aed593783b6c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acb65869157cd0f35d51e713df0e0ac917773320a412b305644f0e19539221ecc92cb4e25ec32d3b853b203c5a4931efda457a0c0882988f4502c1d4ab3c06c6
|
7
|
+
data.tar.gz: 1b42332fa3e556a0ca035da62641a452fed3b607d4cc0026c6309c4dc7e2ffa096193db1b8385a7ae345386320b014ff37a48519c328f7b1c4ab58192fc8d23d
|
data/README.md
CHANGED
@@ -101,6 +101,24 @@ git diff --name-only --diff-filter=ACMTUXB origin/master | grep _test.rb | xargs
|
|
101
101
|
```
|
102
102
|
(see https://git-scm.com/docs/git-diff)
|
103
103
|
|
104
|
+
|
105
|
+
```
|
106
|
+
function tdiff()
|
107
|
+
{
|
108
|
+
git diff --name-only --diff-filter=ACMTUXB $@ | grep _test.rb | xargs test_launcher
|
109
|
+
}
|
110
|
+
|
111
|
+
# Now you can:
|
112
|
+
|
113
|
+
tdiff
|
114
|
+
|
115
|
+
# or
|
116
|
+
|
117
|
+
tdiff origin/master
|
118
|
+
```
|
119
|
+
|
120
|
+
Super fun!
|
121
|
+
|
104
122
|
#Installation
|
105
123
|
|
106
124
|
To install:
|
data/bin/test_launcher
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
require "optparse"
|
2
2
|
|
3
3
|
require "test_launcher/version"
|
4
|
-
|
4
|
+
|
5
|
+
require "test_launcher/frameworks/rspec"
|
6
|
+
require "test_launcher/frameworks/minitest"
|
7
|
+
require "test_launcher/frameworks/elixir"
|
8
|
+
require "test_launcher/cli/request"
|
5
9
|
|
6
10
|
module TestLauncher
|
7
11
|
module CLI
|
@@ -19,8 +23,9 @@ VERSION: #{TestLauncher::VERSION}
|
|
19
23
|
|
20
24
|
DESC
|
21
25
|
|
22
|
-
def initialize(args)
|
23
|
-
@
|
26
|
+
def initialize(args, env)
|
27
|
+
@search_string = args
|
28
|
+
@env = env
|
24
29
|
@options = {}
|
25
30
|
option_parser.parse!(args)
|
26
31
|
rescue OptionParser::ParseError
|
@@ -30,18 +35,34 @@ VERSION: #{TestLauncher::VERSION}
|
|
30
35
|
exit
|
31
36
|
end
|
32
37
|
|
33
|
-
def
|
34
|
-
if @
|
38
|
+
def requests(shell:, searcher:)
|
39
|
+
if @search_string.size == 0
|
35
40
|
puts option_parser
|
36
41
|
exit
|
37
42
|
end
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
frameworks =
|
45
|
+
if @options[:framework] == "rspec"
|
46
|
+
[Frameworks::RSpec]
|
47
|
+
elsif @options[:framework] == "minitest"
|
48
|
+
[Frameworks::Minitest]
|
49
|
+
elsif @options[:framework] == "elixir"
|
50
|
+
[Frameworks::Elixir]
|
51
|
+
else
|
52
|
+
[Frameworks::Minitest, Frameworks::RSpec, Frameworks::Elixir]
|
53
|
+
end
|
54
|
+
|
55
|
+
frameworks.map {|framework|
|
56
|
+
Request.new(
|
57
|
+
search_string: @search_string.join(" "),
|
58
|
+
run_all: !!@options[:run_all],
|
59
|
+
disable_spring: !!@env["DISABLE_SPRING"],
|
60
|
+
example_name: @options[:name],
|
61
|
+
framework: framework,
|
62
|
+
shell: shell,
|
63
|
+
searcher: searcher
|
64
|
+
)
|
65
|
+
}
|
45
66
|
end
|
46
67
|
|
47
68
|
def options
|
@@ -68,9 +89,13 @@ VERSION: #{TestLauncher::VERSION}
|
|
68
89
|
exit
|
69
90
|
end
|
70
91
|
|
71
|
-
opts.on("-f", "--framework framework", "The testing framework being used. Valid options: ['minitest', 'rspec', 'guess']. Defaults to 'guess'") do |framework|
|
92
|
+
opts.on("-f", "--framework framework", "The testing framework being used. Valid options: ['minitest', 'rspec', 'elixir', 'guess']. Defaults to 'guess'") do |framework|
|
72
93
|
options[:framework] = framework
|
73
94
|
end
|
95
|
+
|
96
|
+
opts.on("-n", "--name name", "Minitest name of testcase to run") do |name|
|
97
|
+
options[:name] = name
|
98
|
+
end
|
74
99
|
end
|
75
100
|
end
|
76
101
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test_launcher/base_error"
|
2
|
+
require "test_launcher/queries"
|
3
|
+
require "test_launcher/cli/request"
|
4
|
+
|
5
|
+
module TestLauncher
|
6
|
+
module CLI
|
7
|
+
class Query < BaseQuery
|
8
|
+
attr_reader :shell, :searcher
|
9
|
+
|
10
|
+
def command
|
11
|
+
def queries
|
12
|
+
requests.map {|request| Queries::GenericQuery.new(request: request)}
|
13
|
+
end
|
14
|
+
|
15
|
+
def requests
|
16
|
+
@frameworks.map {|framework|
|
17
|
+
Request.new(
|
18
|
+
framework: framework,
|
19
|
+
search_string: @search_string,
|
20
|
+
run_all: @run_all,
|
21
|
+
disable_spring: @disable_spring,
|
22
|
+
example_name: @example_name,
|
23
|
+
shell: shell,
|
24
|
+
searcher: searcher
|
25
|
+
)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module TestLauncher
|
2
|
+
module CLI
|
3
|
+
class Request
|
4
|
+
def initialize(
|
5
|
+
search_string:,
|
6
|
+
framework:,
|
7
|
+
run_all: false,
|
8
|
+
disable_spring: false,
|
9
|
+
example_name: nil,
|
10
|
+
shell:,
|
11
|
+
searcher:
|
12
|
+
)
|
13
|
+
@search_string = search_string
|
14
|
+
@framework = framework
|
15
|
+
@run_all = run_all
|
16
|
+
@disable_spring = disable_spring
|
17
|
+
@example_name = example_name
|
18
|
+
@shell = shell
|
19
|
+
@searcher = searcher
|
20
|
+
end
|
21
|
+
|
22
|
+
def search_string
|
23
|
+
@search_string
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_all?
|
27
|
+
@run_all
|
28
|
+
end
|
29
|
+
|
30
|
+
def disable_spring?
|
31
|
+
@disable_spring
|
32
|
+
end
|
33
|
+
|
34
|
+
def example_name
|
35
|
+
@example_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def searcher
|
39
|
+
framework.searcher(@searcher)
|
40
|
+
end
|
41
|
+
|
42
|
+
def runner(*a)
|
43
|
+
framework.runner(*a)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_case(*a)
|
47
|
+
framework.test_case(*a)
|
48
|
+
end
|
49
|
+
|
50
|
+
def shell
|
51
|
+
@shell
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def framework
|
57
|
+
@framework
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "test_launcher/shell/runner"
|
2
|
+
require "test_launcher/search"
|
3
|
+
require "test_launcher/cli/input_parser"
|
4
|
+
require "test_launcher/queries"
|
5
|
+
|
6
|
+
module TestLauncher
|
7
|
+
module CLI
|
8
|
+
|
9
|
+
class MultiRequestQuery < Struct.new(:requests)
|
10
|
+
|
11
|
+
def command
|
12
|
+
command = nil
|
13
|
+
command_finders.each do |command_finder|
|
14
|
+
command = command_finder.generic_search
|
15
|
+
break if command
|
16
|
+
end
|
17
|
+
command
|
18
|
+
end
|
19
|
+
|
20
|
+
def command_finders
|
21
|
+
requests.map {|request| Queries::CommandFinder.new(request)}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.launch(argv, env, shell: Shell::Runner.new(log_path: "/tmp/test_launcher.log"))
|
26
|
+
searcher = Search.searcher(shell)
|
27
|
+
|
28
|
+
requests = CLI::InputParser.new(
|
29
|
+
argv,
|
30
|
+
env
|
31
|
+
).requests(shell: shell, searcher: searcher)
|
32
|
+
|
33
|
+
command = MultiRequestQuery.new(requests).command
|
34
|
+
|
35
|
+
if command
|
36
|
+
shell.exec command
|
37
|
+
else
|
38
|
+
shell.warn "No tests found."
|
39
|
+
end
|
40
|
+
rescue BaseError => e
|
41
|
+
shell.warn(e)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,23 +1,38 @@
|
|
1
|
-
require "test_launcher/frameworks/implementation/locator"
|
2
1
|
require "test_launcher/frameworks/implementation/test_case"
|
3
|
-
require "test_launcher/frameworks/implementation/consolidator"
|
4
2
|
|
5
3
|
module TestLauncher
|
6
4
|
module Frameworks
|
7
5
|
module Base
|
8
|
-
class
|
6
|
+
class Searcher < Struct.new(:raw_searcher)
|
7
|
+
def test_files(query)
|
8
|
+
raw_searcher
|
9
|
+
.find_files(query)
|
10
|
+
.select {|f| f.match(file_name_regex)}
|
11
|
+
end
|
12
|
+
|
13
|
+
def examples(query)
|
14
|
+
grep(example_name_regex(query))
|
15
|
+
end
|
16
|
+
|
17
|
+
def grep(regex)
|
18
|
+
raw_searcher.grep(regex, file_pattern: file_name_pattern)
|
19
|
+
end
|
20
|
+
|
21
|
+
def by_line(file_pattern, line_number)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
9
27
|
def file_name_regex
|
10
|
-
# for ruby to match on file names
|
11
28
|
raise NotImplementedError
|
12
29
|
end
|
13
30
|
|
14
31
|
def file_name_pattern
|
15
|
-
# for bash to match on file names
|
16
32
|
raise NotImplementedError
|
17
33
|
end
|
18
34
|
|
19
|
-
def
|
20
|
-
# to match on examples
|
35
|
+
def example_name_regex(query)
|
21
36
|
raise NotImplementedError
|
22
37
|
end
|
23
38
|
end
|
@@ -27,6 +42,10 @@ module TestLauncher
|
|
27
42
|
raise NotImplementedError
|
28
43
|
end
|
29
44
|
|
45
|
+
def multiple_examples_same_file(test_cases)
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
|
30
49
|
def one_or_more_files(test_cases)
|
31
50
|
raise NotImplementedError
|
32
51
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "test_launcher/frameworks/base"
|
2
|
+
require "test_launcher/base_error"
|
3
|
+
|
4
|
+
module TestLauncher
|
5
|
+
module Frameworks
|
6
|
+
module Elixir
|
7
|
+
def self.active?
|
8
|
+
# Do not do this outside of the shell.
|
9
|
+
! Dir.glob("**/test/**/*.exs").empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.test_case(*a)
|
13
|
+
TestCase.new(*a)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.searcher(*a)
|
17
|
+
Searcher.new(*a)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.runner(*a)
|
21
|
+
Runner.new(*a)
|
22
|
+
end
|
23
|
+
|
24
|
+
class Searcher < Base::Searcher
|
25
|
+
MultipleByLineMatches = Class.new(BaseError)
|
26
|
+
|
27
|
+
def by_line(file_pattern, line_number)
|
28
|
+
files = test_files(file_pattern)
|
29
|
+
return unless files.any?
|
30
|
+
raise multiple_files_error if files.size > 1
|
31
|
+
|
32
|
+
{
|
33
|
+
file: files.first,
|
34
|
+
line_number: line_number
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def file_name_regex
|
41
|
+
/.*_test\.exs$/
|
42
|
+
end
|
43
|
+
|
44
|
+
def file_name_pattern
|
45
|
+
"*_test.exs"
|
46
|
+
end
|
47
|
+
|
48
|
+
def example_name_regex(query="")
|
49
|
+
"^\s*test\s+\".*#{query}.*\"\s+do"
|
50
|
+
end
|
51
|
+
|
52
|
+
def multiple_files_error
|
53
|
+
MultipleByLineMatches.new(<<-MSG)
|
54
|
+
It looks like you are running a line number in a test file.
|
55
|
+
|
56
|
+
Multiple files have been found that match your query.
|
57
|
+
|
58
|
+
This case is not supported.
|
59
|
+
MSG
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Runner < Base::Runner
|
64
|
+
def single_example(test_case)
|
65
|
+
%{cd #{test_case.app_root} && mix test #{test_case.file}:#{test_case.line_number}}
|
66
|
+
end
|
67
|
+
|
68
|
+
def multiple_examples_same_file(test_cases)
|
69
|
+
one_or_more_files(test_cases.first)
|
70
|
+
end
|
71
|
+
|
72
|
+
def one_or_more_files(test_cases)
|
73
|
+
%{cd #{test_cases.first.app_root} && mix test #{test_cases.map(&:file).join(" ")}}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class TestCase < Base::TestCase
|
78
|
+
def test_root_dir_name
|
79
|
+
"test"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -4,15 +4,16 @@ module TestLauncher
|
|
4
4
|
module Frameworks
|
5
5
|
module Implementation
|
6
6
|
class TestCase
|
7
|
-
attr_reader :file, :example, :request
|
7
|
+
attr_reader :file, :example, :request, :line_number
|
8
8
|
|
9
9
|
def self.from_search(file:, query:, request:)
|
10
10
|
new(file: file, example: query, request: request)
|
11
11
|
end
|
12
12
|
|
13
|
-
def initialize(file:, example: nil, request:)
|
13
|
+
def initialize(file:, example: nil, request:, line_number: nil)
|
14
14
|
@file = file
|
15
15
|
@example = example
|
16
|
+
@line_number = line_number
|
16
17
|
@request = request
|
17
18
|
end
|
18
19
|
|
@@ -31,7 +32,7 @@ module TestLauncher
|
|
31
32
|
while !candidates.empty?
|
32
33
|
if candidates.last == test_root_dir_name
|
33
34
|
root_path = File.join("/", candidates[0..-2])
|
34
|
-
return root_path if Dir.entries(root_path).any? {|e| e.match /Gemfile|gemspec/}
|
35
|
+
return root_path if Dir.entries(root_path).any? {|e| e.match /Gemfile|gemspec|mix.exs/} # TODO: extract this
|
35
36
|
end
|
36
37
|
|
37
38
|
candidates.pop
|
@@ -46,10 +47,6 @@ module TestLauncher
|
|
46
47
|
File.join(app_root, test_root_dir_name)
|
47
48
|
end
|
48
49
|
|
49
|
-
def runner
|
50
|
-
raise NotImplementedError
|
51
|
-
end
|
52
|
-
|
53
50
|
def test_root_dir_name
|
54
51
|
raise NotImplementedError
|
55
52
|
end
|
@@ -1,53 +1,104 @@
|
|
1
|
+
require 'shellwords'
|
1
2
|
require "test_launcher/frameworks/base"
|
3
|
+
require "test_launcher/base_error"
|
2
4
|
|
3
5
|
module TestLauncher
|
4
6
|
module Frameworks
|
5
7
|
module Minitest
|
6
|
-
|
7
8
|
def self.active?
|
9
|
+
# Do not do this outside of the shell.
|
8
10
|
! Dir.glob("**/test/**/*_test.rb").empty?
|
9
11
|
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
def self.test_case(*a)
|
14
|
+
TestCase.new(*a)
|
15
|
+
end
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
"--name=/#{test_case.example}/"
|
19
|
-
end
|
17
|
+
def self.searcher(*a)
|
18
|
+
Searcher.new(*a)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
def self.runner(*a)
|
22
|
+
Runner.new(*a)
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
class Searcher < Base::Searcher
|
26
|
+
MultipleByLineMatches = Class.new(BaseError)
|
27
|
+
|
28
|
+
def by_line(file_pattern, line_number)
|
29
|
+
files = test_files(file_pattern)
|
30
|
+
return unless files.any?
|
31
|
+
raise multiple_files_error if files.size > 1
|
32
|
+
#
|
33
|
+
file = files.first
|
34
|
+
grep_results = raw_searcher.grep(example_name_regex, file_pattern: file)
|
35
|
+
# return unless grep_results.any?
|
36
|
+
best_result =
|
37
|
+
grep_results
|
38
|
+
.select {|r| line_number >= r[:line_number]}
|
39
|
+
.min_by {|r| line_number - r[:line_number]}
|
40
|
+
|
41
|
+
if best_result
|
42
|
+
{
|
43
|
+
file: best_result[:file],
|
44
|
+
example_name: best_result[:line].match(/(test_\w+)/)[1],
|
45
|
+
line_number: best_result[:line_number]
|
46
|
+
}
|
47
|
+
else
|
48
|
+
# line number outside of example. Run whole file
|
49
|
+
{
|
50
|
+
file: grep_results.first[:file]
|
51
|
+
}
|
52
|
+
end
|
26
53
|
end
|
27
|
-
end
|
28
54
|
|
29
|
-
class Locator < Base::Locator
|
30
55
|
private
|
31
56
|
|
32
57
|
def file_name_regex
|
33
|
-
/.*_test\.rb
|
58
|
+
/.*_test\.rb$/
|
34
59
|
end
|
35
60
|
|
36
61
|
def file_name_pattern
|
37
62
|
"*_test.rb"
|
38
63
|
end
|
39
64
|
|
40
|
-
def
|
41
|
-
|
65
|
+
def example_name_regex(query="")
|
66
|
+
if query.match(/^test_/)
|
67
|
+
"^\s*def\s+#{query}.*"
|
68
|
+
else
|
69
|
+
"^\s*def\s+test_.*#{query}.*"
|
70
|
+
end
|
42
71
|
end
|
43
72
|
|
44
|
-
def
|
45
|
-
|
73
|
+
def multiple_files_error
|
74
|
+
MultipleByLineMatches.new(<<-MSG)
|
75
|
+
It looks like you are running a line number in a test file.
|
76
|
+
|
77
|
+
Multiple files have been found that match your query.
|
78
|
+
|
79
|
+
This case is not supported.
|
80
|
+
MSG
|
46
81
|
end
|
82
|
+
|
47
83
|
end
|
48
84
|
|
49
|
-
class
|
85
|
+
class Runner < Base::Runner
|
86
|
+
def single_example(test_case, name: test_case.example)
|
50
87
|
|
88
|
+
%{cd #{test_case.app_root} && #{test_case.runner} #{test_case.file} --name=/#{Shellwords.escape(name)}/}
|
89
|
+
end
|
90
|
+
|
91
|
+
def multiple_examples_same_file(test_cases)
|
92
|
+
test_case = test_cases.first
|
93
|
+
single_example(test_cases.first)
|
94
|
+
end
|
95
|
+
|
96
|
+
def one_or_more_files(test_cases)
|
97
|
+
%{cd #{test_cases.first.app_root} && #{test_cases.first.multiple_files_runner} #{test_cases.map(&:file).join(" ")}}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class TestCase < Base::TestCase
|
51
102
|
def runner
|
52
103
|
if spring_enabled?
|
53
104
|
"bundle exec spring testunit"
|
@@ -58,12 +109,19 @@ module TestLauncher
|
|
58
109
|
end
|
59
110
|
end
|
60
111
|
|
112
|
+
def multiple_files_runner
|
113
|
+
if spring_enabled?
|
114
|
+
"bundle exec spring testunit"
|
115
|
+
else
|
116
|
+
"bundle exec ruby -I test -e 'ARGV.each {|f| require(f)}'"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
61
120
|
def test_root_dir_name
|
62
121
|
"test"
|
63
122
|
end
|
64
123
|
|
65
124
|
def spring_enabled?
|
66
|
-
# TODO: move ENV reference to options hash
|
67
125
|
return false if request.disable_spring?
|
68
126
|
|
69
127
|
[
|
@@ -73,7 +131,6 @@ module TestLauncher
|
|
73
131
|
File.exist?(File.join(app_root, f))
|
74
132
|
}
|
75
133
|
end
|
76
|
-
|
77
134
|
end
|
78
135
|
end
|
79
136
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "shellwords"
|
2
|
-
|
3
2
|
require "test_launcher/frameworks/base"
|
4
3
|
|
5
4
|
module TestLauncher
|
@@ -10,17 +9,31 @@ module TestLauncher
|
|
10
9
|
! Dir.glob("**/*_spec.rb").empty?
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
12
|
+
def self.test_case(*a)
|
13
|
+
TestCase.new(*a)
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def self.searcher(*a)
|
17
|
+
Searcher.new(*a)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.runner(*a)
|
21
|
+
Runner.new(*a)
|
21
22
|
end
|
22
23
|
|
23
|
-
class
|
24
|
+
class Searcher < Base::Searcher
|
25
|
+
|
26
|
+
def by_line(file_pattern, line_number)
|
27
|
+
files = test_files(file_pattern)
|
28
|
+
return unless files.any?
|
29
|
+
raise multiple_files_error if files.size > 1
|
30
|
+
|
31
|
+
{
|
32
|
+
file: files.first,
|
33
|
+
line_number: line_number
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
24
37
|
private
|
25
38
|
|
26
39
|
def file_name_regex
|
@@ -31,12 +44,24 @@ module TestLauncher
|
|
31
44
|
'*_spec.rb'
|
32
45
|
end
|
33
46
|
|
34
|
-
def
|
35
|
-
"^\s*(it|context|(RSpec.)?describe) .*#{
|
47
|
+
def example_name_regex(query)
|
48
|
+
"^\s*(it|context|(RSpec.)?describe) .*#{query}.* do.*"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Runner < Base::Runner
|
53
|
+
def single_example(test_case, **_)
|
54
|
+
%{cd #{test_case.app_root} && rspec #{test_case.file} --example #{Shellwords.escape(test_case.example)}}
|
55
|
+
end
|
56
|
+
|
57
|
+
def multiple_examples_same_file(test_cases)
|
58
|
+
test_case = test_cases.first
|
59
|
+
single_example(test_case)
|
36
60
|
end
|
37
61
|
|
38
|
-
|
39
|
-
|
62
|
+
|
63
|
+
def one_or_more_files(test_cases)
|
64
|
+
%{cd #{test_cases.first.app_root} && rspec #{test_cases.map(&:file).join(" ")}}
|
40
65
|
end
|
41
66
|
end
|
42
67
|
|