chaser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,109 @@
1
+ History for Chaser:
2
+
3
+ * Coming soon
4
+
5
+ History for Heckle:
6
+
7
+ === 1.4.3 / 2009-06-23
8
+
9
+ * 2 minor enhancements:
10
+
11
+ * Added autotest/heckle plugin
12
+ * Skipping testing on 1.9
13
+
14
+ === 1.4.2 / 2009-02-08
15
+
16
+ * 2 bug fixes:
17
+
18
+ * Fixed Ruby2Ruby dependency and Ruby2Ruby references (name changed).
19
+ Reported by David Chelimsky
20
+ * Fix bug #11435 where [:iter, [:call], ...] would cause an endless
21
+ loop. Reported by Thomas Preymesser.
22
+
23
+ === 1.4.1 / 2007-06-05
24
+
25
+ * 3 bug fixes:
26
+
27
+ * Add zentest as a heckle dependency. Closes #10996
28
+ * Fixed heckling of call with blocks.
29
+ * Fix test_unit_heckler's test_pass? so it returns the result of the
30
+ run rather than ARGV.clear
31
+
32
+ === 1.4.0 / 2007-05-18
33
+
34
+ * 2 major enhancements:
35
+
36
+ * Method calls are now heckled (by removal).
37
+ * Assignments are now heckled (by value changing).
38
+
39
+ * 3 minor enhancements:
40
+
41
+ * Added --focus to feel the Eye of Sauron (specify unit tests to run).
42
+ * Specify nodes to be included/excluded in heckle with -n/-x.
43
+ * Test only assignments with --assignments
44
+
45
+ === 1.3.0 / 2007-02-12
46
+
47
+ * 1 major enhancement:
48
+
49
+ * Unified diffs for mutatated methods
50
+
51
+ * 4 minor enhancements:
52
+
53
+ * Now returns exit status 1 if failed.
54
+ * Added a simple report at the end.
55
+ * Runs are now sorted by method.
56
+ * Autodetects rails and changes test_pattern accordingly.
57
+
58
+ * 2 bug fixes:
59
+
60
+ * Aborts when an unknown method is supplied.
61
+ * Escapes slashes in random regexps.
62
+
63
+ === 1.2.0 / 2007-01-15
64
+
65
+ * 2 major enhancements:
66
+
67
+ * Timeout for tests set dynamically and overridable with -T
68
+ * Class method support with "self.method_name"
69
+
70
+ * 3 minor enhancements:
71
+
72
+ * -b allows heckling of branches only
73
+ * Restructured class heirarchy and got rid of Base and others.
74
+ * Revamped the tests and reduced size by 60%.
75
+
76
+ * 1 bug fix:
77
+
78
+ * Fixed the infinite loop caused by syntax errors
79
+
80
+ === 1.1.1 / 2006-12-20
81
+
82
+ * 3 bug fixes:
83
+
84
+ * Load tests properly when supplying method name.
85
+ * Make sure random symbols have at least one character.
86
+ * Removed all extra warnings from the unit tests. Consolidated and cleaned.
87
+
88
+ === 1.1.0 / 2006-12-19
89
+
90
+ * 12 major enhancements:
91
+
92
+ * Able to roll back original method after processing.
93
+ * Can mutate numeric literals.
94
+ * Can mutate strings.
95
+ * Can mutate a node at a time.
96
+ * Can mutate if/unless
97
+ * Decoupled from Test::Unit
98
+ * Cleaner output
99
+ * Can mutate true and false.
100
+ * Can mutate while and until.
101
+ * Can mutate regexes, ranges, symbols
102
+ * Can run against entire classes
103
+ * Command line options!
104
+
105
+ === 1.0.0 / 2006-10-22
106
+
107
+ * 1 major enhancement
108
+
109
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,10 @@
1
+ chaser.gemspec
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/chaser
7
+ lib/chaser.rb
8
+ lib/test_unit_chaser.rb
9
+ test/fixtures/chased.rb
10
+ test/test_chaser.rb
data/README.txt ADDED
@@ -0,0 +1,47 @@
1
+ = chaser
2
+
3
+ * Web site coming real soon now
4
+
5
+ == DESCRIPTION:
6
+
7
+ Chaser is unit test sadism(tm), like Seattlerb's Heckle. It's more or less mutation testing, except that rather than mutating every line of code it can get its claws into, it merely modifies the return value of targeted methods. If the unit tests don't notice the modified return values, or the program going haywire as a result of using those modified return values, then they aren't doing their jobs properly.
8
+
9
+ Unit test sadism is a trademark of Ryan Davis and Kevin Clark, and is used without permission.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * It only mutates the return values of methods.
14
+ * It should be able to mutate class methods, and work in ruby 1.9 or Windows.
15
+
16
+ == REQUIREMENTS:
17
+
18
+ * None!
19
+
20
+ == INSTALL:
21
+
22
+ * sudo gem install agrimm-chaser
23
+
24
+ == LICENSE:
25
+
26
+ (The MIT License)
27
+
28
+ Copyright (c) 2006-2009 Ryan Davis and Kevin Clark and Andrew Grimm
29
+
30
+ Permission is hereby granted, free of charge, to any person obtaining
31
+ a copy of this software and associated documentation files (the
32
+ 'Software'), to deal in the Software without restriction, including
33
+ without limitation the rights to use, copy, modify, merge, publish,
34
+ distribute, sublicense, and/or sell copies of the Software, and to
35
+ permit persons to whom the Software is furnished to do so, subject to
36
+ the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be
39
+ included in all copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
42
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
44
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
45
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
46
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ task :default => [:test]
2
+
3
+ begin
4
+ require 'jeweler'
5
+ require File.dirname(__FILE__) + "/lib/chaser.rb"
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "chaser"
8
+ gemspec.summary = "Unit test sadism, with less masochism"
9
+ gemspec.description = "Lightweight mutation testing in any flavor of ruby"
10
+ gemspec.email = "andrew.j.grimm@gmail.com"
11
+ gemspec.authors = ["Andrew Grimm", "Ryan Davis", "Eric Hodel", "Kevin Clark"]
12
+ gemspec.add_dependency('test-unit') #Ruby 1.9 doesn't have full test-unit in the standard library.
13
+ gemspec.version = Chaser::VERSION
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ task :test do
20
+ ruby "test/test_chaser.rb"
21
+ end
22
+
data/bin/chaser ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+ require 'test_unit_chaser'
5
+ require 'optparse'
6
+
7
+ force = false
8
+
9
+ opts = OptionParser.new do |opts|
10
+ opts.banner = "Usage: #{File.basename($0)} class_name [method_name]"
11
+ opts.on("-v", "--verbose", "Loudly explain chaser run") do |opt|
12
+ TestUnitChaser.debug = true
13
+ end
14
+
15
+ opts.on("-V", "--version", "Prints Chaser's version number") do |opt|
16
+ puts "Chaser #{Chaser::VERSION}"
17
+ exit 0
18
+ end
19
+
20
+ opts.on("-t", "--tests TEST_PATTERN",
21
+ "Location of tests (glob)") do |pattern|
22
+ TestUnitChaser.test_pattern = pattern
23
+ end
24
+
25
+ opts.on("-F", "--force", "Ignore initial test failures") do |opt|
26
+ force = true
27
+ end
28
+
29
+ opts.on("-T", "--timeout SECONDS", "The maximum time for a test run in seconds",
30
+ "Used to catch infinite loops") do |timeout|
31
+ Chaser.timeout = timeout.to_i
32
+ puts "Setting timeout at #{timeout} seconds."
33
+ end
34
+
35
+ opts.on("-h", "--help", "Show this message") do |opt|
36
+ puts opts
37
+ exit 0
38
+ end
39
+ end
40
+
41
+ looks_like_rails = test ?f, 'config/environment.rb'
42
+ TestUnitChaser.test_pattern = "test/**/*.rb" if looks_like_rails
43
+
44
+ opts.parse!
45
+
46
+ impl = ARGV.shift
47
+ meth = ARGV.shift
48
+
49
+ unless impl then
50
+ puts opts
51
+ exit 1
52
+ end
53
+
54
+ exit TestUnitChaser.validate(impl, meth, force)
55
+
data/lib/chaser.rb ADDED
@@ -0,0 +1,329 @@
1
+ require 'rubygems'
2
+ require 'timeout'
3
+
4
+ class String # :nodoc:
5
+ def to_class
6
+ split(/::/).inject(Object) { |klass, name| klass.const_get(name) }
7
+ end
8
+ end
9
+
10
+ ##
11
+ # Test Unit Sadism
12
+
13
+ class Chaser
14
+
15
+ class Timeout < Timeout::Error; end
16
+
17
+ ##
18
+ # The version of Chaser you are using.
19
+
20
+ VERSION = '0.0.1'
21
+
22
+ ##
23
+ # Is this platform MS Windows-like?
24
+
25
+ WINDOZE = RUBY_PLATFORM =~ /mswin/
26
+
27
+ ##
28
+ # Path to the bit bucket.
29
+
30
+ NULL_PATH = WINDOZE ? 'NUL:' : '/dev/null'
31
+
32
+ ##
33
+ # Class being chased
34
+
35
+ attr_accessor :klass
36
+
37
+ ##
38
+ # Name of class being chased
39
+
40
+ attr_accessor :klass_name
41
+
42
+ ##
43
+ # Method being chased
44
+
45
+ attr_accessor :method
46
+
47
+ ##
48
+ # Name of method being chased
49
+
50
+ attr_accessor :method_name
51
+
52
+ ##
53
+ # The original version of the method being chased
54
+
55
+ attr_reader :old_method
56
+
57
+ @@debug = false
58
+ @@guess_timeout = true
59
+ @@timeout = 60 # default to something longer (can be overridden by runners)
60
+
61
+ def self.debug
62
+ @@debug
63
+ end
64
+
65
+ def self.debug=(value)
66
+ @@debug = value
67
+ end
68
+
69
+ def self.timeout=(value)
70
+ @@timeout = value
71
+ @@guess_timeout = false # We've set the timeout, don't guess
72
+ end
73
+
74
+ def self.guess_timeout?
75
+ @@guess_timeout
76
+ end
77
+
78
+ ##
79
+ # Creates a new Chaser that will chase +klass_name+ and +method_name+,
80
+ # sending results to +reporter+.
81
+
82
+ def initialize(klass_name = nil, method_name = nil, reporter = Reporter.new)
83
+ @klass_name = klass_name
84
+ @method_name = method_name.intern if method_name
85
+
86
+ @klass = klass_name.to_class
87
+
88
+ @method = nil
89
+ @reporter = reporter
90
+
91
+ @mutated = false
92
+
93
+ @failure = false
94
+ end
95
+
96
+ ##
97
+ # Overwrite test_pass? for your own Chaser runner.
98
+
99
+ def tests_pass?
100
+ raise NotImplementedError
101
+ end
102
+
103
+ def run_tests
104
+ if tests_pass? then
105
+ record_passing_mutation
106
+ else
107
+ @reporter.report_test_failures
108
+ end
109
+ end
110
+
111
+ ############################################################
112
+ ### Running the script
113
+
114
+ def validate
115
+ @reporter.method_loaded(klass_name, method_name)
116
+
117
+ begin
118
+ modify_method
119
+ timeout(@@timeout, Chaser::Timeout) { run_tests }
120
+ rescue Chaser::Timeout
121
+ @reporter.warning "Your tests timed out. Chaser may have caused an infinite loop."
122
+ rescue Interrupt
123
+ @reporter.warning 'Mutation canceled, hit ^C again to exit'
124
+ sleep 2
125
+ end
126
+
127
+ unmodify_method # in case we're validating again. we should clean up.
128
+
129
+ if @failure
130
+ @reporter.report_failure
131
+ false
132
+ else
133
+ @reporter.no_surviving_mutant
134
+ true
135
+ end
136
+ end
137
+
138
+ def record_passing_mutation
139
+ @failure = true
140
+ end
141
+
142
+ def unmodify_instance_method
143
+ chaser = self
144
+ @mutated = false
145
+ @klass.send(:define_method, @method_name) do |*args|
146
+ chaser.old_method.bind(self).call(*args)
147
+ end
148
+ end
149
+
150
+ def unmodify_class_method
151
+ chaser = self
152
+ @mutated = false
153
+ aliasing_class(@method_name).send(:define_method, clean_method_name) do |*args|
154
+ chaser.old_method.bind(self).call(*args)
155
+ end
156
+ end
157
+
158
+ def modify_instance_method
159
+ chaser = self
160
+ @mutated = true
161
+ @old_method = @klass.instance_method(@method_name)
162
+ @klass.send(:define_method, @method_name) do |*args|
163
+ chaser.mutate_value(chaser.old_method.bind(self).call(*args))
164
+ end
165
+ end
166
+
167
+ def modify_class_method
168
+ chaser = self
169
+ @mutated = true
170
+ @old_method = aliasing_class(@method_name).instance_method(clean_method_name)
171
+ aliasing_class(@method_name).send(:define_method, clean_method_name) do |*args|
172
+ chaser.mutate_value(chaser.old_method.bind(self).call(*args))
173
+ end
174
+ end
175
+
176
+ def modify_method
177
+ if method_name.to_s =~ /self\./
178
+ modify_class_method
179
+ else
180
+ modify_instance_method
181
+ end
182
+ end
183
+
184
+ def unmodify_method
185
+ if method_name.to_s =~ /self\./ #TODO fix duplication. Give the test a name
186
+ unmodify_class_method
187
+ else
188
+ unmodify_instance_method
189
+ end
190
+ end
191
+
192
+
193
+ ##
194
+ # Replaces the value with a random value.
195
+
196
+ def mutate_value(value)
197
+ case value
198
+ when Fixnum, Float, Bignum
199
+ value + rand_number
200
+ when String
201
+ rand_string
202
+ when Symbol
203
+ rand_symbol
204
+ when Regexp
205
+ Regexp.new(Regexp.escape(rand_string.gsub(/\//, '\\/')))
206
+ when Range
207
+ rand_range
208
+ when NilClass, FalseClass
209
+ rand_number
210
+ when TrueClass
211
+ false
212
+ else
213
+ nil
214
+ end
215
+ end
216
+
217
+ ############################################################
218
+ ### Convenience methods
219
+
220
+ def aliasing_class(method_name)
221
+ method_name.to_s =~ /self\./ ? class << @klass; self; end : @klass
222
+ end
223
+
224
+ def clean_method_name
225
+ method_name.to_s.gsub(/self\./, '')
226
+ end
227
+
228
+ ##
229
+ # Returns a random Fixnum.
230
+
231
+ def rand_number
232
+ (rand(100) + 1)*((-1)**rand(2))
233
+ end
234
+
235
+ ##
236
+ # Returns a random String
237
+
238
+ def rand_string
239
+ size = rand(50)
240
+ str = ""
241
+ size.times { str << rand(126).chr }
242
+ str
243
+ end
244
+
245
+ ##
246
+ # Returns a random Symbol
247
+
248
+ def rand_symbol
249
+ letters = ('a'..'z').to_a + ('A'..'Z').to_a
250
+ str = ""
251
+ (rand(50) + 1).times { str << letters[rand(letters.size)] }
252
+ :"#{str}"
253
+ end
254
+
255
+ ##
256
+ # Returns a random Range
257
+
258
+ def rand_range
259
+ min = rand(50)
260
+ max = min + rand(50)
261
+ min..max
262
+ end
263
+
264
+ ##
265
+ # Suppresses output on $stdout and $stderr.
266
+
267
+ def silence_stream
268
+ return yield if @@debug
269
+
270
+ begin
271
+ dead = File.open(Chaser::NULL_PATH, "w")
272
+
273
+ $stdout.flush
274
+ $stderr.flush
275
+
276
+ oldstdout = $stdout.dup
277
+ oldstderr = $stderr.dup
278
+
279
+ $stdout.reopen(dead)
280
+ $stderr.reopen(dead)
281
+
282
+ result = yield
283
+
284
+ ensure
285
+ $stdout.flush
286
+ $stderr.flush
287
+
288
+ $stdout.reopen(oldstdout)
289
+ $stderr.reopen(oldstderr)
290
+ result
291
+ end
292
+ end
293
+
294
+ class Reporter
295
+ def method_loaded(klass_name, method_name)
296
+ info "#{klass_name}\##{method_name} loaded"
297
+ end
298
+
299
+ def warning(message)
300
+ puts "!" * 70
301
+ puts "!!! #{message}"
302
+ puts "!" * 70
303
+ puts
304
+ end
305
+
306
+ def info(message)
307
+ puts "*"*70
308
+ puts "*** #{message}"
309
+ puts "*"*70
310
+ puts
311
+ end
312
+
313
+ def report_failure
314
+ puts
315
+ puts "The affected method didn't cause test failures."
316
+ puts
317
+ end
318
+
319
+ def no_surviving_mutant
320
+ puts "The mutant didn't survive. Cool!\n\n"
321
+ end
322
+
323
+ def report_test_failures
324
+ puts "Tests failed -- this is good" if Chaser.debug
325
+ end
326
+ end
327
+
328
+ end
329
+
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit/autorunner'
4
+ require 'test/unit/testcase'
5
+ require 'chaser'
6
+
7
+ $: << 'lib' << 'test'
8
+
9
+ # Make sure test/unit doesn't swallow our timeout
10
+ begin
11
+ Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS << Chaser::Timeout
12
+ rescue NameError
13
+ # ignore
14
+ end
15
+
16
+ class TestUnitChaser < Chaser
17
+
18
+ @@test_pattern = 'test/test_*.rb'
19
+ @@tests_loaded = false
20
+
21
+ def self.test_pattern=(value)
22
+ @@test_pattern = value
23
+ end
24
+
25
+ def self.load_test_files
26
+ @@tests_loaded = true
27
+ Dir.glob(@@test_pattern).each {|test| require test}
28
+ end
29
+
30
+ def self.validate(klass_name, method_name = nil, force = false)
31
+ load_test_files
32
+ klass = klass_name.to_class
33
+
34
+ # Does the method exist?
35
+ klass_methods = klass.singleton_methods(false).collect {|meth| "self.#{meth}"}
36
+ if method_name
37
+ if method_name =~ /self\./
38
+ abort "Unknown method: #{klass_name}.#{method_name.gsub('self.', '')}" unless klass_methods.include? method_name
39
+ else
40
+ abort "Unknown method: #{klass_name}##{method_name}" unless klass.instance_methods(false).include? method_name
41
+ end
42
+ end
43
+
44
+ initial_time = Time.now
45
+
46
+ chaser = self.new(klass_name)
47
+
48
+ passed = chaser.tests_pass?
49
+
50
+ unless force or passed then
51
+ abort "Initial run of tests failed... fix and run chaser again"
52
+ end
53
+
54
+ if self.guess_timeout? then
55
+ running_time = Time.now - initial_time
56
+ adjusted_timeout = (running_time * 2 < 5) ? 5 : (running_time * 2).ceil
57
+ self.timeout = adjusted_timeout
58
+ end
59
+
60
+ puts "Timeout set to #{adjusted_timeout} seconds."
61
+
62
+ if passed then
63
+ puts "Initial tests pass. Let's rumble."
64
+ else
65
+ puts "Initial tests failed but you forced things. Let's rumble."
66
+ end
67
+ puts
68
+
69
+ methods = method_name ? Array(method_name) : klass.instance_methods(false) + klass_methods
70
+
71
+ counts = Hash.new(0)
72
+ methods.sort.each do |method_name|
73
+ result = self.new(klass_name, method_name).validate
74
+ counts[result] += 1
75
+ end
76
+ all_good = counts[false] == 0
77
+
78
+ puts "Chaser Results:"
79
+ puts
80
+ puts "Passed : %3d" % counts[true]
81
+ puts "Failed : %3d" % counts[false]
82
+ puts
83
+
84
+ if all_good then
85
+ puts "All chasing was thwarted! YAY!!!"
86
+ else
87
+ puts "Improve the tests and try again."
88
+ end
89
+
90
+ all_good
91
+ end
92
+
93
+ def initialize(klass_name=nil, method_name=nil)
94
+ super
95
+ self.class.load_test_files unless @@tests_loaded
96
+ end
97
+
98
+ def tests_pass?
99
+ silence_stream do
100
+ result = Test::Unit::AutoRunner.run
101
+ ARGV.clear
102
+ result
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,13 @@
1
+ class Chased
2
+ def add(a,b)
3
+ a + b
4
+ end
5
+
6
+ def say_hello
7
+ "G'day!"
8
+ end
9
+
10
+ def self.static_method
11
+ "Zap!"
12
+ end
13
+ end
@@ -0,0 +1,76 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/fixtures')
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'test/unit/testcase'
5
+ require 'test/unit' if $0 == __FILE__
6
+ require 'test_unit_chaser'
7
+ require 'chased'
8
+
9
+ class TestChaser < Chaser
10
+ def rand(*args)
11
+ 5
12
+ end
13
+
14
+ def rand_string
15
+ "l33t h4x0r"
16
+ end
17
+
18
+ def rand_number(*args)
19
+ 5
20
+ end
21
+
22
+ def rand_symbol
23
+ :"l33t h4x0r"
24
+ end
25
+ end
26
+
27
+ class ChaserTestCase < Test::Unit::TestCase
28
+ unless defined? Mini then
29
+ undef_method :default_test
30
+ alias :refute_equal :assert_not_equal
31
+ end
32
+
33
+ def setup
34
+ end
35
+
36
+ def teardown
37
+ @chaser.unmodify_method if defined?(@chaser) && @chaser
38
+ end
39
+
40
+ def test_unmodified_behaves_as_expected
41
+ chased = Chased.new
42
+ assert_equal 5, chased.add(2,3), "Unmodified version should equal 5"
43
+ end
44
+
45
+ def test_modify_and_unmodify_instance_method
46
+ @chaser = TestChaser.new("Chased", "add")
47
+ chased = Chased.new
48
+ assert_equal 5, chased.add(2,3), "method has been modified before it should have been"
49
+ @chaser.modify_method
50
+ assert_equal 10, chased.add(2,3), "method hasn't been modified"
51
+ @chaser.unmodify_method
52
+ assert_equal 5, chased.add(2,3), "method should be back to normal, but it isn't"
53
+ end
54
+
55
+ def test_modify_and_unmodify_string
56
+ @chaser = TestChaser.new("Chased", "say_hello")
57
+ chased = Chased.new
58
+ assert_equal "G'day!", chased.say_hello, "method has been modified before it should have been"
59
+ @chaser.modify_method
60
+ assert_equal "l33t h4x0r", chased.say_hello, "method hasn't been modified"
61
+ @chaser.unmodify_method
62
+ assert_equal "G'day!", chased.say_hello, "method should be back to normal, but it isn't"
63
+ end
64
+
65
+ def test_modify_and_unmodify_class_method
66
+ @chaser = TestChaser.new("Chased", "self.static_method")
67
+ assert_equal "Zap!", Chased.static_method, "class method has been modified before it should have been"
68
+ @chaser.modify_method
69
+ assert_equal "l33t h4x0r", Chased.static_method, "class method hasn't been modified"
70
+ @chaser.unmodify_method
71
+ assert_equal "Zap!", Chased.static_method, "class method should be back to normal, but it isn't"
72
+ end
73
+
74
+ end
75
+
76
+
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chaser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Grimm
8
+ - Ryan Davis
9
+ - Eric Hodel
10
+ - Kevin Clark
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+
15
+ date: 2009-11-07 00:00:00 +11:00
16
+ default_executable: chaser
17
+ dependencies: []
18
+
19
+ description: Lightweight mutation testing in any flavor of ruby
20
+ email: andrew.j.grimm@gmail.com
21
+ executables:
22
+ - chaser
23
+ extensions: []
24
+
25
+ extra_rdoc_files:
26
+ - README.txt
27
+ files:
28
+ - History.txt
29
+ - Manifest.txt
30
+ - README.txt
31
+ - Rakefile
32
+ - bin/chaser
33
+ - lib/chaser.rb
34
+ - lib/test_unit_chaser.rb
35
+ - test/fixtures/chased.rb
36
+ - test/test_chaser.rb
37
+ has_rdoc: true
38
+ homepage:
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Unit test sadism, with less masochism
65
+ test_files:
66
+ - test/fixtures/chased.rb
67
+ - test/test_chaser.rb