stubborn 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Daniel Cadenas
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ = stubborn
2
+
3
+ A Ruby gem that helps you find missing stubs in your tests.
4
+
5
+ Say you have this classes:
6
+
7
+ class Api
8
+ def slow_method(a, b, c)
9
+ ...
10
+ end
11
+ end
12
+
13
+ class MyClassThatUsesApi
14
+ def useful_method
15
+ ...
16
+ important_value = api.slow_method(important_parameter, something_else, another)
17
+ ...
18
+ end
19
+ end
20
+
21
+ And you have this somewhere in your test_helper/spec_helper:
22
+
23
+ require 'rubygems'
24
+ require 'stubborn'
25
+
26
+ Stubborn.should_be_stubbed(Api)
27
+
28
+ Then if you forget about stubbing the api class in some of your tests like this:
29
+
30
+ it "should do something useful" do
31
+ MyClassThatUsesApi.new.useful_method.should be_useful
32
+ end
33
+
34
+ You will know that you missed it because the test will fail with an exception including all information you need to construct the correct stub:
35
+
36
+ You've missed adding a stub. Consider this suggestions:
37
+ api_instance.stub!(:slow_method).with(123, AClass, "hi").and_return(another_class_instance)
38
+ api_instance.stub!(:slow_method).and_return(another_class_instance)
39
+
40
+ == Installation
41
+
42
+ sudo gem install stubborn
43
+
44
+ == To Do
45
+
46
+ * Filters so that you can choose which methods to include or exclude
47
+ * Stub suggestions for more test frameworks. It currently show only rspec syntax
48
+
49
+ == Collaborate
50
+
51
+ http://github.com/dcadenas/stubborn
52
+
53
+ == Copyright
54
+
55
+ Copyright (c) 2009 Daniel Cadenas. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "stubborn"
8
+ gem.summary = %Q{A gem to help you find your missing stubs}
9
+ gem.email = "dcadenas@gmail.com"
10
+ gem.homepage = "http://github.com/dcadenas/stubborn"
11
+ gem.authors = ["Daniel Cadenas"]
12
+ gem.rubyforge_project = "stubborn"
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/*_test.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ if File.exist?('VERSION.yml')
46
+ config = YAML.load(File.read('VERSION.yml'))
47
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
48
+ else
49
+ version = ""
50
+ end
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "stubborn #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
57
+
58
+ begin
59
+ require 'rake/contrib/sshpublisher'
60
+ namespace :rubyforge do
61
+
62
+ desc "Release gem and RDoc documentation to RubyForge"
63
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
64
+
65
+ namespace :release do
66
+ desc "Publish RDoc to RubyForge."
67
+ task :docs => [:rdoc] do
68
+ config = YAML.load(
69
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
70
+ )
71
+
72
+ host = "#{config['username']}@rubyforge.org"
73
+ remote_dir = "/var/www/gforge-projects/stubborn/"
74
+ local_dir = 'rdoc'
75
+
76
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
77
+ end
78
+ end
79
+ end
80
+ rescue LoadError
81
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
82
+ end
83
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
@@ -0,0 +1,27 @@
1
+ module Stubborn
2
+ class MissedStubException < RuntimeError
3
+ def initialize(object, method_name, args, result, suggester)
4
+ object_label = friendly_name(object)
5
+ args = args.map{|a| friendly_name(a)}.join(", ")
6
+ result = friendly_name(result)
7
+
8
+ @suggestions = suggester.suggestions(object_label, method_name, args, result)
9
+ end
10
+
11
+ def message
12
+ "You've missed adding a stub. Consider this suggestion#{@suggestions.size > 1 ? "s" : ""}:\n#{@suggestions.join("\n")}"
13
+ end
14
+
15
+ private
16
+ def friendly_name(object)
17
+ return "\"#{object}\"" if object.respond_to?(:to_str)
18
+ return object.inspect if object.respond_to?(:to_int)
19
+
20
+ if object.is_a?(Class)
21
+ object.name
22
+ else
23
+ "#{object.class.name.downcase}_instance"
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/stubborn.rb ADDED
@@ -0,0 +1,62 @@
1
+ begin
2
+ require 'proxen'
3
+ rescue LoadError
4
+ puts "You need to install the proxen gem: sudo gem install nakajima-proxen -s http://gems.github.com"
5
+ exit
6
+ end
7
+
8
+ require 'suggesters/rspec_suggester'
9
+ require 'missed_stub_exception'
10
+
11
+ module Stubborn
12
+ def self.should_be_stubbed(object)
13
+ if object.is_a?(Class)
14
+ ProxyForClass.new(object)
15
+ else
16
+ ProxyForInstance.new(object)
17
+ end
18
+ end
19
+
20
+ class ProxyForInstance
21
+ attr_accessor :proxy_target
22
+ proxy_to :proxy_target, :blank_slate => true
23
+
24
+ def initialize(proxy_target, klass = proxy_target.class)
25
+ @proxy_target = proxy_target
26
+ @klass = klass
27
+ @methods_to_skip = ["respond_to?", "is_a?"]
28
+ end
29
+
30
+ def class
31
+ @klass
32
+ end
33
+
34
+ def method_missing(method_name, *args, &block)
35
+ result = @proxy_target.send(method_name, *args, &block)
36
+ return result if @methods_to_skip.include?(method_name.to_s)
37
+ raise MissedStubException.new(@proxy_target, method_name, args, result, Suggesters::RSpecSuggester)
38
+ end
39
+ end
40
+
41
+ class ProxyForClass < ProxyForInstance
42
+ def initialize(proxy_target)
43
+ super
44
+ redefine_const(proxy_target.name, self) unless proxy_target.name.strip.empty?
45
+ end
46
+
47
+ def name
48
+ @proxy_target.name
49
+ end
50
+
51
+ def new(*args, &block)
52
+ new_instance = @proxy_target.new(*args, &block)
53
+ ProxyForInstance.new(new_instance, self)
54
+ end
55
+
56
+ private
57
+ def redefine_const(name, value)
58
+ Object.__send__(:remove_const, name) if Object.const_defined?(name)
59
+ Object.const_set(name, value)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,14 @@
1
+ module Stubborn
2
+ module Suggesters
3
+ module RSpecSuggester
4
+ def self.suggestions(object_label, method_name, args, result)
5
+ with = args.strip.empty? ? nil : ".with(#{args})"
6
+ and_return = result.nil? ? nil : ".and_return(#{result})"
7
+ suggestions = []
8
+ suggestions << "#{object_label}.stub!(:#{method_name})#{with}#{and_return}"
9
+ suggestions << "#{object_label}.stub!(:#{method_name})#{and_return}"
10
+ suggestions.uniq
11
+ end
12
+ end
13
+ end
14
+ end
data/stubborn.gemspec ADDED
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{stubborn}
5
+ s.version = "0.1.2"
6
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
+ s.authors = ["Daniel Cadenas"]
8
+ s.date = %q{2009-10-02}
9
+ s.email = %q{dcadenas@gmail.com}
10
+ s.extra_rdoc_files = [
11
+ "LICENSE",
12
+ "README.rdoc"
13
+ ]
14
+
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "lib/missed_stub_exception.rb",
23
+ "lib/stubborn.rb",
24
+ "lib/suggesters/rspec_suggester.rb",
25
+ "stubborn.gemspec",
26
+ "test/stubborn_method_filtering_test.rb",
27
+ "test/stubborn_test.rb",
28
+ "test/suggesters/rspec_suggester_test.rb",
29
+ "test/test_helper.rb"
30
+ ]
31
+ s.homepage = %q{http://github.com/dcadenas/stubborn}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubyforge_project = %q{stubborn}
35
+ s.rubygems_version = %q{1.3.3}
36
+ s.summary = %q{A gem to help you find your missing stubs}
37
+ s.test_files = [
38
+ "test/stubborn_method_filtering_test.rb",
39
+ "test/stubborn_test.rb",
40
+ "test/suggesters/rspec_suggester_test.rb",
41
+ "test/test_helper.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ else
50
+ end
51
+ else
52
+ end
53
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ def reset_test_api_class
4
+ name = "TestApi"
5
+ Object.__send__(:remove_const, name) if Object.const_defined?(name)
6
+ klass = Class.new do
7
+ def instance_method_1
8
+ "instance_method_1 called"
9
+ end
10
+
11
+ def instance_method_2
12
+ "instance_method_2 called"
13
+ end
14
+
15
+ def self.class_method_1
16
+ "class_method_1 called"
17
+ end
18
+
19
+ def self.class_method_2
20
+ "class_method_2 called"
21
+ end
22
+ end
23
+ Object.const_set(name, klass)
24
+ end
25
+
26
+ __END__
27
+ PENDING
28
+
29
+ Expectations do
30
+ expect "instance_method_1 called" do
31
+ api = TestApi.new
32
+ Stubborn.should_be_stubbed(api, :except => :instance_method_1)
33
+ api.instance_method_1
34
+ end
35
+
36
+ expect Stubborn::MissedStubException do
37
+ api = TestApi.new
38
+ Stubborn.should_be_stubbed(api, :except => :instance_method_1)
39
+ api.instance_method_2
40
+ end
41
+
42
+ expect "instance_method_2 called" do
43
+ api = TestApi.new
44
+ Stubborn.should_be_stubbed(api, :only => :instance_method_1)
45
+ api.instance_method_2
46
+ end
47
+
48
+ expect Stubborn::MissedStubException do
49
+ api = TestApi.new
50
+ Stubborn.should_be_stubbed(api, :only => :instance_method_1)
51
+ api.instance_method_1
52
+ end
53
+ end
@@ -0,0 +1,105 @@
1
+ require 'test_helper'
2
+
3
+ def reset_test_api_class
4
+ name = "TestApi"
5
+ Object.__send__(:remove_const, name) if Object.const_defined?(name)
6
+ klass = Class.new do
7
+ def plus_one(number)
8
+ number + 1
9
+ end
10
+
11
+ def self.plus_two(number)
12
+ number + 2
13
+ end
14
+ end
15
+ Object.const_set(name, klass)
16
+ end
17
+
18
+ Expectations do
19
+ expect 2 do
20
+ reset_test_api_class
21
+ TestApi.new.plus_one(1)
22
+ end
23
+
24
+ expect "TestApi" do
25
+ reset_test_api_class
26
+ api = TestApi.new
27
+ api = Stubborn.should_be_stubbed(api)
28
+ api.class.name
29
+ end
30
+
31
+ expect true do
32
+ reset_test_api_class
33
+ api = TestApi.new
34
+ api = Stubborn.should_be_stubbed(api)
35
+ api.respond_to?(:plus_one)
36
+ end
37
+
38
+ expect Stubborn::MissedStubException do
39
+ reset_test_api_class
40
+ api = TestApi.new
41
+ api = Stubborn.should_be_stubbed(api)
42
+ api.plus_one(1)
43
+ end
44
+
45
+ expect 3 do
46
+ reset_test_api_class
47
+ api = TestApi.new
48
+ api = Stubborn.should_be_stubbed(api)
49
+ api.class.plus_two(1)
50
+ end
51
+
52
+ expect "You've missed adding a stub. Consider this suggestions:\ntestapi_instance.stub!(:plus_one).with(0).and_return(1)\ntestapi_instance.stub!(:plus_one).and_return(1)" do
53
+ reset_test_api_class
54
+ api = TestApi.new
55
+ api = Stubborn.should_be_stubbed(api)
56
+ message = ""
57
+ begin
58
+ api.plus_one(0)
59
+ rescue => e
60
+ message = e.message
61
+ end
62
+ end
63
+
64
+ expect "TestApi" do
65
+ reset_test_api_class
66
+ Stubborn.should_be_stubbed(TestApi)
67
+ api = TestApi.new
68
+ api.class.name
69
+ end
70
+
71
+ expect true do
72
+ reset_test_api_class
73
+ Stubborn.should_be_stubbed(TestApi)
74
+ api = TestApi.new
75
+ api.respond_to?(:plus_one)
76
+ end
77
+
78
+ expect Stubborn::MissedStubException do
79
+ reset_test_api_class
80
+ Stubborn.should_be_stubbed(TestApi)
81
+ api = TestApi.new
82
+ api.plus_one(1)
83
+ end
84
+
85
+ expect Stubborn::MissedStubException do
86
+ reset_test_api_class
87
+ Stubborn.should_be_stubbed(TestApi)
88
+ api = TestApi.new
89
+ api.class.plus_two(1)
90
+ end
91
+
92
+ expect "You've missed adding a stub. Consider this suggestions:\ntestapi_instance.stub!(:plus_one).with(0).and_return(1)\ntestapi_instance.stub!(:plus_one).and_return(1)" do
93
+ reset_test_api_class
94
+ Stubborn.should_be_stubbed(TestApi)
95
+ message = ""
96
+ api = TestApi.new
97
+ begin
98
+ api.plus_one(0)
99
+ rescue => e
100
+ message = e.message
101
+ end
102
+ end
103
+ end
104
+
105
+
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class AClass; end
4
+ class Api; end
5
+
6
+ include Stubborn
7
+
8
+ Expectations do
9
+ expect "You've missed adding a stub. Consider this suggestions:\napi_instance.stub!(:method).with(123, AClass, \"hi\").and_return(aclass_instance)\napi_instance.stub!(:method).and_return(aclass_instance)" do
10
+ MissedStubException.new(Api.new, :method, [123, AClass,"hi"], AClass.new, Suggesters::RSpecSuggester).message
11
+ end
12
+
13
+ expect "You've missed adding a stub. Consider this suggestion:\napi_instance.stub!(:method).and_return(aclass_instance)" do
14
+ MissedStubException.new(Api.new, :method, [], AClass.new, Suggesters::RSpecSuggester).message
15
+ end
16
+ end
17
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'expectations'
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ require 'stubborn'
7
+
8
+ class Test::Unit::TestCase
9
+ end
10
+
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stubborn
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Cadenas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-02 00:00:00 -03:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: dcadenas@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - lib/missed_stub_exception.rb
33
+ - lib/stubborn.rb
34
+ - lib/suggesters/rspec_suggester.rb
35
+ - stubborn.gemspec
36
+ - test/stubborn_method_filtering_test.rb
37
+ - test/stubborn_test.rb
38
+ - test/suggesters/rspec_suggester_test.rb
39
+ - test/test_helper.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/dcadenas/stubborn
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --charset=UTF-8
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project: stubborn
64
+ rubygems_version: 1.3.3
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: A gem to help you find your missing stubs
68
+ test_files:
69
+ - test/stubborn_method_filtering_test.rb
70
+ - test/stubborn_test.rb
71
+ - test/suggesters/rspec_suggester_test.rb
72
+ - test/test_helper.rb