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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -0
  3. data/bin/test_launcher +2 -5
  4. data/lib/test_launcher/cli/input_parser.rb +37 -12
  5. data/lib/test_launcher/cli/query.rb +30 -0
  6. data/lib/test_launcher/cli/request.rb +61 -0
  7. data/lib/test_launcher/cli.rb +44 -0
  8. data/lib/test_launcher/frameworks/base.rb +26 -7
  9. data/lib/test_launcher/frameworks/elixir.rb +84 -0
  10. data/lib/test_launcher/frameworks/implementation/test_case.rb +4 -7
  11. data/lib/test_launcher/frameworks/minitest.rb +80 -23
  12. data/lib/test_launcher/frameworks/rspec.rb +38 -13
  13. data/lib/test_launcher/queries.rb +346 -0
  14. data/lib/test_launcher/rubymine/launcher.rb +1 -12
  15. data/lib/test_launcher/rubymine/request.rb +15 -0
  16. data/lib/test_launcher/rubymine.rb +20 -13
  17. data/lib/test_launcher/search/ag.rb +96 -0
  18. data/lib/test_launcher/search/git.rb +6 -2
  19. data/lib/test_launcher/search.rb +18 -0
  20. data/lib/test_launcher/shell/runner.rb +2 -1
  21. data/lib/test_launcher/version.rb +1 -1
  22. data/lib/test_launcher.rb +0 -26
  23. data/test/test_helper.rb +2 -1
  24. data/test/test_helpers/integration_helper.rb +40 -0
  25. data/test/test_helpers/mock.rb +59 -0
  26. data/test/test_helpers/mock_searcher.rb +1 -0
  27. data/test/test_helpers/mocks/searcher_mock.rb +82 -0
  28. data/test/test_helpers/mocks.rb +76 -0
  29. data/test/test_launcher/cli/input_parser_test.rb +72 -0
  30. data/test/test_launcher/frameworks/minitest/runner_test.rb +72 -0
  31. data/test/test_launcher/frameworks/minitest/searcher_test.rb +109 -0
  32. data/test/test_launcher/frameworks/rspec/runner_test.rb +76 -0
  33. data/test/test_launcher/frameworks/rspec/searcher_test.rb +54 -0
  34. data/test/test_launcher/minitest_integration_test.rb +31 -40
  35. data/test/test_launcher/queries/example_name_query_test.rb +217 -0
  36. data/test/test_launcher/queries/full_regex_query_test.rb +153 -0
  37. data/test/test_launcher/queries/generic_query_test.rb +23 -0
  38. data/test/test_launcher/queries/line_number_query_test.rb +107 -0
  39. data/test/test_launcher/queries/multi_term_query_test.rb +138 -0
  40. data/test/test_launcher/queries/path_query_test.rb +192 -0
  41. data/test/test_launcher/queries/search_query_test.rb +54 -0
  42. data/test/test_launcher/queries/single_term_query_test.rb +36 -0
  43. data/test/test_launcher/queries/specified_name_query_test.rb +112 -0
  44. data/test/test_launcher/rspec_integration_test.rb +27 -41
  45. data/test/test_launcher/search/git_test.rb +2 -0
  46. metadata +49 -10
  47. data/lib/test_launcher/frameworks/implementation/collection.rb +0 -36
  48. data/lib/test_launcher/frameworks/implementation/consolidator.rb +0 -83
  49. data/lib/test_launcher/frameworks/implementation/locator.rb +0 -118
  50. data/lib/test_launcher/frameworks.rb +0 -20
  51. data/lib/test_launcher/request.rb +0 -36
  52. data/test/test_launcher/frameworks/implementation/locator_test.rb +0 -166
@@ -0,0 +1,59 @@
1
+ class Mock
2
+ UnmockedMethodError = Class.new(StandardError)
3
+ MockingUnimplementedMethodError = Class.new(StandardError)
4
+
5
+ def self.impl(method_name)
6
+ define_method method_name do |*args|
7
+ record_call(method_name, args)
8
+ yield(*args) if block_given?
9
+ end
10
+ end
11
+
12
+ def self.mocks(klass)
13
+ define_method(:mocked_klass) do
14
+ klass
15
+ end
16
+ end
17
+
18
+ def impl(method_name)
19
+ define_singleton_method method_name do |*args|
20
+ record_call(method_name, args)
21
+ yield(*args) if block_given?
22
+ end
23
+ end
24
+
25
+ def initialize(*args)
26
+ @attrs = args.pop || {}
27
+ @klass = args.first if args.any?
28
+ @calls = {}
29
+ yield(self) if block_given?
30
+ raise "Mocked class not specified" unless mocked_klass
31
+ end
32
+
33
+ def recall(method_name)
34
+ @calls[method_name] || []
35
+ end
36
+
37
+ private
38
+
39
+ def method_missing(method_name, *args)
40
+ record_call(method_name, args)
41
+
42
+ if @attrs.key?(method_name)
43
+ @attrs[method_name]
44
+ else
45
+ raise UnmockedMethodError, "#{method_name} is not mocked"
46
+ end
47
+ end
48
+
49
+ def record_call(method_name, args)
50
+ if !mocked_klass.method_defined?(method_name)
51
+ raise MockingUnimplementedMethodError, "#{mocked_klass} does not implement #{method_name}"
52
+ end
53
+ (@calls[method_name] ||= []) << args
54
+ end
55
+
56
+ def mocked_klass
57
+ @klass
58
+ end
59
+ end
@@ -0,0 +1 @@
1
+ require "test_helpers/mock"
@@ -0,0 +1,82 @@
1
+ require "test_helpers/mock"
2
+ require "test_launcher/search/git"
3
+
4
+ module TestLauncher
5
+ class MemorySearcher < Mock
6
+ class FileBuilder
7
+ def path(path)
8
+ @path = path
9
+ end
10
+
11
+ def contents(string)
12
+ @lines = string.split("\n")
13
+ end
14
+
15
+ def mtime(time) # TODO: this doesn't work yet!
16
+ @mtime = time
17
+ end
18
+
19
+ def to_file_mock
20
+ FileMock.new(@path, @lines, @time)
21
+ end
22
+ end
23
+
24
+ class FileMock < Struct.new(:path, :lines, :mtime)
25
+ attr_reader :path, :lines
26
+ def initialize(path, lines, mtime)
27
+ @path = path
28
+ @lines = lines
29
+ File.stubs(:mtime).with(path).returns(mtime)
30
+ end
31
+
32
+ def grep(regex)
33
+ lines
34
+ .each_with_index
35
+ .map {|line_text, line_number|
36
+ {
37
+ file: path,
38
+ line: line_text.strip,
39
+ line_number: line_number + 1
40
+ }
41
+ }
42
+ .select {|result|
43
+ result[:line].match(regex)
44
+ }
45
+ end
46
+ end
47
+
48
+ mocks Search::Git
49
+
50
+ def initialize
51
+ yield(self)
52
+ end
53
+
54
+ def find_files(glob_pattern)
55
+ file_mocks_for_pattern(glob_pattern).map(&:path)
56
+ end
57
+
58
+ def grep(regex, file_pattern: '*')
59
+ file_mocks_for_pattern(file_pattern)
60
+ .flat_map { |file|
61
+ file.grep(regex)
62
+ }
63
+ end
64
+
65
+ def mock_file
66
+ file_builder = FileBuilder.new
67
+ yield(file_builder)
68
+ file_mocks << file_builder.to_file_mock
69
+ end
70
+
71
+ private
72
+
73
+ def file_mocks_for_pattern(glob_pattern)
74
+ regex = glob_pattern.gsub("*", ".*")
75
+ file_mocks.select {|fm| fm.path.match(regex)}
76
+ end
77
+
78
+ def file_mocks
79
+ @file_mocks ||= []
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,76 @@
1
+ require "test_helpers/mock"
2
+ require "test_helpers/mocks/searcher_mock"
3
+
4
+ module TestLauncher
5
+
6
+ require "test_launcher/frameworks/base"
7
+ class MockSearcher < Mock
8
+ mocks Frameworks::Base::Searcher
9
+ end
10
+
11
+ require "test_launcher/shell/runner"
12
+ class MockShell < Mock
13
+ mocks Shell::Runner
14
+
15
+ impl :warn
16
+ impl :notify
17
+ impl :puts
18
+ end
19
+
20
+
21
+ require "test_launcher/queries"
22
+ class MockCommandFinder < Mock
23
+ mocks Queries::CommandFinder
24
+ end
25
+
26
+
27
+ require "test_launcher/cli/request"
28
+ class MockRequest < Mock
29
+ mocks CLI::Request
30
+
31
+ impl :test_case do |*args|
32
+ Frameworks::Implementation::TestCase.new(*args)
33
+ end
34
+ end
35
+
36
+ require "test_launcher/frameworks/base"
37
+ class MockRunner < Mock
38
+ mocks Frameworks::Base::Runner
39
+
40
+ impl(:single_file) { "single_file_return" }
41
+ impl(:multiple_files) { "multiple_files_return" }
42
+ impl(:single_example) { "single_example_return" }
43
+ end
44
+
45
+ require "test_launcher/frameworks/base"
46
+ class MockTestCase < Mock
47
+ mocks Frameworks::Base::TestCase
48
+
49
+ end
50
+
51
+ module DefaultMocks
52
+ def default_searcher
53
+ @default_searcher ||= MockSearcher.new
54
+ end
55
+
56
+ def default_shell
57
+ @default_shell ||= MockShell.new
58
+ end
59
+
60
+ def default_command_finder
61
+ @default_command_finder ||= MockCommandFinder.new
62
+ end
63
+
64
+ def default_request
65
+ @default_runner ||= MockRequest.new
66
+ end
67
+
68
+ def default_runner
69
+ @default_runner ||= MockRunner.new
70
+ end
71
+
72
+ def default_test_case
73
+ @default_test_case ||= MockTestCase.new
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,72 @@
1
+ require "test_helper"
2
+ require "test_launcher/cli/input_parser"
3
+
4
+ module TestLauncher
5
+ module CLI
6
+ class InputParserTest < TestCase
7
+
8
+ def test_request__defaults
9
+ requests = parse("a_string", {})
10
+
11
+ assert_equal "a_string", requests.first.search_string
12
+ assert_equal false, requests.first.run_all?
13
+ assert_equal false, requests.first.disable_spring?
14
+ assert_equal nil, requests.first.example_name
15
+ end
16
+
17
+ def test_request__all
18
+ requests = parse("a_string --all", {})
19
+
20
+ assert_equal "a_string", requests.first.search_string
21
+ assert_equal true, requests.first.run_all?
22
+ end
23
+
24
+ def test_request__disable_spring
25
+ requests = parse("a_string", {"DISABLE_SPRING" => "1"})
26
+
27
+ assert_equal "a_string", requests.first.search_string
28
+ assert_equal true, requests.first.disable_spring?
29
+ end
30
+
31
+ def test_request__example_name
32
+ requests = parse("path/to/file_test.rb --name example_name", {})
33
+
34
+ assert_equal "path/to/file_test.rb", requests.first.search_string
35
+ assert_equal "example_name", requests.first.example_name
36
+ end
37
+
38
+ def test_request__example_name__regex
39
+ requests = parse("path/to/file_test.rb --name /example_name/", {})
40
+
41
+ assert_equal "path/to/file_test.rb", requests.first.search_string
42
+ assert_equal "/example_name/", requests.first.example_name
43
+ end
44
+
45
+ def test_request__example_name__with_equal_sign
46
+ requests = parse("path/to/file_test.rb --name=/example_name/", {})
47
+
48
+ assert_equal "path/to/file_test.rb", requests.first.search_string
49
+ assert_equal "/example_name/", requests.first.example_name
50
+ end
51
+
52
+ def test_request__example_name__short_option
53
+ requests = parse("path/to/file_test.rb -n /example_name/", {})
54
+
55
+ assert_equal "path/to/file_test.rb", requests.first.search_string
56
+ assert_equal "/example_name/", requests.first.example_name
57
+ end
58
+
59
+ def test_joins_spaces
60
+ requests = parse("query with spaces", {})
61
+
62
+ assert_equal "query with spaces", requests.first.search_string
63
+ end
64
+
65
+ private
66
+
67
+ def parse(input, env)
68
+ InputParser.new(input.split(" "), env).requests(shell: dummy_shell, searcher: nil)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,72 @@
1
+ require "test_helper"
2
+ require "test_helpers/mocks"
3
+ require "test_launcher/frameworks/minitest"
4
+
5
+ module TestLauncher
6
+ module Frameworks
7
+ module Minitest
8
+ class RunnerTest < ::TestCase
9
+
10
+ class MockTestCase < Mock
11
+ mocks Minitest::TestCase
12
+ end
13
+
14
+ def test_single_example
15
+ test_case = MockTestCase.new(
16
+ example: "example_name",
17
+ app_root: "app_root",
18
+ runner: "runner",
19
+ file: "file"
20
+ )
21
+ assert_equal "cd app_root && runner file --name=example_name", Runner.new.single_example(test_case)
22
+ end
23
+
24
+ def test_multiple_examples_same_file
25
+ test_cases = [
26
+ MockTestCase.new(
27
+ example: "example_name",
28
+ app_root: "app_root",
29
+ runner: "runner",
30
+ file: "file"
31
+ ),
32
+ MockTestCase.new(
33
+ example: "example_name",
34
+ app_root: "app_root",
35
+ runner: "runner",
36
+ file: "file"
37
+ )
38
+ ]
39
+ assert_equal "cd app_root && runner file --name=/example_name/", Runner.new.multiple_examples_same_file(test_cases)
40
+ end
41
+
42
+ def test_single_file
43
+ test_case = MockTestCase.new(
44
+ example: "example_name",
45
+ app_root: "app_root",
46
+ runner: "runner",
47
+ file: "file"
48
+ )
49
+ assert_equal "cd app_root && runner file", Runner.new.single_file(test_case)
50
+ end
51
+
52
+ def test_one_or_more_files
53
+ test_cases = [
54
+ MockTestCase.new(
55
+ example: "example_name",
56
+ app_root: "app_root",
57
+ runner: "runner",
58
+ file: "file_1"
59
+ ),
60
+ MockTestCase.new(
61
+ example: "example_name",
62
+ app_root: "app_root",
63
+ runner: "runner",
64
+ file: "file_2"
65
+ )
66
+ ]
67
+ assert_equal "cd app_root && runner file_1 file_2", Runner.new.one_or_more_files(test_cases)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,109 @@
1
+ require "test_helper"
2
+ require "test_helpers/mocks"
3
+ require "test_launcher/search/git"
4
+ require "test_launcher/frameworks/minitest"
5
+
6
+ module TestLauncher
7
+ module Frameworks
8
+ module Minitest
9
+ class SearcherTest < ::TestCase
10
+ include DefaultMocks
11
+
12
+ class RawSearcherMock < Mock
13
+ mocks Search::Git
14
+
15
+ impl :grep do |regex, file_pattern:|
16
+ example_name_regex = "^ *def test_.*.*" #TODO: no bueno copying this
17
+ case [regex, file_pattern]
18
+ when [example_name_regex, "test/test_launcher/single_test.rb"]
19
+ [
20
+ {file: "test/test_launcher/single_test.rb", line_number: 8, line: "def test__first"},
21
+ {file: "test/test_launcher/single_test.rb", line_number: 13, line: "def test__second"},
22
+ {file: "test/test_launcher/single_test.rb", line_number: 18, line: "def test__third"},
23
+ ]
24
+ when [example_name_regex, "root_path/non_test_file"]
25
+ []
26
+ when [example_name_regex, "root_path/multiple_1"]
27
+ [
28
+ "test/dir/1_multiple_test.rb:8: def test__first",
29
+ "test/dir/1_multiple_test.rb:13: def test__second",
30
+ ]
31
+ when [example_name_regex, "root_path/multiple_2"]
32
+ [
33
+ "test/dir/2_multiple_test.rb:12: def test__first",
34
+ "test/dir/2_multiple_test.rb:30: def test__second",
35
+ ]
36
+ else
37
+ raise "unmocked search: #{regex}, #{file_pattern}"
38
+ end
39
+ end
40
+
41
+ impl :find_files do |pattern|
42
+ case pattern
43
+ when "not_found_test.rb"
44
+ []
45
+ when "single_test.rb"
46
+ ["test/test_launcher/single_test.rb"]
47
+ when "non_test_file.rb"
48
+ ["non_test_file.rb"]
49
+ when "multiple_test.rb"
50
+ ["test/dir/1_multiple_test.rb", "test/dir/2_multiple_test.rb"]
51
+ else
52
+ raise "unmocked search: #{pattern}"
53
+ end
54
+ end
55
+ end
56
+
57
+ def searcher
58
+ @searcher ||= Searcher.new(RawSearcherMock.new)
59
+ end
60
+
61
+ def test_by_line__file_not_found
62
+ assert_equal nil, searcher.by_line("not_found_test.rb", 1)
63
+ end
64
+
65
+ def test_by_line__file_is_not_test_file
66
+ assert_equal nil, searcher.by_line("non_test_file.rb", 1)
67
+ end
68
+
69
+ def test_by_line__single_file_line_before_all_examples
70
+ expected_result = {file: "test/test_launcher/single_test.rb"}
71
+ assert_equal expected_result, searcher.by_line("single_test.rb", 1)
72
+ end
73
+
74
+ def test_by_line__single_file_line_exact_number
75
+ expected_result = {
76
+ file: "test/test_launcher/single_test.rb",
77
+ example_name: "test__first",
78
+ line_number: 8
79
+ }
80
+ assert_equal expected_result, searcher.by_line("single_test.rb", 8)
81
+ end
82
+
83
+ def test_by_line__single_file_line_after_example
84
+ expected_result = {
85
+ file: "test/test_launcher/single_test.rb",
86
+ example_name: "test__first",
87
+ line_number: 8
88
+ }
89
+ assert_equal expected_result, searcher.by_line("single_test.rb", 10)
90
+ end
91
+
92
+ def test_by_line__single_file_line_after_example_2
93
+ expected_result = {
94
+ file: "test/test_launcher/single_test.rb",
95
+ example_name: "test__second",
96
+ line_number: 13
97
+ }
98
+ assert_equal expected_result, searcher.by_line("single_test.rb", 17)
99
+ end
100
+
101
+ def test_by_line__multiple_files__raises_error_for_now
102
+ assert_raises Searcher::MultipleByLineMatches do
103
+ searcher.by_line("multiple_test.rb", 1)
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,76 @@
1
+ require "test_helper"
2
+ require "test_helpers/mocks"
3
+ require "test_launcher/frameworks/rspec"
4
+
5
+ module TestLauncher
6
+ module Frameworks
7
+ module RSpec
8
+ class RunnerTest < ::TestCase
9
+
10
+ class MockTestCase < Mock
11
+ mocks RSpec::TestCase
12
+ end
13
+
14
+ def test_single_example
15
+ test_case = MockTestCase.new(
16
+ example: "example_name",
17
+ app_root: "app_root",
18
+ file: "file"
19
+ )
20
+ assert_equal "cd app_root && rspec file --example example_name", Runner.new.single_example(test_case)
21
+ end
22
+
23
+ def test_single_example__with_messy_name
24
+ test_case = MockTestCase.new(
25
+ example: "this is it's name :(",
26
+ app_root: "app_root",
27
+ file: "file"
28
+ )
29
+ assert_equal "cd app_root && rspec file --example this\\ is\\ it\\'s\\ name\\ :\\(", Runner.new.single_example(test_case)
30
+ end
31
+
32
+
33
+ def test_multiple_examples_same_file
34
+ test_cases = [
35
+ MockTestCase.new(
36
+ example: "example_name",
37
+ app_root: "app_root",
38
+ file: "file"
39
+ ),
40
+ MockTestCase.new(
41
+ example: "example_name",
42
+ app_root: "app_root",
43
+ file: "file"
44
+ )
45
+ ]
46
+ assert_equal "cd app_root && rspec file --example example_name", Runner.new.multiple_examples_same_file(test_cases)
47
+ end
48
+
49
+ def test_single_file
50
+ test_case = MockTestCase.new(
51
+ example: "example_name",
52
+ app_root: "app_root",
53
+ file: "file"
54
+ )
55
+ assert_equal "cd app_root && rspec file", Runner.new.single_file(test_case)
56
+ end
57
+
58
+ def test_one_or_more_files
59
+ test_cases = [
60
+ MockTestCase.new(
61
+ example: "example_name",
62
+ app_root: "app_root",
63
+ file: "file_1"
64
+ ),
65
+ MockTestCase.new(
66
+ example: "example_name",
67
+ app_root: "app_root",
68
+ file: "file_2"
69
+ )
70
+ ]
71
+ assert_equal "cd app_root && rspec file_1 file_2", Runner.new.one_or_more_files(test_cases)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,54 @@
1
+ require "test_helper"
2
+ require "test_helpers/mocks"
3
+ require "test_launcher/search/git"
4
+ require "test_launcher/frameworks/rspec"
5
+
6
+ module TestLauncher
7
+ module Frameworks
8
+ module RSpec
9
+ class SearcherTest < ::TestCase
10
+ include DefaultMocks
11
+
12
+ class RawSearcherMock < Mock
13
+ mocks Search::Git
14
+
15
+ impl :find_files do |pattern|
16
+ case pattern
17
+ when "not_found_spec.rb"
18
+ []
19
+ when "single_spec.rb"
20
+ ["spec/test_launcher/single_spec.rb"]
21
+ when "non_test_file.rb"
22
+ ["non_test_file.rb"]
23
+ when "multiple_spec.rb"
24
+ ["spec/dir/1_multiple_spec.rb", "spec/dir/2_multiple_spec.rb"]
25
+ else
26
+ raise "unmocked search: #{pattern}"
27
+ end
28
+ end
29
+ end
30
+
31
+ def searcher
32
+ @searcher ||= Searcher.new(RawSearcherMock.new)
33
+ end
34
+
35
+ def test_by_line__file_not_found
36
+ assert_equal nil, searcher.by_line("not_found_spec.rb", 1)
37
+ end
38
+
39
+ def test_by_line__file_is_not_test_file
40
+ assert_equal nil, searcher.by_line("non_test_file.rb", 1)
41
+ end
42
+
43
+ def test_by_line__file_is_found
44
+ expected_result = {
45
+ file: "spec/test_launcher/single_spec.rb",
46
+ line_number: 8
47
+ }
48
+
49
+ assert_equal expected_result, searcher.by_line("single_spec.rb", 8)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end