test_launcher 1.5.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
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