testrbl 0.1.17 → 0.2.0

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