drunit 0.2 → 0.4.1
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/Rakefile +1 -8
- data/lib/drunit/remote_app.rb +8 -26
- data/lib/drunit/remote_error.rb +31 -0
- data/lib/drunit/remote_test.rb +35 -35
- data/lib/drunit.rb +52 -23
- data/test/fake_app/fake_app.rb +6 -0
- data/test/unit/main_test.rb +19 -2
- data/test/unit/test_case_switching_test.rb +17 -0
- metadata +19 -8
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ end
|
|
17
17
|
|
18
18
|
spec = Gem::Specification.new do |s|
|
19
19
|
s.name = %q{drunit}
|
20
|
-
s.version = "0.
|
20
|
+
s.version = "0.4.1"
|
21
21
|
s.summary = %q{A library for running tests across multiple applications from a single test case.}
|
22
22
|
s.description = %q{A library for running tests across multiple applications from a single test case.}
|
23
23
|
|
@@ -43,10 +43,3 @@ end
|
|
43
43
|
|
44
44
|
desc "Clean files generated by rake tasks"
|
45
45
|
task :clobber => [:clobber_rdoc, :clobber_package]
|
46
|
-
|
47
|
-
desc "Generate a gemspec file"
|
48
|
-
task :gemspec do
|
49
|
-
File.open("#{spec.name}.gemspec", 'w') do |f|
|
50
|
-
f.write spec.to_ruby
|
51
|
-
end
|
52
|
-
end
|
data/lib/drunit/remote_app.rb
CHANGED
@@ -3,42 +3,30 @@ require 'ruby2ruby'
|
|
3
3
|
|
4
4
|
module Drunit
|
5
5
|
class RemoteApp
|
6
|
-
def initialize(name, boot = nil)
|
6
|
+
def initialize(name, boot = nil, dir = nil)
|
7
7
|
@name = name
|
8
8
|
@boot = boot
|
9
|
-
@
|
10
|
-
@boot ||= "
|
9
|
+
@dir = File.expand_path(dir || name)
|
10
|
+
@boot ||= "test/drunit_test_helper.rb" if File.exist? "#{@dir}/test/drunit_test_helper.rb"
|
11
|
+
@boot ||= "test/test_helper.rb" if File.exist? "#{@dir}/test/test_helper.rb"
|
11
12
|
@remote_object = nil
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def last_assertion_count
|
19
|
-
app.last_assertion_count
|
15
|
+
def new_test_case(class_name = "Test::Unit::TestCase")
|
16
|
+
app.new_test_case(class_name)
|
20
17
|
end
|
21
18
|
|
22
19
|
private
|
23
|
-
def raise_or_return(e, method_name)
|
24
|
-
return e unless e.is_a? Exception
|
25
|
-
if first_remote_line = e.backtrace.grep(Regexp.new(method_name)).last
|
26
|
-
index = e.backtrace.index(first_remote_line)
|
27
|
-
raise e, e.message, e.backtrace[0..index] + ["RemoteApp<#{@name}>"] + caller(0)
|
28
|
-
end
|
29
|
-
raise e
|
30
|
-
end
|
31
|
-
|
32
20
|
def get_url(pipe)
|
33
21
|
pipe.each_line do |line|
|
34
22
|
return $1 if line =~ /^DRUNIT:URI (.*)$/
|
35
|
-
STDERR.puts "From drunit_remote>> #{line}"
|
23
|
+
STDERR.puts "From drunit_remote(#{@name})>> #{line}"
|
36
24
|
end
|
37
25
|
end
|
38
26
|
|
39
27
|
def start_app!
|
40
28
|
drb_server = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "bin", "drunit_remote"))
|
41
|
-
pipe = IO.popen("#{drb_server} #{@boot}")
|
29
|
+
pipe = IO.popen("cd #{@dir} && #{drb_server} #{@boot}")
|
42
30
|
pid = pipe.pid
|
43
31
|
url = get_url(pipe) or raise "Could not establish connection to the remote drunit instance."
|
44
32
|
remote_object = DRbObject.new(nil, url)
|
@@ -49,11 +37,5 @@ module Drunit
|
|
49
37
|
def app
|
50
38
|
@remote_object ||= start_app!
|
51
39
|
end
|
52
|
-
|
53
|
-
def block_to_source(method_name, &block)
|
54
|
-
m = Module.new
|
55
|
-
m.send(:define_method, method_name, &block)
|
56
|
-
Ruby2Ruby.translate(m, method_name)
|
57
|
-
end
|
58
40
|
end
|
59
41
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Drunit
|
2
|
+
class RemoteError < RuntimeError
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def name
|
6
|
+
@name || super
|
7
|
+
end
|
8
|
+
attr_writer :name
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(exception_name)
|
12
|
+
@exception_name = exception_name.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def class
|
16
|
+
type = look_up_exception
|
17
|
+
return type if type
|
18
|
+
super.name = @exception_name #Now we hope and prey that the name of the class is checked imidiately
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def look_up_exception
|
23
|
+
@exception_name.split("::").inject(Object){|node, part|
|
24
|
+
node && node.const_defined?(part) && node.const_get(part)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
data/lib/drunit/remote_test.rb
CHANGED
@@ -1,54 +1,54 @@
|
|
1
1
|
require 'drb'
|
2
2
|
require 'test/unit'
|
3
|
+
require File.join(File.dirname(__FILE__), *%w[remote_error])
|
3
4
|
|
4
5
|
module Drunit
|
5
|
-
class RemoteError < RuntimeError
|
6
|
-
def initialize(real_exception)
|
7
|
-
@real_exception = real_exception
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
6
|
class RemoteTest
|
12
|
-
|
7
|
+
def new_test_case(name)
|
8
|
+
tc = Class.new(eval(name, Object.class_eval{ binding }))
|
9
|
+
tc.send(:include, TestCaseModule)
|
10
|
+
tc.allocate
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
module TestCaseModule
|
14
|
+
def self.included(other)
|
15
|
+
other.send(:class_eval) do
|
16
|
+
include DRb::DRbUndumped
|
17
|
+
attr_reader :assertion_count
|
18
|
+
end
|
19
|
+
end
|
17
20
|
|
18
|
-
def initialize
|
21
|
+
def initialize
|
19
22
|
@assertion_count = 0
|
20
|
-
@method_name = method_name
|
21
|
-
instance_eval(code, source_file, source_line)
|
22
23
|
end
|
23
24
|
|
24
25
|
def add_assertion
|
25
26
|
@assertion_count += 1
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
-
|
29
|
+
def define(code, source_file, source_line)
|
30
|
+
instance_eval(code, source_file, source_line)
|
30
31
|
end
|
31
|
-
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
33
|
+
def run(method_name, *args)
|
34
|
+
@assertion_count = 0
|
35
|
+
rewrite_exceptions{ __send__(method_name, *args) }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
# We need to strip down and generalise the exceptions to prevent the integration project from having to know anything about anything.
|
40
|
+
def rewrite_exceptions
|
41
|
+
begin
|
42
|
+
return yield
|
43
|
+
rescue Test::Unit::AssertionFailedError
|
44
|
+
raise
|
45
|
+
rescue ArgumentError => e
|
46
|
+
raise e unless e.message =~ /Anonymous modules /
|
47
|
+
raise NameError, "Const Missing", e.backtrace[3..-1]
|
48
|
+
rescue Exception => e
|
49
|
+
raise Drunit::RemoteError.new(e.class.name), e.message, e.backtrace
|
50
|
+
end
|
51
|
+
end
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
data/lib/drunit.rb
CHANGED
@@ -1,47 +1,76 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
1
3
|
module Drunit
|
2
|
-
class RemoteError < RuntimeError
|
3
|
-
def self.name
|
4
|
-
@@name
|
5
|
-
end
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
else
|
11
|
-
@@name = @real_exception.to_s
|
12
|
-
super
|
13
|
-
end
|
5
|
+
module ClassMethods
|
6
|
+
def RemoteApp(name, *args)
|
7
|
+
const_set "RemoteAppFor_#{name}", RemoteApp.new(name, *args)
|
14
8
|
end
|
15
9
|
|
16
|
-
def
|
17
|
-
@
|
18
|
-
|
19
|
-
}
|
10
|
+
def drunit_test_case_class_name
|
11
|
+
@drunit_test_case_class_name ||
|
12
|
+
(superclass.respond_to?(:drunit_test_case_class_name) ? superclass.drunit_test_case_class_name : "Test::Unit::TestCase")
|
20
13
|
end
|
21
|
-
end
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
const_set "RemoteAppFor_#{name}", RemoteApp.new(name, *args)
|
15
|
+
def set_drunit_test_case_class_name(name)
|
16
|
+
@drunit_test_case_class_name = name
|
26
17
|
end
|
27
18
|
end
|
28
19
|
|
29
20
|
def in_app(name, *args, &block)
|
30
|
-
file, line, method =
|
31
|
-
|
32
|
-
|
21
|
+
file, line, method = caller_file_and_method_for_block(&block)
|
22
|
+
test_case = remote_test_case_for(name)
|
23
|
+
test_case.define(block_to_source(method, &block), file, line)
|
24
|
+
test_case.run(method, *args)
|
25
|
+
rescue Exception => e
|
26
|
+
rewrite_backtrace(e, method, name) or raise
|
33
27
|
ensure
|
34
|
-
|
28
|
+
test_case.assertion_count.times{ add_assertion } rescue nil
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def rewrite_backtrace(e, method_name, app_name)
|
33
|
+
backtrace = e.backtrace
|
34
|
+
if first_remote_line = backtrace.grep(Regexp.new(method_name)).first
|
35
|
+
index = backtrace.index(first_remote_line)
|
36
|
+
backtrace = backtrace[0..index] + ["in drunit_remote(#{app_name})"] + caller(1)
|
37
|
+
backtrace.map!{|line| line.gsub(/\(druby:\/\/[^\)]+\) /, "")}
|
38
|
+
raise e, e.message, backtrace
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def block_to_source(method_name, &block)
|
43
|
+
m = Module.new
|
44
|
+
m.send(:define_method, method_name, &block)
|
45
|
+
Ruby2Ruby.translate(m, method_name)
|
35
46
|
end
|
36
47
|
|
37
48
|
def remote_app_for(name)
|
38
49
|
self.class.const_get("RemoteAppFor_#{name}")
|
39
50
|
end
|
40
51
|
|
52
|
+
def remote_test_case_for(name)
|
53
|
+
@remote_test_cases ||= {}
|
54
|
+
@remote_test_cases[name.to_sym] ||= remote_app_for(name).new_test_case(drunit_test_case_class_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_drunit_test_case_class_name(name)
|
58
|
+
@drunit_test_case_class_name = name
|
59
|
+
end
|
60
|
+
|
61
|
+
def drunit_test_case_class_name
|
62
|
+
@drunit_test_case_class_name || self.class.drunit_test_case_class_name
|
63
|
+
end
|
64
|
+
|
65
|
+
def caller_file_and_method_for_block(&block)
|
66
|
+
eval(%%caller(0)[0] =~ /in `(.*)'/; [__FILE__, __LINE__, $1 || 'unknown_method']%, block.binding)
|
67
|
+
end
|
68
|
+
|
41
69
|
def self.included(other)
|
42
70
|
other.send(:extend, ClassMethods)
|
43
71
|
end
|
44
72
|
end
|
45
73
|
|
46
74
|
require File.join(File.dirname(__FILE__), *%w[drunit remote_app])
|
75
|
+
require File.join(File.dirname(__FILE__), *%w[drunit remote_error])
|
47
76
|
|
data/test/fake_app/fake_app.rb
CHANGED
data/test/unit/main_test.rb
CHANGED
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), *%w[.. test_helper])
|
|
2
2
|
|
3
3
|
class MainTest < Test::Unit::TestCase
|
4
4
|
include Drunit
|
5
|
-
RemoteApp(:fake_app,
|
5
|
+
RemoteApp(:fake_app, "fake_app.rb", FAKE_APP_PATH)
|
6
6
|
def InApp(*args, &block)
|
7
7
|
in_app(:fake_app, *args, &block)
|
8
8
|
end
|
@@ -13,6 +13,11 @@ class MainTest < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
def test_should_be_in_the_given_dir
|
17
|
+
actual = InApp{ File.expand_path Dir.pwd }
|
18
|
+
assert_equal File.expand_path(FAKE_APP_PATH), actual
|
19
|
+
end
|
20
|
+
|
16
21
|
def test_should_raise_an_exception
|
17
22
|
assert_raise(RuntimeError) { InApp{ raise "Fail" } }
|
18
23
|
end
|
@@ -26,7 +31,7 @@ class MainTest < Test::Unit::TestCase
|
|
26
31
|
|
27
32
|
def test_should_inject_the_fact_we_are_in_a_remote_app_into_the_backtrace
|
28
33
|
e = assert_raise(RuntimeError) { InApp{ raise "Fail" } }
|
29
|
-
assert_equal 1, e.backtrace.grep("
|
34
|
+
assert_equal 1, e.backtrace.grep("in drunit_remote(fake_app)").size, e.backtrace.join("\n")
|
30
35
|
end
|
31
36
|
|
32
37
|
def test_should_raise_the_assertion_count_when_we_assert
|
@@ -35,7 +40,19 @@ class MainTest < Test::Unit::TestCase
|
|
35
40
|
assert_equal original_count + 1, @_result.assertion_count
|
36
41
|
end
|
37
42
|
|
43
|
+
def test_should_not_count_the_same_assert_twice
|
44
|
+
original_count = @_result.assertion_count
|
45
|
+
InApp{ assert true}
|
46
|
+
InApp{ assert true}
|
47
|
+
assert_equal original_count + 2, @_result.assertion_count
|
48
|
+
end
|
49
|
+
|
38
50
|
def test_should_be_able_to_pass_in_simple_params
|
39
51
|
assert_equal 12, InApp(2,6){|a,b| SomeFoo.new.multiply(a, b)}
|
40
52
|
end
|
53
|
+
|
54
|
+
def test_consistant_remote_instance
|
55
|
+
InApp{ @foo = 1 }
|
56
|
+
InApp{ assert_equal 1, @foo }
|
57
|
+
end
|
41
58
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. test_helper])
|
2
|
+
|
3
|
+
class SomeOtherTestCaseTest < Test::Unit::TestCase
|
4
|
+
include Drunit
|
5
|
+
RemoteApp(:fake_app, FAKE_APP_PATH + "/fake_app.rb")
|
6
|
+
def InApp(*args, &block)
|
7
|
+
in_app(:fake_app, *args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
set_drunit_test_case_class_name "SomeOtherTestCase"
|
11
|
+
|
12
|
+
def test_foo
|
13
|
+
InApp{ assert_in_new_test_case }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: drunit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Tom Lea
|
@@ -9,8 +14,8 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
17
|
+
date: 2010-03-25 00:00:00 +00:00
|
18
|
+
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
16
21
|
description: A library for running tests across multiple applications from a single test case.
|
@@ -25,15 +30,18 @@ files:
|
|
25
30
|
- Rakefile
|
26
31
|
- README.markdown
|
27
32
|
- lib/drunit/remote_app.rb
|
33
|
+
- lib/drunit/remote_error.rb
|
28
34
|
- lib/drunit/remote_test.rb
|
29
35
|
- lib/drunit.rb
|
30
36
|
- test/fake_app/fake_app.rb
|
31
37
|
- test/test_helper.rb
|
32
38
|
- test/unit/exception_handling_test.rb
|
33
39
|
- test/unit/main_test.rb
|
34
|
-
-
|
40
|
+
- test/unit/test_case_switching_test.rb
|
35
41
|
has_rdoc: true
|
36
42
|
homepage:
|
43
|
+
licenses: []
|
44
|
+
|
37
45
|
post_install_message:
|
38
46
|
rdoc_options:
|
39
47
|
- --line-numbers
|
@@ -46,21 +54,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
46
54
|
requirements:
|
47
55
|
- - ">="
|
48
56
|
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
49
59
|
version: "0"
|
50
|
-
version:
|
51
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
61
|
requirements:
|
53
62
|
- - ">="
|
54
63
|
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
55
66
|
version: "0"
|
56
|
-
version:
|
57
67
|
requirements: []
|
58
68
|
|
59
69
|
rubyforge_project:
|
60
|
-
rubygems_version: 1.3.
|
70
|
+
rubygems_version: 1.3.6
|
61
71
|
signing_key:
|
62
|
-
specification_version:
|
72
|
+
specification_version: 3
|
63
73
|
summary: A library for running tests across multiple applications from a single test case.
|
64
74
|
test_files:
|
65
75
|
- test/unit/exception_handling_test.rb
|
66
76
|
- test/unit/main_test.rb
|
77
|
+
- test/unit/test_case_switching_test.rb
|