testrbl 0.1.17 → 0.2.0

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.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
  gemspec
3
3
 
4
4
  gem 'test-unit'
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- testrbl (0.1.17)
4
+ testrbl (0.2.0)
5
5
 
6
6
  GEM
7
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
8
8
  specs:
9
9
  activesupport (2.3.14)
10
10
  bump (0.3.3)
@@ -1,3 +1,3 @@
1
1
  module Testrbl
2
- VERSION = '0.1.17'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/testrbl.rb CHANGED
@@ -7,6 +7,8 @@ module Testrbl
7
7
  /^(\s+)def\s+(test_)([a-z_\d]+)\s*(?:#.*)?$/
8
8
  ]
9
9
 
10
+ OPTION_WITH_ARGUMENT = ["-I", "-r", "-n", "-e"]
11
+
10
12
  # copied from minitest
11
13
  MINITEST_NAME_RE = if RUBY_VERSION >= "1.9"
12
14
  Regexp.new("[^[[:word:]]]+")
@@ -17,89 +19,113 @@ module Testrbl
17
19
  INTERPOLATION = /\\\#\\\{.*?\\\}/
18
20
 
19
21
  def self.run_from_cli(argv)
20
- i_test, file, line = detect_usable(argv)
21
- if file and line
22
- file = localize(file)
23
- run "#{ruby} #{i_test}#{file} -n '/#{pattern_from_file(File.readlines(file), line)}/'"
24
- elsif file
25
- run "#{ruby} #{i_test}#{file}"
26
- elsif argv.all?{|f| File.file?(f) } # testrb has a lot of weird issues vs test-unit, so try to avoid it
27
- run "#{ruby} #{argv.map{|f| "-r #{localize(f)}" }.join(" ")} -e ''"
28
- else # pass though
29
- # no bundle exec: projects with mini and unit-test do not run well via bundle exec testrb
30
- run ["testrb"] + argv
22
+ files, options = partition_argv(argv)
23
+ files = files.map { |f| localize(f) }
24
+ load_options, options = partition_options(options)
25
+
26
+ if files.size == 1 and files.first =~ /^(\S+):(\d+)$/
27
+ file = $1
28
+ line = $2
29
+ run(ruby + load_options + [file, "-n", "/#{pattern_from_file(File.readlines(file), line)}/"] + options)
30
+ else
31
+ if files.all? { |f| File.file?(f) } and options.none? { |arg| arg =~ /^-n/ }
32
+ run(ruby + load_options + files.map { |f| "-r#{f}" } + options + ["-e", ""])
33
+ else # pass though
34
+ # no bundle exec: projects with mini and unit-test do not run well via bundle exec testrb
35
+ run ["testrb"] + argv
36
+ end
31
37
  end
32
38
  end
33
39
 
34
- # useable e.g. via zeus
40
+ # usable via external tools like zeus
35
41
  def self.pattern_from_file(lines, line)
36
- search = lines[0..(line.to_i-1)].reverse
42
+ possible_lines = lines[0..(line.to_i-1)].reverse
37
43
 
38
44
  last_spaces = " " * 100
39
- found = search.map{|line| pattern_from_line(line) }.compact
45
+ found = possible_lines.map { |line| test_pattern_from_line(line) }.compact
46
+
47
+ # pattern and the groups it is nested under (like describe - describe - it)
40
48
  patterns = found.select do |spaces, name|
41
49
  last_spaces = spaces if spaces.size < last_spaces.size
42
50
  end.map(&:last)
43
51
 
44
- use = []
45
- found_final = false
46
- patterns.each do |pattern|
47
- is_final = pattern.end_with?("$")
48
- next if is_final && found_final
49
- found_final = is_final
50
- use << pattern
51
- end
52
-
53
- return use.reverse.join(".*") if found.size > 0
52
+ return filter_duplicate_final(patterns).reverse.join(".*") if found.size > 0
54
53
 
55
54
  raise "no test found before line #{line}"
56
55
  end
57
56
 
57
+ # only keep 1 pattern that stops matching via $
58
+ def self.filter_duplicate_final(patterns)
59
+ found_final = 0
60
+ patterns.reject { |p| p.end_with?("$") and (found_final += 1) > 1 }
61
+ end
62
+
58
63
  private
59
64
 
65
+ def self.partition_options(options)
66
+ next_is_before = false
67
+ options.partition do |option|
68
+ if next_is_before
69
+ next_is_before = false
70
+ true
71
+ else
72
+ if option =~ /^-(r|I)/
73
+ next_is_before = (option.size == 2)
74
+ true
75
+ else
76
+ false
77
+ end
78
+ end
79
+ end
80
+ end
81
+
60
82
  # fix 1.9 not being able to load local files
61
83
  def self.localize(file)
62
84
  file =~ /^[-a-z\d_]/ ? "./#{file}" : file
63
85
  end
64
86
 
65
- def self.detect_usable(argv)
66
- argv = argv.dup # do not mess up args
67
- i_test = "-Itest " if ((argv.delete("-I") and argv.delete("test")) or argv.delete("-Itest"))
68
-
69
- return unless argv.size == 1
70
-
71
- if argv.first =~ /^(\S+):(\d+)$/
72
- [i_test, $1, $2]
73
- elsif File.file?(argv.first)
74
- [i_test, argv.first, false]
87
+ def self.partition_argv(argv)
88
+ next_is_option = false
89
+ argv.partition do |arg|
90
+ if next_is_option
91
+ next_is_option = false
92
+ else
93
+ if arg =~ /^-.$/ or arg =~ /^--/ # single letter option followed by argument like -I test or long options like --verbose
94
+ next_is_option = true if OPTION_WITH_ARGUMENT.include?(arg)
95
+ false
96
+ elsif arg =~ /^-/ # multi letter option like -Itest
97
+ false
98
+ else
99
+ true
100
+ end
101
+ end
75
102
  end
76
103
  end
77
104
 
78
105
  def self.ruby
79
106
  if File.file?("Gemfile")
80
- "ruby -rbundler/setup" # faster then bundle exec ruby
107
+ ["ruby", "-rbundler/setup"] # faster then bundle exec ruby
81
108
  else
82
- "ruby"
109
+ ["ruby"]
83
110
  end
84
111
  end
85
112
 
86
113
  def self.run(command)
87
- command = [*command]
88
114
  puts command.join(" ")
89
115
  STDOUT.flush # if exec fails horribly we at least see some output
90
116
  Kernel.exec *command
91
117
  end
92
118
 
93
- def self.pattern_from_line(line)
119
+ def self.test_pattern_from_line(line)
94
120
  PATTERNS.each do |r|
95
121
  next unless line =~ r
96
122
  whitespace, method, test_name = $1, $2, $3
97
- return [whitespace, pattern_from_match(method, test_name)]
123
+ return [whitespace, test_pattern_from_match(method, test_name)]
98
124
  end
99
125
  nil
100
126
  end
101
127
 
102
- def self.pattern_from_match(method, test_name)
128
+ def self.test_pattern_from_match(method, test_name)
103
129
  regex = Regexp.escape(test_name).gsub("\\ "," ").gsub(INTERPOLATION, ".*")
104
130
 
105
131
  if method == "should"
data/spec/testrbl_spec.rb CHANGED
@@ -383,24 +383,33 @@ describe Testrbl do
383
383
  before do
384
384
  write "backtrace_test.rb", <<-RUBY
385
385
  puts caller
386
+ require 'test/unit'
387
+
388
+ class Xxx1 < Test::Unit::TestCase
389
+ def test_xxx
390
+ puts 'BACKTRACE'
391
+ end
392
+ end
386
393
  RUBY
387
394
  end
388
395
 
389
396
  it "does not run via testrb if possible" do
390
- result = testrbl "a/b/c_test.rb backtrace_test.rb"
397
+ result = testrbl "-Itest -I lib a/b/c_test.rb backtrace_test.rb -v"
391
398
  result.should include("CDE")
399
+ result.should include("BACKTRACE")
392
400
  result.should_not include("bin/testrb:")
393
401
  end
394
402
 
395
- it "runs via testrb if not possible via ruby" do
396
- result = testrbl "a/b/c_test.rb backtrace_test.rb -v"
403
+ it "runs via testrb if unavoidable" do
404
+ result = testrbl "a/b/c_test.rb backtrace_test.rb -n '/xxx/'"
397
405
  result.should include("CDE")
406
+ result.should include("BACKTRACE")
398
407
  result.should include("bin/testrb:")
399
408
  end
400
409
  end
401
410
  end
402
411
 
403
- describe ".pattern_from_file" do
412
+ describe ".test_pattern_from_file" do
404
413
  def call(content, line)
405
414
  lines = content.split("\n").map{|l| l + "\n" }
406
415
  Testrbl.pattern_from_file(lines, line)
@@ -425,9 +434,9 @@ describe Testrbl do
425
434
  end
426
435
  end
427
436
 
428
- describe ".pattern_from_line" do
437
+ describe ".test_pattern_from_line" do
429
438
  def call(line)
430
- Testrbl.pattern_from_line(line)
439
+ Testrbl.test_pattern_from_line(line)
431
440
  end
432
441
 
433
442
  it "finds simple tests" do
@@ -498,4 +507,34 @@ describe Testrbl do
498
507
  call(" context \"xx ' xx\" do\n").should == [" ", "xx . xx"]
499
508
  end
500
509
  end
510
+
511
+ describe ".partition_argv" do
512
+ def call(*args)
513
+ Testrbl.send(:partition_argv, *args)
514
+ end
515
+
516
+ it "finds files" do
517
+ call(["xxx"]).should == [["xxx"], []]
518
+ end
519
+
520
+ it "finds files after multi-space options" do
521
+ call(["-I", "test", "xxx"]).should == [["xxx"], ["-I", "test"]]
522
+ end
523
+
524
+ it "finds options" do
525
+ call(["-I", "test"]).should == [[], ["-I", "test"]]
526
+ end
527
+
528
+ it "finds --verbose" do
529
+ call(["--verbose", "test"]).should == [["test"], ["--verbose"]]
530
+ end
531
+
532
+ it "finds -- options" do
533
+ call(["--foo", "test"]).should == [["test"], ["--foo"]]
534
+ end
535
+
536
+ it "finds mashed options" do
537
+ call(["-Itest"]).should == [[], ["-Itest"]]
538
+ end
539
+ end
501
540
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testrbl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.17
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-29 00:00:00.000000000 Z
12
+ date: 2013-03-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: michael@grosser.it
@@ -44,7 +44,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
44
44
  version: '0'
45
45
  segments:
46
46
  - 0
47
- hash: 3686334179144340123
47
+ hash: -866997392072142941
48
48
  required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
@@ -53,10 +53,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
53
  version: '0'
54
54
  segments:
55
55
  - 0
56
- hash: 3686334179144340123
56
+ hash: -866997392072142941
57
57
  requirements: []
58
58
  rubyforge_project:
59
- rubygems_version: 1.8.24
59
+ rubygems_version: 1.8.25
60
60
  signing_key:
61
61
  specification_version: 3
62
62
  summary: Run ruby Test::Unit/Shoulda tests by line-number / folder / the dozen