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 +4 -4
- data/.gitignore +1 -0
- data/bin/test_runner +38 -0
- data/lib/test_run/searchers/git_searcher.rb +38 -0
- data/lib/test_run/shell/color.rb +26 -0
- data/lib/test_run/shell/runner.rb +66 -0
- data/lib/test_run/tests/minitest/consolidator.rb +42 -0
- data/lib/test_run/tests/minitest/finder.rb +50 -0
- data/lib/test_run/tests/minitest/wrappers/multiple_files.rb +23 -0
- data/lib/test_run/tests/minitest/wrappers/multiple_roots.rb +28 -0
- data/lib/test_run/tests/minitest/wrappers/single_file.rb +33 -0
- data/lib/test_run/tests/minitest/wrappers/single_root.rb +33 -0
- data/lib/test_run/tests/minitest/wrappers/single_test.rb +42 -0
- data/lib/test_run/utils/path.rb +32 -0
- data/lib/test_run/version.rb +1 -1
- data/test_run-0.0.1.gem +0 -0
- data/test_run.gemspec +2 -2
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a15a71d527a5bfc218b66b112fa17c190206b667
|
4
|
+
data.tar.gz: ae00269c6b9506995cb3c62106e0e2eea9a9513e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2550c215d5d98b04d1f1333acc3c79ebba130beaf92db8caa8eee08a5e94aa39105915eeb799bfddca7d9e6c4c56c8ad2faade2d85221cc3218bc9c3effaf3a9
|
7
|
+
data.tar.gz: 4758c47037e7588ec9dcbfbb55d863217f7bc15179fa29661e5130dbc053cc3e202af640bf5ad1f06109fa6dd36a511680956ab72c8fffd9489e1787d4beed88
|
data/.gitignore
CHANGED
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
|
data/lib/test_run/version.rb
CHANGED
data/test_run-0.0.1.gem
ADDED
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{
|
12
|
-
spec.description = %q{
|
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.
|
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-
|
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:
|
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.
|
90
|
+
rubygems_version: 2.2.2
|
77
91
|
signing_key:
|
78
92
|
specification_version: 4
|
79
|
-
summary:
|
93
|
+
summary: Easily run tests
|
80
94
|
test_files: []
|