drunit 0.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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.2"
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
@@ -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
- @boot ||= "#{name}/test/drunit_test_helper.rb" if File.exist? "#{name}/test/drunit_test_helper.rb"
10
- @boot ||= "#{name}/test/test_helper.rb" if File.exist? "#{name}/test/test_helper.rb"
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 run(method_name, file, line, *args, &block)
15
- raise_or_return(app.eval(block_to_source(method_name, &block), file, line, method_name, *args), method_name)
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
+
@@ -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
- attr_reader :last_assertion_count
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
- class TestCase
15
- include Test::Unit::Assertions
16
- attr_reader :assertion_count
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(code, source_file, source_line, method_name)
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 run(*args)
29
- send(@method_name, *args)
29
+ def define(code, source_file, source_line)
30
+ instance_eval(code, source_file, source_line)
30
31
  end
31
- end
32
32
 
33
- def eval(code, source_file, source_line, method_name, *args)
34
- test_case = TestCase.new(code, source_file, source_line, method_name)
35
- return rewrite_exceptions{ test_case.run(*args) }
36
- rescue Exception => e
37
- return e
38
- ensure
39
- @last_assertion_count = defined?(test_case.assertion_count) ? test_case.assertion_count : 0
40
- end
41
- private
42
- # We need to strib down and generalise the exceptions to prevent the integration project from having to know anything about anything.
43
- def rewrite_exceptions
44
- return yield
45
- rescue Test::Unit::AssertionFailedError
46
- raise
47
- rescue ArgumentError => e
48
- raise e unless e.message =~ /Anonymous modules /
49
- raise NameError, "Const Missing", e.backtrace[3..-1]
50
- rescue Exception => e
51
- raise Drunit::RemoteError.new(e.class.name), e.message, e.backtrace
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
- def class
8
- if type = look_up_exception
9
- return type
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 look_up_exception
17
- @real_exception.split("::").inject(Object){|node, part|
18
- node && node.const_defined?(part) && node.const_get(part)
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
- module ClassMethods
24
- def RemoteApp(name, *args)
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 = caller(2).first.split(":")
31
- method ||= "unknown_method"
32
- remote_app_for(name).run(method.gsub(/^in /, "").gsub(/[^a-zA-Z0-9_?!]/, ""), file, line.to_i, *args, &block)
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
- remote_app_for(name).last_assertion_count.times{ add_assertion } rescue nil
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
 
@@ -7,6 +7,12 @@ end
7
7
  class SomeException < Exception
8
8
  end
9
9
 
10
+ class SomeOtherTestCase
11
+ def assert_in_new_test_case
12
+ add_assertion
13
+ end
14
+ end
15
+
10
16
  module MyModule
11
17
  class SomeOtherException < Exception
12
18
  end
@@ -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, FAKE_APP_PATH + "/fake_app.rb")
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("RemoteApp<fake_app>").size
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
- version: "0.2"
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: 2009-04-07 00:00:00 +01:00
13
- default_executable: drunit_remote
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
- - bin/drunit_remote
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.1
70
+ rubygems_version: 1.3.6
61
71
  signing_key:
62
- specification_version: 2
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