zombie-chaser 0.0.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/README.txt +47 -0
- data/Rakefile +24 -0
- data/bin/zombie-chaser +65 -0
- data/lib/chaser.rb +373 -0
- data/lib/human.rb +180 -0
- data/lib/interface.rb +77 -0
- data/lib/test_unit_handler.rb +42 -0
- data/lib/world.rb +93 -0
- data/lib/zombie_test_chaser.rb +133 -0
- data/test/fixtures/chased.rb +56 -0
- data/test/test_chaser.rb +144 -0
- data/test/test_unit.rb +2 -0
- data/test/test_zombie.rb +95 -0
- data/ui/icons/death.png +0 -0
- data/ui/icons/robot.png +0 -0
- data/ui/sprites/robot-attacking.png +0 -0
- data/ui/sprites/robot-dead.png +0 -0
- data/ui/sprites/robot-dying.png +0 -0
- data/ui/sprites/robot-idle.png +0 -0
- data/ui/sprites/robot-moving.png +0 -0
- data/ui/sprites/robot-turning.png +0 -0
- data/ui/sprites/tank-attacking.png +0 -0
- data/ui/sprites/tank-dead.png +0 -0
- data/ui/sprites/tank-idle.png +0 -0
- data/ui/sprites/tank-moving.png +0 -0
- data/ui/sprites/tank-turning.png +0 -0
- data/ui/sprites/witch-attacking.png +0 -0
- data/ui/sprites/witch-dead.png +0 -0
- data/ui/sprites/witch-idle.png +0 -0
- data/ui/sprites/witch-moving.png +0 -0
- data/ui/sprites/witch-turning.png +0 -0
- data/ui/sprites/zombie-attacking.png +0 -0
- data/ui/sprites/zombie-dead.png +0 -0
- data/ui/sprites/zombie-dying.png +0 -0
- data/ui/sprites/zombie-idle.png +0 -0
- data/ui/sprites/zombie-moving.png +0 -0
- data/ui/sprites/zombie-turning.png +0 -0
- data/ui/tiles/grass.png +0 -0
- data/ui/tiles/shrubbery.png +0 -0
- data/ui/ui.rb +117 -0
- metadata +109 -0
data/lib/interface.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
class Interface
|
2
|
+
attr_writer :human, :current_zombie
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@representations = []
|
6
|
+
@current_zombie = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_representation
|
10
|
+
if @current_zombie.nil?
|
11
|
+
"." * human_successful_step_count + @human.current_symbol
|
12
|
+
elsif human_successful_step_count > @current_zombie.successful_step_count
|
13
|
+
"." * @current_zombie.successful_step_count + @current_zombie.current_symbol + "." * (@human.successful_step_count - @current_zombie.successful_step_count - 1) + @human.current_symbol
|
14
|
+
else
|
15
|
+
"." * @current_zombie.successful_step_count + @current_zombie.current_symbol
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def human_successful_step_count
|
20
|
+
@human.successful_step_count
|
21
|
+
end
|
22
|
+
|
23
|
+
def something_happened
|
24
|
+
@representations << current_representation
|
25
|
+
display_representation(@representations.last)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class NoInterface < Interface
|
31
|
+
attr_reader :representations
|
32
|
+
|
33
|
+
def display_representation(representation)
|
34
|
+
#Do nothing
|
35
|
+
end
|
36
|
+
|
37
|
+
def finish
|
38
|
+
#Do nothing
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class ConsoleInterface < Interface
|
43
|
+
|
44
|
+
def display_representation(representation)
|
45
|
+
print "\r", representation
|
46
|
+
STDOUT.flush
|
47
|
+
sleep 0.2
|
48
|
+
end
|
49
|
+
|
50
|
+
def finish
|
51
|
+
puts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class GuiInterface < Interface
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@window = Window.new
|
59
|
+
#Actor.window = @window #Fixme why can't this do the trick?
|
60
|
+
Human.window = @window
|
61
|
+
Zombie.window = @window
|
62
|
+
@window_showing_thread = Thread.new {@window.show}
|
63
|
+
end
|
64
|
+
|
65
|
+
#Doesn't need to be used, as window updates 60 times a second anyway
|
66
|
+
def something_happened
|
67
|
+
end
|
68
|
+
|
69
|
+
def human=(human)
|
70
|
+
@window.human = human
|
71
|
+
end
|
72
|
+
|
73
|
+
def current_zombie=(current_zombie)
|
74
|
+
@window.current_zombie = current_zombie
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "test/unit/collector/objectspace"
|
2
|
+
require "test/unit/ui/testrunnermediator"
|
3
|
+
|
4
|
+
class TestUnitHandler
|
5
|
+
attr_reader :results
|
6
|
+
|
7
|
+
def initialize(test_pattern, actor)
|
8
|
+
@actor = actor
|
9
|
+
raise "Error: can't detect any files in test pattern \"#{test_pattern} (Don't forget to use forward slashes even in Windows)" if Dir.glob(test_pattern).empty?
|
10
|
+
Dir.glob(test_pattern).each {|test| require test} #In heckle, this is separated out
|
11
|
+
@finished = false
|
12
|
+
@results = []
|
13
|
+
@step_count = 0
|
14
|
+
obj_sp = Test::Unit::Collector::ObjectSpace.new
|
15
|
+
test_suite = Test::Unit::TestSuite.new("Mutation slayer test suite")
|
16
|
+
test_suite << obj_sp.collect
|
17
|
+
@test_runner_mediator = Test::Unit::UI::TestRunnerMediator.new(test_suite)
|
18
|
+
@test_runner_mediator.add_listener(Test::Unit::TestResult::FAULT) {test_failed}
|
19
|
+
@test_runner_mediator.add_listener(Test::Unit::TestCase::FINISHED) {test_finished}
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
catch(:stop_test_runner) do
|
25
|
+
@test_runner_mediator.run_suite
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_failed
|
30
|
+
@results << :failure
|
31
|
+
@actor.notify_failing_step
|
32
|
+
sleep 0.5
|
33
|
+
throw :stop_test_runner
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_finished
|
37
|
+
sleep 0.1 #Hack to avoid it being too quick
|
38
|
+
@results << :pass
|
39
|
+
@actor.notify_passing_step
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/world.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require "human"
|
2
|
+
require "interface"
|
3
|
+
|
4
|
+
class World
|
5
|
+
attr_reader :representations, :interface
|
6
|
+
|
7
|
+
def self.new_using_results(human_results, zombies_results)
|
8
|
+
world = new(:no_interface)
|
9
|
+
human = MockHuman.new_using_results(human_results, world)
|
10
|
+
zombie_list = MockZombieList.new_using_results(zombies_results, world)
|
11
|
+
world.set_human(human)
|
12
|
+
world.set_zombie_list(zombie_list)
|
13
|
+
world
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.new_using_test_unit_handler(test_pattern)
|
17
|
+
world = new(:gui_interface) #FIXME make this a choice between console and gui
|
18
|
+
human = Human.new_using_test_unit_handler(test_pattern, world)
|
19
|
+
zombie_list = MockZombieList.new_using_results([], world) #Fixme
|
20
|
+
world.set_human(human)
|
21
|
+
world.set_zombie_list(zombie_list)
|
22
|
+
world.set_test_pattern(test_pattern)
|
23
|
+
world
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(interface_type)
|
27
|
+
@human = nil
|
28
|
+
@current_zombie = nil
|
29
|
+
@zombie_list = nil
|
30
|
+
@test_pattern = nil
|
31
|
+
@interface = case interface_type
|
32
|
+
when :console_interface then ConsoleInterface.new
|
33
|
+
when :no_interface then NoInterface.new
|
34
|
+
when :gui_interface then GuiInterface.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_human(human)
|
39
|
+
raise "Already set" unless @human.nil?
|
40
|
+
@human = human
|
41
|
+
interface.human = human
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_zombie_list(zombie_list)
|
45
|
+
raise "Already set" unless @zombie_list.nil?
|
46
|
+
@zombie_list = zombie_list
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_test_pattern(test_pattern)
|
50
|
+
raise "Already set" unless @test_pattern.nil?
|
51
|
+
@test_pattern = test_pattern
|
52
|
+
end
|
53
|
+
|
54
|
+
#FIXME currently only used by the unit tests. It is equivalent to ZombieTestChaser.validate
|
55
|
+
def run
|
56
|
+
run_human
|
57
|
+
until (@human.dead? or @zombie_list.all_slain?)
|
58
|
+
run_zombie(@zombie_list.supply_next_zombie)
|
59
|
+
end
|
60
|
+
@interface.finish
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_human
|
64
|
+
@human.run
|
65
|
+
@human.finish_dying if @human.dying?
|
66
|
+
! @human.dead?
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_zombie_using_test_unit_handler
|
70
|
+
raise "@test_pattern not defined?" if @test_pattern.nil?
|
71
|
+
zombie = Zombie.new_using_test_unit_handler(@test_pattern, self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def run_zombie(zombie)
|
75
|
+
@current_zombie = zombie
|
76
|
+
@interface.current_zombie = zombie
|
77
|
+
sleep 0.2
|
78
|
+
@current_zombie.run
|
79
|
+
if @current_zombie.dying?
|
80
|
+
@current_zombie.finish_dying
|
81
|
+
else
|
82
|
+
@current_zombie.eat(@human)
|
83
|
+
sleep 1
|
84
|
+
end
|
85
|
+
! @current_zombie.dead?
|
86
|
+
end
|
87
|
+
|
88
|
+
def something_happened
|
89
|
+
@interface.something_happened
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "test/unit/collector/objectspace"
|
4
|
+
require "test/unit/ui/testrunnermediator"
|
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 ZombieTestChaser < Chaser
|
17
|
+
|
18
|
+
VERSION = '0.0.1'
|
19
|
+
|
20
|
+
@@test_pattern = 'test/test_*.rb'
|
21
|
+
@@tests_loaded = false
|
22
|
+
@@world = nil
|
23
|
+
|
24
|
+
def self.test_pattern=(value)
|
25
|
+
@@test_pattern = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create_world
|
29
|
+
@@tests_loaded = true
|
30
|
+
@@world = World.new_using_test_unit_handler(@@test_pattern)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.world
|
34
|
+
@@world
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.current_class_names(exclude_list)
|
38
|
+
result = []
|
39
|
+
ObjectSpace.each_object(Class) do |klass|
|
40
|
+
next if klass.to_s.include?("Class:0x")
|
41
|
+
next unless klass.ancestors.all? {|ancestor| (ancestor.to_s.split(/::/) & exclude_list).empty?}
|
42
|
+
result << klass.to_s
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.validate(klass_name = nil, method_name = nil, force = false)
|
48
|
+
pre_existing_class_names = self.current_class_names([]) unless klass_name
|
49
|
+
create_world
|
50
|
+
|
51
|
+
if klass_name
|
52
|
+
klass = klass_name.to_class
|
53
|
+
# Does the method exist?
|
54
|
+
klass_methods = klass.singleton_methods(false).collect {|meth| "self.#{meth}"}
|
55
|
+
if method_name
|
56
|
+
if method_name =~ /self\./
|
57
|
+
abort "Unknown method: #{klass_name}.#{method_name.gsub('self.', '')}" unless klass_methods.include? method_name
|
58
|
+
else
|
59
|
+
abort "Unknown method: #{klass_name}##{method_name}" unless klass.instance_methods(false).map{|sym| sym.to_s}.include? method_name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
initial_time = Time.now
|
65
|
+
|
66
|
+
chaser = self.new(klass_name)
|
67
|
+
|
68
|
+
passed = chaser.human_survives?
|
69
|
+
|
70
|
+
unless force or passed then
|
71
|
+
abort "Initial run of tests failed... fix and run chaser again"
|
72
|
+
end
|
73
|
+
|
74
|
+
if self.guess_timeout? then
|
75
|
+
running_time = Time.now - initial_time
|
76
|
+
adjusted_timeout = (running_time * 2 < 5) ? 5 : (running_time * 2).ceil
|
77
|
+
self.timeout = adjusted_timeout
|
78
|
+
end
|
79
|
+
|
80
|
+
puts "Timeout set to #{adjusted_timeout} seconds."
|
81
|
+
|
82
|
+
if passed then
|
83
|
+
puts "Initial tests pass. Let's rumble."
|
84
|
+
else
|
85
|
+
puts "Initial tests failed but you forced things. Let's rumble."
|
86
|
+
end
|
87
|
+
puts
|
88
|
+
|
89
|
+
counts = Hash.new(0)
|
90
|
+
|
91
|
+
klass_names = klass_name ? Array(klass_name) : self.current_class_names(["Test"]) - pre_existing_class_names
|
92
|
+
klass_names.each do |block_klass_name|
|
93
|
+
block_klass = block_klass_name.to_class
|
94
|
+
|
95
|
+
methods = method_name ? Array(method_name) : block_klass.instance_methods(false) + block_klass.singleton_methods(false).collect {|meth| "self.#{meth}"}
|
96
|
+
|
97
|
+
methods.sort.each do |block_method_name|
|
98
|
+
result = self.new(block_klass_name, block_method_name).validate
|
99
|
+
counts[result] += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
all_good = counts[false] == 0
|
103
|
+
|
104
|
+
puts "Chaser Results:"
|
105
|
+
puts
|
106
|
+
puts "Passed : %3d" % counts[true]
|
107
|
+
puts "Failed : %3d" % counts[false]
|
108
|
+
puts
|
109
|
+
|
110
|
+
if all_good then
|
111
|
+
puts "All chasing was thwarted! YAY!!!"
|
112
|
+
else
|
113
|
+
puts "Improve the tests and try again."
|
114
|
+
end
|
115
|
+
|
116
|
+
all_good
|
117
|
+
end
|
118
|
+
|
119
|
+
def human_survives?
|
120
|
+
self.class.world.run_human
|
121
|
+
end
|
122
|
+
|
123
|
+
def zombie_survives?
|
124
|
+
zombie = self.class.world.create_zombie_using_test_unit_handler
|
125
|
+
self.class.world.run_zombie(zombie)
|
126
|
+
end
|
127
|
+
|
128
|
+
def initialize(klass_name=nil, method_name=nil)
|
129
|
+
super
|
130
|
+
self.class.create_world unless @@tests_loaded
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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
|
+
|
14
|
+
def block_using_instance_method
|
15
|
+
result = []
|
16
|
+
block_yielding_instance_method do |i|
|
17
|
+
result << i * 2
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def block_yielding_instance_method
|
23
|
+
yield 1
|
24
|
+
yield 2
|
25
|
+
yield 3
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.block_using_class_method
|
29
|
+
result = []
|
30
|
+
block_yielding_class_method do |i|
|
31
|
+
result << i * 2
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.block_yielding_class_method
|
37
|
+
yield 1
|
38
|
+
yield 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](x)
|
42
|
+
x * 2
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.[](x)
|
46
|
+
x * 2
|
47
|
+
end
|
48
|
+
|
49
|
+
def question?
|
50
|
+
"exclamation!"
|
51
|
+
end
|
52
|
+
|
53
|
+
def foo=(x)
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
data/test/test_chaser.rb
ADDED
@@ -0,0 +1,144 @@
|
|
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 'zombie_test_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
|
+
def test_pass_blocks_on_in_instance_methods
|
75
|
+
@chaser = TestChaser.new("Chased", "block_yielding_instance_method")
|
76
|
+
chased = Chased.new
|
77
|
+
assert_equal [2,4,6], chased.block_using_instance_method, "block yielding instance method has been modified before it should have been"
|
78
|
+
@chaser.modify_method
|
79
|
+
assert_equal [12, 14, 16], chased.block_using_instance_method, "yielded values haven't been modified"
|
80
|
+
@chaser.unmodify_method
|
81
|
+
assert_equal [2,4,6], chased.block_using_instance_method, "block yielding instance method has been modified before it should have been"
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_pass_blocks_on_in_class_methods
|
85
|
+
@chaser = TestChaser.new("Chased", "self.block_yielding_class_method")
|
86
|
+
assert_equal [2,4], Chased.block_using_class_method, "block yielding class method has been modified before it should have been"
|
87
|
+
@chaser.modify_method
|
88
|
+
assert_equal [12, 14], Chased.block_using_class_method, "yielded values haven't been modified"
|
89
|
+
@chaser.unmodify_method
|
90
|
+
assert_equal [2,4], Chased.block_using_class_method, "block yielding class method has been modified before it should have been"
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_handle_funny_characters_in_instance_method_names
|
94
|
+
@chaser = TestChaser.new("Chased", "[]")
|
95
|
+
chased = Chased.new
|
96
|
+
assert_equal 2, chased[1], "Original doesn't work"
|
97
|
+
@chaser.modify_method
|
98
|
+
assert_equal 7, chased[1], "Modified doesn't work"
|
99
|
+
@chaser.unmodify_method
|
100
|
+
assert_equal 2, chased[1], "Modified then unmodified doesn't work"
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_handle_funny_characters_in_class_method_names
|
104
|
+
@chaser = TestChaser.new("Chased", "self.[]")
|
105
|
+
assert_equal 2, Chased[1], "Original doesn't work"
|
106
|
+
@chaser.modify_method
|
107
|
+
assert_equal 7, Chased[1], "Modified doesn't work"
|
108
|
+
@chaser.unmodify_method
|
109
|
+
assert_equal 2, Chased[1], "Modified then unmodified doesn't work"
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_more_funny_characters
|
113
|
+
assert_nothing_raised("Can't handle certain characters") do
|
114
|
+
@chaser = TestChaser.new("Chased", "question?")
|
115
|
+
chased = Chased.new
|
116
|
+
chased.question?
|
117
|
+
@chaser.modify_method
|
118
|
+
chased.question?
|
119
|
+
@chaser.unmodify_method
|
120
|
+
chased.question?
|
121
|
+
end
|
122
|
+
|
123
|
+
assert_nothing_raised("Can't handle equal signs") do
|
124
|
+
@chaser = TestChaser.new("Chased", "foo=")
|
125
|
+
chased = Chased.new
|
126
|
+
chased.foo= 1
|
127
|
+
@chaser.modify_method
|
128
|
+
chased.foo = 2
|
129
|
+
@chaser.unmodify_method
|
130
|
+
chased.foo = 3
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
class ZombieTestChaserCase < Test::Unit::TestCase
|
137
|
+
def test_detects_invalid_glob
|
138
|
+
incorrect_glob = 'test\test_chaser.rb'
|
139
|
+
ZombieTestChaser.test_pattern = incorrect_glob
|
140
|
+
assert_raise(RuntimeError, "Can't detect an incorrect glob") do
|
141
|
+
ZombieTestChaser.create_world
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/test/test_unit.rb
ADDED
data/test/test_zombie.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
$: << "lib"
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
require "world"
|
5
|
+
|
6
|
+
module TestHumanHelper
|
7
|
+
def assert_that_representations_include(expected_representation, human_results, failure_message)
|
8
|
+
world = create_world(human_results)
|
9
|
+
interface = world.interface
|
10
|
+
assert interface.representations.include?(expected_representation), failure_message + "Expected #{expected_representation}, got #{world.representations.inspect}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def assert_that_representations_include_these_representations(expected_representations, human_results, zombies_results, failure_message)
|
14
|
+
world = create_world(human_results, zombies_results)
|
15
|
+
interface = world.interface
|
16
|
+
expected_representations.each do |expected_representation|
|
17
|
+
assert interface.representations.include?(expected_representation), failure_message + ": Expected #{expected_representation}, got #{world.representations.inspect}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_world(human_results, zombies_results = [])
|
22
|
+
world = World.new_using_results(human_results, zombies_results)
|
23
|
+
world.run
|
24
|
+
world
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TestHuman < Test::Unit::TestCase
|
29
|
+
include TestHumanHelper
|
30
|
+
|
31
|
+
def test_human_single_success
|
32
|
+
human_results = [:pass]
|
33
|
+
failure_message = "Can't handle single success"
|
34
|
+
assert_that_representations_include(".@", human_results, failure_message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_human_single_failure
|
38
|
+
human_results = [:failure]
|
39
|
+
failure_message = "Can't handle single failure"
|
40
|
+
assert_that_representations_include("+", human_results, failure_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_human_two_successes
|
44
|
+
human_results = [:pass, :pass]
|
45
|
+
expected_representations = ["@", ".@", "..@"]
|
46
|
+
failure_message = "Needs to be able to do multiple steps"
|
47
|
+
#This'll run the simulation three times. Optimize if neccessary (it isn't yet)
|
48
|
+
expected_representations.each do |expected_representation|
|
49
|
+
assert_that_representations_include(expected_representation, human_results, failure_message)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_human_success_failure
|
54
|
+
human_results = [:pass, :failure]
|
55
|
+
expected_representation = ".+"
|
56
|
+
failure_message = "Can't handle success and failure"
|
57
|
+
assert_that_representations_include(expected_representation, human_results, failure_message)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_human_success_failure_success
|
61
|
+
human_results = [:pass, :failure, :pass]
|
62
|
+
expected_representation = ".+"
|
63
|
+
failure_message = "Can't handle success and failure"
|
64
|
+
assert_that_representations_include(expected_representation, human_results, failure_message)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_human_exploding
|
68
|
+
human_results = [:pass, :failure]
|
69
|
+
expected_representation = ".*"
|
70
|
+
failure_message = "Doesn't represent the human exploding"
|
71
|
+
assert_that_representations_include(expected_representation, human_results, failure_message)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class TestZombie < Test::Unit::TestCase
|
77
|
+
include TestHumanHelper
|
78
|
+
|
79
|
+
def test_human_surviving_zombie_slaying
|
80
|
+
human_results = [:pass, :pass]
|
81
|
+
zombies_results = [[:failure]]
|
82
|
+
expected_representations = ["..@", "*.@"]
|
83
|
+
failure_message = "Can't represent a zombie slaying."
|
84
|
+
assert_that_representations_include_these_representations(expected_representations, human_results, zombies_results, failure_message)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_human_surviving_zombie_slaying2
|
88
|
+
human_results = [:pass, :pass, :pass]
|
89
|
+
zombies_results = [[:pass, :failure]]
|
90
|
+
expected_representations = ["...@", "Z..@", ".*.@"]
|
91
|
+
failure_message = "Can't represent a zombie slaying."
|
92
|
+
assert_that_representations_include_these_representations(expected_representations, human_results, zombies_results, failure_message)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/ui/icons/death.png
ADDED
Binary file
|
data/ui/icons/robot.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|