rubyslim 0.1.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.
Files changed (38) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +16 -0
  4. data/README.md +187 -0
  5. data/Rakefile +21 -0
  6. data/bin/rubyslim +10 -0
  7. data/lib/rubyslim/list_deserializer.rb +67 -0
  8. data/lib/rubyslim/list_executor.rb +12 -0
  9. data/lib/rubyslim/list_serializer.rb +43 -0
  10. data/lib/rubyslim/ruby_slim.rb +61 -0
  11. data/lib/rubyslim/slim_error.rb +3 -0
  12. data/lib/rubyslim/slim_helper_library.rb +23 -0
  13. data/lib/rubyslim/socket_service.rb +53 -0
  14. data/lib/rubyslim/statement.rb +79 -0
  15. data/lib/rubyslim/statement_executor.rb +174 -0
  16. data/lib/rubyslim/table_to_hash_converter.rb +34 -0
  17. data/lib/test_module/library_new.rb +13 -0
  18. data/lib/test_module/library_old.rb +12 -0
  19. data/lib/test_module/should_not_find_test_slim_in_here/test_slim.rb +7 -0
  20. data/lib/test_module/simple_script.rb +9 -0
  21. data/lib/test_module/test_chain.rb +5 -0
  22. data/lib/test_module/test_slim.rb +86 -0
  23. data/lib/test_module/test_slim_with_arguments.rb +23 -0
  24. data/lib/test_module/test_slim_with_no_sut.rb +5 -0
  25. data/rubyslim.gemspec +21 -0
  26. data/spec/instance_creation_spec.rb +40 -0
  27. data/spec/it8f_spec.rb +9 -0
  28. data/spec/list_deserializer_spec.rb +67 -0
  29. data/spec/list_executor_spec.rb +187 -0
  30. data/spec/list_serialzer_spec.rb +39 -0
  31. data/spec/method_invocation_spec.rb +128 -0
  32. data/spec/slim_helper_library_spec.rb +80 -0
  33. data/spec/socket_service_spec.rb +98 -0
  34. data/spec/spec_helper.rb +2 -0
  35. data/spec/statement_executor_spec.rb +50 -0
  36. data/spec/statement_spec.rb +17 -0
  37. data/spec/table_to_hash_converter_spec.rb +32 -0
  38. metadata +100 -0
@@ -0,0 +1,23 @@
1
+ module TestModule
2
+ class TestSlimWithArguments
3
+ def initialize(arg)
4
+ @arg = arg
5
+ end
6
+
7
+ def arg
8
+ @arg
9
+ end
10
+
11
+ def name
12
+ @arg[:name]
13
+ end
14
+
15
+ def addr
16
+ @arg[:addr]
17
+ end
18
+
19
+ def set_arg(hash)
20
+ @arg = hash
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ module TestModule
2
+ class TestSlimWithNoSut
3
+
4
+ end
5
+ end
data/rubyslim.gemspec ADDED
@@ -0,0 +1,21 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.name = "rubyslim"
4
+ s.version = "0.1.1"
5
+ s.summary = "Ruby SliM protocol for FitNesse"
6
+ s.description = <<-EOS
7
+ RubySliM implements the SliM protocol for the FitNesse
8
+ acceptance testing framework.
9
+ EOS
10
+ s.authors = ["Robert C. Martin", "Doug Bradbury"]
11
+ s.email = "unclebob@cleancoder.com"
12
+ s.platform = Gem::Platform::RUBY
13
+
14
+ s.add_development_dependency 'rspec', '~> 1.3.0'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.require_path = 'lib'
18
+
19
+ s.executables = ['rubyslim']
20
+ end
21
+
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+ require "statement_executor"
3
+
4
+ describe StatementExecutor do
5
+ before do
6
+ @caller = StatementExecutor.new
7
+ end
8
+
9
+ it "can create an instance" do
10
+ response = @caller.create("x", "TestModule::TestSlim", [])
11
+ response.should == "OK"
12
+ x = @caller.instance("x")
13
+ x.class.name.should == "TestModule::TestSlim"
14
+ end
15
+
16
+ it "can create an instance with arguments" do
17
+ response = @caller.create("x", "TestModule::TestSlimWithArguments", ["3"])
18
+ response.should == "OK"
19
+ x = @caller.instance("x")
20
+ x.arg.should == "3"
21
+ end
22
+
23
+ it "can create an instance with arguments that are symbols" do
24
+ @caller.set_symbol("X", "3")
25
+ response = @caller.create("x", "TestModule::TestSlimWithArguments", ["$X"])
26
+ response.should == "OK"
27
+ x = @caller.instance("x")
28
+ x.arg.should == "3"
29
+ end
30
+
31
+ it "can't create an instance with the wrong number of arguments" do
32
+ result = @caller.create("x", "TestModule::TestSlim", ["1", "noSuchArgument"])
33
+ result.should include(Statement::EXCEPTION_TAG + "message:<<COULD_NOT_INVOKE_CONSTRUCTOR TestModule::TestSlim[2]>>")
34
+ end
35
+
36
+ it "can't create an instance if there is no class" do
37
+ result = @caller.create("x", "TestModule::NoSuchClass", [])
38
+ result.should include(Statement::EXCEPTION_TAG + "message:<<COULD_NOT_INVOKE_CONSTRUCTOR TestModule::NoSuchClass failed to find in []>>")
39
+ end
40
+ end
data/spec/it8f_spec.rb ADDED
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
3
+
4
+ describe "characters" do
5
+ it "should be able to deal with it8f chars" do
6
+ "Köln".should == "Köln"
7
+ "Köln".size.should == 4
8
+ end
9
+ end
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
3
+ require "list_serializer"
4
+ require "list_deserializer"
5
+
6
+ describe ListDeserializer do
7
+ before do
8
+ @list = []
9
+ end
10
+
11
+ it "can't deserialize a null string" do
12
+ proc {ListDeserializer.deserialize(nil)}.should raise_error(ListDeserializer::SyntaxError)
13
+ end
14
+
15
+ it "can't deserialize empty string" do
16
+ proc {ListDeserializer.deserialize("")}.should raise_error(ListDeserializer::SyntaxError)
17
+ end
18
+
19
+ it "can't deserialize string that doesn't start with an open bracket" do
20
+ proc {ListDeserializer.deserialize("hello")}.should raise_error(ListDeserializer::SyntaxError)
21
+ end
22
+
23
+ it "can't deserialize string that doesn't end with a bracket" do
24
+ proc {ListDeserializer.deserialize("[000000:")}.should raise_error(ListDeserializer::SyntaxError)
25
+ end
26
+
27
+ def check()
28
+ serialized = ListSerializer.serialize(@list)
29
+ deserialized = ListDeserializer.deserialize(serialized)
30
+ deserialized.should == @list
31
+ end
32
+
33
+ it "can deserialize and empty list" do
34
+ check
35
+ end
36
+
37
+ it "can deserialize a list with one element" do
38
+ @list = ["hello"]
39
+ check
40
+ end
41
+
42
+ it "can deserialize a list with two elements" do
43
+ @list = ["hello", "bob"]
44
+ check
45
+ end
46
+
47
+ it "can deserialize sublists" do
48
+ @list = ["hello", ["bob", "micah"], "today"]
49
+ check
50
+ end
51
+
52
+ it "can deserialize lists with multibyte strings" do
53
+ @list = ["Köln"]
54
+ check
55
+ end
56
+
57
+ it "can deserialize lists of strings that end with multibyte chars" do
58
+ @list = ["Kö"]
59
+ check
60
+ end
61
+
62
+ it "can deserialize lists with utf8" do
63
+ @list = ["123456789012345", "Espa\357\277\275ol"]
64
+ check
65
+ end
66
+
67
+ end
@@ -0,0 +1,187 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+ require "statement_executor"
3
+ require "list_executor"
4
+
5
+ describe ListExecutor do
6
+ before do
7
+ @executor = ListExecutor.new
8
+ @statements = []
9
+ @table = "<table><tr><td>name</td><td>bob</td></tr><tr><td>addr</td><td>here</td></tr></table>"
10
+ add_statement "i1", "import", "TestModule"
11
+ add_statement "m1", "make", "test_slim", "TestSlim"
12
+ end
13
+
14
+ def get_result(id, result_list)
15
+ pairs_to_map(result_list)[id]
16
+ end
17
+
18
+ def pairs_to_map(pairs)
19
+ map = {}
20
+ pairs.each {|pair| map[pair[0]] = pair[1]}
21
+ map
22
+ end
23
+
24
+ def add_statement(*args)
25
+ @statements << args
26
+ end
27
+
28
+ def check_results expectations
29
+ results = @executor.execute(@statements)
30
+ expectations.each_pair {|id, expected|
31
+ get_result(id, results).should == expected
32
+ }
33
+ end
34
+
35
+ it "can respond with OK to import" do
36
+ check_results "i1"=>"OK"
37
+ end
38
+
39
+ it "can't execute an invalid operation" do
40
+ add_statement "inv1", "invalidOperation"
41
+ results = @executor.execute(@statements)
42
+ get_result("inv1", results).should include(Statement::EXCEPTION_TAG+"message:<<INVALID_STATEMENT: [\"inv1\", \"invalidOperation\"].")
43
+ end
44
+
45
+ it "can't execute a malformed instruction" do
46
+ add_statement "id", "call", "notEnoughArguments"
47
+ message = "message:<<MALFORMED_INSTRUCTION [\"id\", \"call\", \"notEnoughArguments\"].>>"
48
+ results = @executor.execute(@statements)
49
+ get_result("id", results).should include(Statement::EXCEPTION_TAG+message)
50
+ end
51
+
52
+ it "can't call a method on an instance that doesn't exist" do
53
+ add_statement "id", "call", "no_such_instance", "no_such_method"
54
+ results = @executor.execute(@statements)
55
+ get_result("id", results).should include(Statement::EXCEPTION_TAG+"message:<<NO_INSTANCE no_such_instance>>")
56
+ end
57
+
58
+ it "should respond to an empty set of instructions with an empty set of results" do
59
+ @executor.execute([]).length.should == 0
60
+ end
61
+
62
+ it "can make an instance given a fully qualified name in dot format" do
63
+ @executor.execute([["m1", "make", "instance", "testModule.TestSlim"]]).should == [["m1", "OK"]]
64
+ end
65
+
66
+ it "can call a simple method in ruby form" do
67
+ add_statement "id", "call", "test_slim", "return_string"
68
+
69
+ check_results "m1" => "OK", "id"=>"string"
70
+ end
71
+
72
+ it "can call a simple method in ruby form" do
73
+ add_statement "id", "call", "test_slim", "utf8"
74
+
75
+ check_results "m1" => "OK", "id"=>"Espa\357\277\275ol"
76
+ end
77
+
78
+
79
+ it "can call a simple method in FitNesse form" do
80
+ add_statement "id", "call", "test_slim", "returnString"
81
+
82
+ check_results "m1"=>"OK", "id"=>"string"
83
+ end
84
+
85
+ it "will allow later imports to take precendence over early imports" do
86
+ @statements.insert(0, ["i2", "import", "TestModule.ShouldNotFindTestSlimInHere"])
87
+ add_statement "id", "call", "test_slim", "return_string"
88
+ check_results "m1"=>"OK", "id"=>"string"
89
+ end
90
+
91
+ it "can pass arguments to constructor" do
92
+ add_statement "m2", "make", "test_slim_2", "TestSlimWithArguments", "3"
93
+ add_statement "c1", "call", "test_slim_2", "arg"
94
+
95
+ check_results "m2"=>"OK", "c1"=>"3"
96
+ end
97
+
98
+ it "can pass tables to constructor" do
99
+ add_statement "m2", "make", "test_slim_2", "TestSlimWithArguments", @table
100
+ add_statement "c1", "call", "test_slim_2", "name"
101
+ add_statement "c2", "call", "test_slim_2", "addr"
102
+
103
+ check_results "m2"=>"OK", "c1"=>"bob", "c2"=>"here"
104
+ end
105
+
106
+ it "can pass tables to functions" do
107
+ add_statement "m2", "make", "test_slim_2", "TestSlimWithArguments", "nil"
108
+ add_statement "c0", "call", "test_slim_2", "set_arg", @table
109
+ add_statement "c1", "call", "test_slim_2", "name"
110
+ add_statement "c2", "call", "test_slim_2", "addr"
111
+
112
+ check_results "m2"=>"OK", "c1"=>"bob", "c2"=>"here"
113
+ end
114
+
115
+ it "can call a function more than once" do
116
+ add_statement "c1", "call", "test_slim", "add", "x", "y"
117
+ add_statement "c2", "call", "test_slim", "add", "a", "b"
118
+
119
+ check_results "c1" => "xy", "c2" => "ab"
120
+ end
121
+
122
+ it "can assign the return value to a symbol" do
123
+ add_statement "id1", "callAndAssign", "v", "test_slim", "add", "x", "y"
124
+ add_statement "id2", "call", "test_slim", "echo", "$v"
125
+ check_results "id1" => "xy", "id2" => "xy"
126
+ end
127
+
128
+ it "can replace multiple symbols in a single argument" do
129
+ add_statement "id1", "callAndAssign", "v1", "test_slim", "echo", "Bob"
130
+ add_statement "id2", "callAndAssign", "v2", "test_slim", "echo", "Martin"
131
+ add_statement "id3", "call", "test_slim", "echo", "name: $v1 $v2"
132
+ check_results "id3" => "name: Bob Martin"
133
+ end
134
+
135
+ it "should ignore '$' if what follows is not a symbol" do
136
+ add_statement "id3", "call", "test_slim", "echo", "$v1"
137
+ check_results "id3" => "$v1"
138
+ end
139
+
140
+ it "can pass and return a list" do
141
+ l = ["1", "2"]
142
+ add_statement "id", "call", "test_slim", "echo", l
143
+ check_results "id"=> l
144
+ end
145
+
146
+ it "can pass a symbol in a list" do
147
+ add_statement "id1", "callAndAssign", "v", "test_slim", "echo", "x"
148
+ add_statement "id2", "call", "test_slim", "echo", ["$v"]
149
+ check_results "id2" => ["x"]
150
+ end
151
+
152
+ it "can return null" do
153
+ add_statement "id", "call", "test_slim", "null"
154
+ check_results "id" => nil
155
+ end
156
+
157
+ it "can survive executing a syntax error" do
158
+ add_statement "id", "call", "test_slim", "syntax_error"
159
+ results = @executor.execute(@statements)
160
+ get_result("id", results).should include(Statement::EXCEPTION_TAG)
161
+ end
162
+
163
+ it "can make a fixture from the name in a symbol" do
164
+ add_statement "id1", "callAndAssign", "test_system", "test_slim", "echo", "TestChain"
165
+ add_statement "id2", "make", "fixture_instance1", "$test_system"
166
+ check_results "id2"=>"OK"
167
+ end
168
+
169
+ it "can make a fixture from a concatonated symbol" do
170
+ add_statement "id1", "callAndAssign", "test_system", "test_slim", "echo", "Chain"
171
+ add_statement "id2", "make", "fixture_instance1", "Test$test_system"
172
+ check_results "id2"=>"OK"
173
+ end
174
+
175
+ it "can use a fixture method that returns a fixture object" do
176
+ add_statement "id1", "callAndAssign", "object", "test_slim", "echo_object", "let_me_see", "Boogaloo"
177
+ add_statement "id2", "call", "test_slim", "call_on", "let_me_see", "$object"
178
+ check_results "id2" => "Boogaloo"
179
+ end
180
+
181
+ it "can use an instance that was stored as a symbol" do
182
+ add_statement "id1", "callAndAssign", "test_slim_instance", "test_slim", "create_test_slim_with_string", "Boogaloo"
183
+ add_statement "m2", "make", "test_slim", "$test_slim_instance"
184
+ check_results "m2" => "OK"
185
+ end
186
+
187
+ end
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
3
+ require "list_serializer"
4
+
5
+ describe ListSerializer do
6
+ it "can serialize and empty list" do
7
+ ListSerializer.serialize([]).should == "[000000:]"
8
+ end
9
+
10
+ it "can serialize a one item list" do
11
+ ListSerializer.serialize(["hello"]).should == "[000001:000005:hello:]"
12
+ end
13
+
14
+ it "can serialize a two item list" do
15
+ ListSerializer.serialize(["hello", "world"]).should == "[000002:000005:hello:000005:world:]"
16
+ end
17
+
18
+ it "can serialize a nested list" do
19
+ ListSerializer.serialize([["element"]]).should == "[000001:000024:[000001:000007:element:]:]"
20
+ end
21
+
22
+ it "can serialize a list with a non-string" do
23
+ ListSerializer.serialize([1]).should == "[000001:000001:1:]"
24
+ end
25
+
26
+ it "can serialize a null element" do
27
+ ListSerializer.serialize([nil]).should == "[000001:000004:null:]"
28
+ end
29
+
30
+ it "can serialize a string with multibyte chars" do
31
+ ListSerializer.serialize(["Köln"]).should == "[000001:000004:Köln:]"
32
+ end
33
+
34
+ it "can serialize a string with UTF8" do
35
+ ListSerializer.serialize(["Español"]).should == "[000001:000007:Espa\xc3\xb1ol:]"
36
+ end
37
+
38
+
39
+ end
@@ -0,0 +1,128 @@
1
+ # coding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
3
+ require "statement_executor"
4
+
5
+ describe StatementExecutor do
6
+ before do
7
+ @executor = StatementExecutor.new
8
+ end
9
+ context "Simple Method Invocations" do
10
+ before do
11
+ @executor.create("test_slim", "TestModule::TestSlim", [])
12
+ @test_slim = @executor.instance("test_slim")
13
+ end
14
+
15
+ it "can call a method with no arguments" do
16
+ @test_slim.should_receive(:no_args).with()
17
+ @executor.call("test_slim", "no_args")
18
+ end
19
+
20
+ it "can't call a method that doesn't exist" do
21
+ result = @executor.call("test_slim", "no_such_method")
22
+ result.should include(Statement::EXCEPTION_TAG + "message:<<NO_METHOD_IN_CLASS no_such_method[0] TestModule::TestSlim.>>")
23
+ end
24
+
25
+ it "can call a method that returns a value" do
26
+ @test_slim.should_receive(:return_value).and_return("arg")
27
+ @executor.call("test_slim", "return_value").should == "arg"
28
+ end
29
+
30
+ it "can call a method that returns a value" do
31
+ @test_slim.should_receive(:return_value).and_return("Español")
32
+ val = @executor.call("test_slim", "return_value")
33
+ val.should == "Español"
34
+ val.length.should == 7
35
+ end
36
+
37
+
38
+ it "can call a method that takes an argument" do
39
+ @test_slim.should_receive(:one_arg).with("arg")
40
+ @executor.call("test_slim", "one_arg", "arg")
41
+ end
42
+
43
+ it "can't call a method on an instance that doesn't exist" do
44
+ result = @executor.call("no_such_instance", "no_such_method")
45
+ result.should include(Statement::EXCEPTION_TAG + "message:<<NO_INSTANCE no_such_instance>>")
46
+ end
47
+
48
+ it "can replace symbol expressions with their values" do
49
+ @executor.set_symbol("v", "bob")
50
+ @executor.call("test_slim", "echo", "hi $v.").should == "hi bob."
51
+ end
52
+
53
+ it "can call a method on the @sut" do
54
+ @test_slim.sut.should_receive(:sut_method).with()
55
+ @executor.call("test_slim", "sut_method")
56
+ end
57
+
58
+ it "should call attributes on sut" do
59
+ @executor.call("test_slim", "set_attribute", "a")
60
+ @executor.call("test_slim", "attribute").should == "a"
61
+ end
62
+ end
63
+
64
+ context "Method invocations using fixture with no sut" do
65
+ before do
66
+ @executor.create("test_slim", "TestModule::TestSlimWithNoSut", []);
67
+ @test_slim = @executor.instance("test_slim")
68
+ end
69
+
70
+ it "can't call method that doesn't exist if no 'sut' exists" do
71
+ result = @executor.call("test_slim", "no_such_method")
72
+ result.should include(Statement::EXCEPTION_TAG + "message:<<NO_METHOD_IN_CLASS no_such_method[0] TestModule::TestSlimWithNoSut.>>")
73
+ end
74
+ end
75
+
76
+ context "Method invocations when library instances have been created." do
77
+ before do
78
+ @executor.create("library_old", "TestModule::LibraryOld", [])
79
+ @executor.create("library_new", "TestModule::LibraryNew", [])
80
+ @library_old = @executor.instance("library_old")
81
+ @library_new = @executor.instance("library_new")
82
+ @executor.create("test_slim", "TestModule::TestSlim", [])
83
+ @test_slim = @executor.instance("test_slim")
84
+ end
85
+
86
+ it "should throw normal exception if no such method is found." do
87
+ result = @executor.call("test_slim", "no_such_method")
88
+ result.should include(Statement::EXCEPTION_TAG + "message:<<NO_METHOD_IN_CLASS no_such_method[0] TestModule::TestSlim.>>")
89
+ end
90
+
91
+ it "should still call normal methods in fixture" do
92
+ @test_slim.should_receive(:no_args).with()
93
+ @executor.call("test_slim", "no_args")
94
+ end
95
+
96
+ it "should still call methods on the sut" do
97
+ @test_slim.sut.should_receive(:sut_method).with()
98
+ @executor.call("test_slim", "sut_method")
99
+ end
100
+
101
+ it "should call a specific method on library_old" do
102
+ @library_old.should_receive(:method_on_library_old).with()
103
+ @executor.call("test_slim", "method_on_library_old")
104
+ end
105
+
106
+ it "should call a specific method on library_new" do
107
+ @library_new.should_receive(:method_on_library_new).with()
108
+ @executor.call("test_slim", "method_on_library_new")
109
+ end
110
+
111
+ it "should call method on library_new but not on library_old" do
112
+ @library_new.should_receive(:a_method).with()
113
+ @library_old.should_not_receive(:a_method).with()
114
+ @executor.call("test_slim", "a_method")
115
+ end
116
+
117
+ it "should call built-in library methods" do
118
+ @executor.call("test_slim", "push_fixture").should == nil
119
+ @executor.call("test_slim", "pop_fixture").should == nil
120
+ end
121
+
122
+ it "should translate getters and setters" do
123
+ @executor.call("test_slim", "set_lib_attribute", "lemon")
124
+ @executor.call("test_slim", "lib_attribute").should == "lemon"
125
+ end
126
+
127
+ end
128
+ end