test_run 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bec50a9c524cc40a441ef84656924dde66c64180
4
- data.tar.gz: e169e16a035000ab3d166b321154aa0a48cf4b45
3
+ metadata.gz: a15a71d527a5bfc218b66b112fa17c190206b667
4
+ data.tar.gz: ae00269c6b9506995cb3c62106e0e2eea9a9513e
5
5
  SHA512:
6
- metadata.gz: ad89e33583acd9308650adda78584da91bcf2eb6d4d757afe549694627772f9e382b7f8a1dacb45e4b97db1f13bc6b299e8820692f693279005fd415df6019f2
7
- data.tar.gz: 8ff9dcd11e12cd9d18ce096deeaa64c479d3224ace21cb659dd6974400be0a77dad6250a2661c359773eee64aed2044d6733fb11321e30ad92ce057fe5c6530a
6
+ metadata.gz: 2550c215d5d98b04d1f1333acc3c79ebba130beaf92db8caa8eee08a5e94aa39105915eeb799bfddca7d9e6c4c56c8ad2faade2d85221cc3218bc9c3effaf3a9
7
+ data.tar.gz: 4758c47037e7588ec9dcbfbb55d863217f7bc15179fa29661e5130dbc053cc3e202af640bf5ad1f06109fa6dd36a511680956ab72c8fffd9489e1787d4beed88
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ notes.txt
data/bin/test_runner ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "test_run/tests/minitest/finder"
5
+ require "test_run/tests/minitest/consolidator"
6
+ require "test_run/shell/runner"
7
+
8
+ class CLI < Thor
9
+
10
+ desc "find", <<-DESC
11
+ Find tests and run them. By trying to match an individual test or the name of a test file(s).
12
+ DESC
13
+
14
+ def find(input)
15
+ if input == '--help'
16
+ puts "use 'test_runner --help find' to see the help"
17
+ exit
18
+ end
19
+
20
+ shell = TestRun::Shell::Runner.new(
21
+ log_path: '/tmp/test_run.log',
22
+ working_directory: '.',
23
+
24
+ )
25
+
26
+ find_results = TestRun::Tests::Minitest::Finder.find(input, shell, options)
27
+
28
+ test_wrapper = TestRun::Tests::Minitest::Consolidator.consolidate(find_results, shell)
29
+
30
+ if test_wrapper.should_run?
31
+ shell.exec test_wrapper.to_command
32
+ end
33
+ end
34
+
35
+ default_task :find
36
+ end
37
+
38
+ CLI.start(ARGV)
@@ -0,0 +1,38 @@
1
+ module TestRun
2
+ module Searchers
3
+ class GitSearcher < Struct.new(:shell)
4
+
5
+ def find_files(pattern)
6
+ shell.run("git ls-files '*#{pattern}*'")
7
+ end
8
+
9
+ def grep(regex, file_pattern: '*')
10
+ results = shell.run("git grep --untracked '#{regex}' -- '#{file_pattern}'")
11
+ results.map do |result|
12
+ interpret_grep_result(result)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def interpret_grep_result(grep_result)
19
+ splits = grep_result.split(/:/)
20
+ file = splits.shift.strip
21
+ # we rejoin on ':' because our
22
+ # code may have colons inside of it.
23
+ #
24
+ # example:
25
+ # path/to/file: run_method(a: A, b: B)
26
+ #
27
+ # so shift the first one out, then
28
+ # rejoin the rest
29
+ line = splits.join(':').strip
30
+
31
+ {
32
+ :file => file,
33
+ :line => line,
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module TestRun
2
+ module Shell
3
+ module Color
4
+ CODES = {
5
+ red: 31,
6
+ green: 32,
7
+ yellow: 33,
8
+ pink: 35,
9
+ }.freeze
10
+
11
+ CODES.each do |color, code|
12
+ self.send(:define_method, color) do |string|
13
+ colorize(string, code)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ # colorization
20
+ def colorize(string, color_code)
21
+ "\e[#{color_code}m#{string}\e[0m"
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,66 @@
1
+ require "test_run/shell/color"
2
+ require "test_run/utils/path"
3
+
4
+ module TestRun
5
+ module Shell
6
+ class Runner
7
+ include Color
8
+
9
+ CommandFailureError = Class.new(StandardError)
10
+
11
+ attr_accessor :working_directory, :log_path, :queue
12
+ private :working_directory, :log_path, :queue
13
+
14
+ def initialize(log_path:, working_directory:)
15
+ @working_directory = working_directory
16
+ @log_path = log_path
17
+
18
+ %x{echo "" > #{log_path}}
19
+ Dir.chdir(%x[ git rev-parse --show-toplevel ].chomp)
20
+ end
21
+
22
+ def run(cmd, dir: working_directory, &block)
23
+ command = "cd #{Utils::Path.relative_join(dir)} && #{cmd}"
24
+ handle_output_for(command)
25
+
26
+ shell_out(command).split("\n")
27
+ end
28
+
29
+ def exec(cmd)
30
+ notify cmd
31
+ Kernel.exec cmd
32
+ end
33
+
34
+ def warn(msg)
35
+ log msg.to_s
36
+ print "#{red(msg.to_s)}\n"
37
+ end
38
+
39
+ def notify(msg)
40
+ log msg.to_s
41
+ print "#{yellow(msg.to_s)}\n"
42
+ end
43
+
44
+ def confirm?(question)
45
+ warn "#{question} [Yn]"
46
+ answer = STDIN.gets.strip.downcase
47
+ return answer != 'n'
48
+ end
49
+
50
+ private
51
+
52
+ def log(msg)
53
+ %x{echo "#{msg.to_s}" >> #{log_path}}
54
+ end
55
+
56
+ def handle_output_for(cmd)
57
+ log(cmd)
58
+ end
59
+
60
+ def shell_out(command)
61
+ %x{ set -o pipefail && #{command} 2>> #{log_path} | tee -a #{log_path} }.chomp
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,42 @@
1
+ require "test_run/utils/path"
2
+
3
+ require "test_run/tests/minitest/wrappers/single_test"
4
+ require "test_run/tests/minitest/wrappers/single_file"
5
+ require "test_run/tests/minitest/wrappers/multiple_files"
6
+
7
+ module TestRun
8
+ module Tests
9
+ module Minitest
10
+ class Consolidator < Struct.new(:find_results, :shell)
11
+
12
+ def self.consolidate(*args)
13
+ new(*args).consolidate
14
+ end
15
+
16
+ def consolidate
17
+ if find_results.empty?
18
+ puts "no results"
19
+ exit
20
+ end
21
+
22
+ if one_result?
23
+ Wrappers::SingleTest.new(find_results.first)
24
+ elsif one_test_file?
25
+ Wrappers::SingleFile.new(find_results.first[:file])
26
+ else
27
+ Wrappers::MultipleFiles.wrap(find_results.map {|r| r[:file] }, shell)
28
+ end
29
+ end
30
+
31
+ def one_test_file?
32
+ find_results.group_by {|f| f[:file]}.size == 1
33
+ end
34
+
35
+ def one_result?
36
+ one_test_file? && find_results.first[:line]
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,50 @@
1
+ require "test_run/searchers/git_searcher"
2
+
3
+ module TestRun
4
+ module Tests
5
+ module Minitest
6
+ class Finder < Struct.new(:query, :shell, :searcher, :options)
7
+
8
+ def self.find(query, shell, options)
9
+ searcher = Searchers::GitSearcher.new(shell)
10
+ new(query, shell, searcher, options).find
11
+ end
12
+
13
+ def find
14
+ return tests_found_by_absolute_path if query.match(/^\//)
15
+
16
+ return tests_found_by_name unless tests_found_by_name.empty?
17
+
18
+ return tests_found_by_file_name unless tests_found_by_file_name.empty?
19
+
20
+ return tests_found_by_full_regex unless tests_found_by_full_regex.empty?
21
+
22
+ []
23
+ end
24
+
25
+ private
26
+
27
+ def tests_found_by_absolute_path
28
+ [ {file: query} ]
29
+ end
30
+
31
+ def tests_found_by_name
32
+ @tests_found_by_name ||= full_regex_search("^\s*def .*#{query}.*")
33
+ end
34
+
35
+ def tests_found_by_file_name
36
+ @tests_found_by_file_name ||= searcher.find_files(query).select { |f| f.match(/_test\.rb/) }.map {|f| {file: f} }
37
+ end
38
+
39
+ def tests_found_by_full_regex
40
+ # we ignore the matched line since we don't know what to do with it
41
+ @tests_found_by_full_regex ||= full_regex_search(query).map {|t| {file: t[:file]} }
42
+ end
43
+
44
+ def full_regex_search(regex)
45
+ searcher.grep(regex, file_pattern: '*_test.rb')
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ require "test_run/tests/minitest/wrappers/single_root"
2
+ require "test_run/tests/minitest/wrappers/multiple_roots"
3
+
4
+ module TestRun
5
+ module Tests
6
+ module Minitest
7
+ module Wrappers
8
+ module MultipleFiles
9
+
10
+ def self.wrap(files, shell)
11
+ wrapper = MultipleRoots.new(files, shell)
12
+
13
+ if wrapper.roots.size > 1
14
+ wrapper
15
+ else
16
+ wrapper.roots.first
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ require "test_run/utils/path"
2
+
3
+ module TestRun
4
+ module Tests
5
+ module Minitest
6
+ module Wrappers
7
+ class MultipleRoots
8
+
9
+ attr_reader :roots, :shell
10
+
11
+ def initialize(files, shell)
12
+ @shell = shell
13
+ @roots = files.map {|f| SingleFile.new(f)}.group_by {|f| f.app_root}.map {|root, _files| SingleRoot.new(_files, shell)}
14
+ end
15
+
16
+ def to_command
17
+ roots.map(&:to_command).join("; cd -; \n\n")
18
+ end
19
+
20
+ def should_run?
21
+ shell.confirm?("Found #{roots.inject(0) {|sum, root| sum + root.files.size }} test files in #{roots.size} apps/engines. Run them all?")
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ require "test_run/utils/path"
2
+
3
+ module TestRun
4
+ module Tests
5
+ module Minitest
6
+ module Wrappers
7
+ class SingleFile < Struct.new(:file)
8
+
9
+ def to_command
10
+ %{cd #{File.join(app_root)} && ruby -I test #{File.join(relative_test_path)}}
11
+ end
12
+
13
+ def app_root
14
+ exploded_path = Utils::Path.split(file)
15
+
16
+ path = exploded_path[0...exploded_path.rindex("test")]
17
+ File.join(path)
18
+ end
19
+
20
+ def relative_test_path
21
+ exploded_path = Utils::Path.split(file)
22
+ path = exploded_path[exploded_path.rindex("test")..-1]
23
+ File.join(path)
24
+ end
25
+
26
+ def should_run?
27
+ true
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require "test_run/utils/path"
2
+
3
+ module TestRun
4
+ module Tests
5
+ module Minitest
6
+ module Wrappers
7
+ class SingleRoot
8
+
9
+ attr_reader :files, :shell
10
+
11
+ def initialize(files, shell)
12
+ @shell = shell
13
+ @files = files.map {|f| f.is_a?(SingleFile) ? f : SingleFile.new(f)}
14
+ end
15
+
16
+ def should_run?
17
+ # keep working here!
18
+ true
19
+ end
20
+
21
+ def to_command
22
+ %{cd #{app_root} && ruby -I test -e 'ARGV.each { |file| require(Dir.pwd + "/" + file) }' #{files.map(&:relative_test_path).join(" ")}}
23
+ end
24
+
25
+ def app_root
26
+ files.first.app_root
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,42 @@
1
+ require "test_run/utils/path"
2
+
3
+ module TestRun
4
+ module Tests
5
+ module Minitest
6
+ module Wrappers
7
+ class SingleTest
8
+
9
+ attr_reader :file, :name
10
+ private :file, :name
11
+
12
+ def initialize(file:, line:)
13
+ @file = file
14
+ @name = line[/\s*def\s+(.*)/, 1]
15
+ end
16
+
17
+ def to_command
18
+ %{cd #{app_root} && ruby -I test #{relative_test_path} --name=/#{name}/}
19
+ end
20
+
21
+ def app_root
22
+ exploded_path = Utils::Path.split(file)
23
+
24
+ path = exploded_path[0...exploded_path.rindex("test")]
25
+ File.join(path)
26
+ end
27
+
28
+ def relative_test_path
29
+ exploded_path = Utils::Path.split(file)
30
+ path = exploded_path[exploded_path.rindex("test")..-1]
31
+ File.join(path)
32
+ end
33
+
34
+ def should_run?
35
+ true
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ require "pathname"
2
+
3
+ module TestRun
4
+ module Utils
5
+ module Path
6
+
7
+ def self.split(filename)
8
+ self.prepend_pwd(Pathname.new(filename).each_filename.to_a)
9
+ end
10
+
11
+ def self.path_for(filename)
12
+ self.split(File.split(file)[0])
13
+ end
14
+
15
+ def self.join(*array)
16
+ File.join(*array)
17
+ end
18
+
19
+ def self.prepend_pwd(dirs)
20
+ if dirs[0] == "."
21
+ dirs
22
+ else
23
+ ["."] + dirs
24
+ end
25
+ end
26
+
27
+ def self.relative_join(array)
28
+ join(prepend_pwd(array))
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module TestRun
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
Binary file
data/test_run.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = TestRun::VERSION
9
9
  spec.authors = ["Pete Kinnecom"]
10
10
  spec.email = ["pete.kinnecom@appfolio.com"]
11
- spec.summary = %q{Write a short summary. Required.}
12
- spec.description = %q{Write a longer description. Optional.}
11
+ spec.summary = %q{Easily run tests}
12
+ spec.description = %q{no really}
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test_run
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Kinnecom
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-27 00:00:00.000000000 Z
11
+ date: 2015-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,10 +38,11 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: Write a longer description. Optional.
41
+ description: no really
42
42
  email:
43
43
  - pete.kinnecom@appfolio.com
44
- executables: []
44
+ executables:
45
+ - test_runner
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
48
  files:
@@ -50,8 +51,21 @@ files:
50
51
  - LICENSE.txt
51
52
  - README.md
52
53
  - Rakefile
54
+ - bin/test_runner
53
55
  - lib/test_run.rb
56
+ - lib/test_run/searchers/git_searcher.rb
57
+ - lib/test_run/shell/color.rb
58
+ - lib/test_run/shell/runner.rb
59
+ - lib/test_run/tests/minitest/consolidator.rb
60
+ - lib/test_run/tests/minitest/finder.rb
61
+ - lib/test_run/tests/minitest/wrappers/multiple_files.rb
62
+ - lib/test_run/tests/minitest/wrappers/multiple_roots.rb
63
+ - lib/test_run/tests/minitest/wrappers/single_file.rb
64
+ - lib/test_run/tests/minitest/wrappers/single_root.rb
65
+ - lib/test_run/tests/minitest/wrappers/single_test.rb
66
+ - lib/test_run/utils/path.rb
54
67
  - lib/test_run/version.rb
68
+ - test_run-0.0.1.gem
55
69
  - test_run.gemspec
56
70
  homepage: ''
57
71
  licenses:
@@ -73,8 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
87
  version: '0'
74
88
  requirements: []
75
89
  rubyforge_project:
76
- rubygems_version: 2.4.3
90
+ rubygems_version: 2.2.2
77
91
  signing_key:
78
92
  specification_version: 4
79
- summary: Write a short summary. Required.
93
+ summary: Easily run tests
80
94
  test_files: []