butterfly_net 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  require 'butterfly_net/file_writer'
2
+ require 'butterfly_net/definitions'
2
3
  require 'butterfly_net/test_unit_method'
3
4
  require 'butterfly_net/test_unit_adapter'
4
5
  require 'butterfly_net/rails_test_unit_adapter'
@@ -11,9 +11,9 @@ module ButterflyNet
11
11
  module Commands
12
12
 
13
13
  def bn_open(file_name=nil)
14
- @file_writer.close if @file_writer
15
- @file_writer = ReadlineReader.new(file_name)
16
- Kernel.at_exit { puts @file_writer.close if @file_writer; @file_writer = nil }
14
+ @readline_reader.close if @readline_reader
15
+ @readline_reader = ReadlineReader.new(file_name)
16
+ Kernel.at_exit { puts @readline_reader.close if @readline_reader; @readline_reader = nil }
17
17
  true
18
18
  rescue Exception => e
19
19
  puts e
@@ -22,9 +22,9 @@ module ButterflyNet
22
22
  end
23
23
 
24
24
  def bn_close
25
- if @file_writer
26
- status = @file_writer.close
27
- @file_writer = nil
25
+ if @readline_reader
26
+ status = @readline_reader.close
27
+ @readline_reader = nil
28
28
  status
29
29
  else
30
30
  puts "butterfly_net: First invoke 'bn' or 'bn_open' to begin a session"
@@ -33,8 +33,8 @@ module ButterflyNet
33
33
  end
34
34
 
35
35
  def bn_method(method_name=nil)
36
- if @file_writer
37
- @file_writer.new_assertion_set(method_name)
36
+ if @readline_reader
37
+ @readline_reader.new_assertion_set(method_name)
38
38
  else
39
39
  puts "butterfly_net: First invoke 'bn' or 'bn_open' to begin a session"
40
40
  false
@@ -0,0 +1,44 @@
1
+ module ButterflyNet
2
+ class Definitions
3
+
4
+ attr_reader :lines
5
+
6
+ def initialize
7
+ @nesting_level = 0
8
+ @lines = []
9
+ end
10
+
11
+ def empty?
12
+ @lines.empty?
13
+ end
14
+
15
+ def self.start_def?(line) # todo: extract to line class
16
+ line =~ /^\s*def\s+|^\s*class\s+|^\s*module\s+/
17
+ end
18
+
19
+ def self.end_def?(line) # todo: extract to line class
20
+ line =~ /end\s*$/
21
+ end
22
+
23
+ def <<(line)
24
+ if Definitions.start_def?(line) and Definitions.end_def?(line)
25
+ @lines << " #{(" " * @nesting_level)}#{line}\n\n"
26
+ elsif Definitions.start_def?(line)
27
+ @nesting_level += 1
28
+ @lines << "#{(" " * @nesting_level)}#{line}\n"
29
+ elsif Definitions.end_def?(line)
30
+ @nesting_level -= 1
31
+ @lines << " #{(" " * @nesting_level)}#{line}\n#{ @nesting_level == 0 ? "\n" : ""}"
32
+ elsif @nesting_level > 0
33
+ @lines << " #{(" " * @nesting_level)}#{line}\n" unless @nesting_level == 0
34
+ else
35
+ false
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ @lines.join
41
+ end
42
+
43
+ end
44
+ end
@@ -2,14 +2,27 @@ module ButterflyNet
2
2
  class TestUnitMethod
3
3
 
4
4
  attr_accessor :name
5
+ attr_reader :definitions, :lines
5
6
 
6
7
  def initialize
7
- @commands = []
8
- @definitions = []
8
+ @commands = [] # todo: merge these 2 arrays in to single array of 2element pairs
9
+ @lines = []
10
+ @definitions = Definitions.new
9
11
  end
10
12
 
11
13
  def <<(line)
12
- @commands << line
14
+ unless @definitions << line
15
+ begin
16
+ code = @definitions.to_s + @commands.join("\n") + "\n" + line
17
+ retval = eval code
18
+ @commands << line # todo replace def handling below with definitions (work in progress)
19
+ @lines << final_line_string(line, retval)
20
+ rescue Exception
21
+ @commands << "# #{line} # butterfly_net: Could not evaluate."
22
+ @lines << " # #{line} # butterfly_net: Could not evaluate."
23
+ end
24
+ end
25
+ self
13
26
  end
14
27
 
15
28
  def empty?
@@ -25,57 +38,12 @@ module ButterflyNet
25
38
  line =~ /require\s*['|"]\w+['|"]|[^=<>!*%\/+-\\|&]=[^=~]/
26
39
  end
27
40
 
28
- def self.start_def?(line) # todo: extract to line class
29
- line =~ /^\s*def\s+|^\s*class\s+|^\s*module\s+/
30
- end
31
-
32
- def self.end_def?(line) # todo: extract to line class
33
- line =~ /end\s*$/
34
- end
35
-
36
41
  def text
37
- purge_bad_commands
38
- before_test_method = ""
39
- lines_string = ""
40
- nesting_level = 0
41
- @commands.each_with_index do |current_line, i|
42
- if TestUnitMethod.start_def?(current_line) and TestUnitMethod.end_def?(current_line)
43
- before_test_method += " #{(" " * nesting_level)}#{current_line}\n\n"
44
- elsif TestUnitMethod.start_def?(current_line)
45
- nesting_level += 1
46
- before_test_method += "#{(" " * nesting_level)}#{current_line}\n"
47
- elsif TestUnitMethod.end_def?(current_line)
48
- nesting_level -= 1
49
- before_test_method += " #{(" " * nesting_level)}#{current_line}\n#{ nesting_level == 0 ? "\n" : ""}"
50
- elsif nesting_level == 0
51
- text = assertion(i)
52
- lines_string += " #{text}\n" if text
53
- else
54
- before_test_method += " #{(" " * nesting_level)}#{current_line}\n"
55
- end
56
- end
57
- before_test_method += " "
58
- lines_string.empty? ? nil : "#{before_test_method}def #{@name}\n#{lines_string} end\n\n"
42
+ lines_string = @lines.inject("") {|result, e| result += " #{e}\n" if e; result}
43
+ lines_string.empty? ? nil : "#{@definitions.to_s} def #{@name}\n#{lines_string} end\n\n"
59
44
  end
60
45
 
61
- def assertion(current_i)
62
-
63
- current_line = @commands[current_i]
64
- commands = current_line
65
- start_i = current_i
66
-
67
- begin
68
- retval = eval commands
69
- rescue Exception
70
- start_i -= 1
71
- commands = @commands[start_i..current_i].join("\n")
72
-
73
- if start_i < 0
74
- return nil # give up, can't go further back
75
- else
76
- retry
77
- end
78
- end
46
+ def final_line_string(current_line, retval)
79
47
  if TestUnitMethod.assignment_or_require?(current_line)
80
48
  current_line
81
49
  elsif instances_equal_by_value?(retval) # expression result supports value equality
@@ -87,13 +55,10 @@ module ButterflyNet
87
55
  else
88
56
  "assert_equal(#{retval.inspect}, #{current_line})"
89
57
  end
90
-
91
58
  else
92
-
93
59
  # any other sort of object is handled as a not equal assertion
94
- "assert_not_equal((#{current_line}), #{current_line})" # todo assert_not_nil in some cases?
60
+ "assert_not_nil(#{current_line})" # todo assert_not_nil in some cases?
95
61
  end
96
-
97
62
  end
98
63
 
99
64
  def instances_equal_by_value?(instance)
@@ -102,40 +67,6 @@ module ButterflyNet
102
67
 
103
68
  private
104
69
 
105
- # def extract_definitions # work in progress, todo: handle definitions separately, place at top of file
106
- # @commands.each_with_index do |current_line, i|
107
- # if TestUnitMethod.start_def?(current_line) or TestUnitMethod.end_def?(current_line)
108
- # @definitions << current_line
109
- # end
110
- # end
111
- # end
112
-
113
- def purge_bad_commands
114
- begin
115
- commands = ""
116
- index = 0
117
- nesting_level = 0
118
- @commands.each_with_index do |current_line, i|
119
- index = i
120
- commands += current_line + "\n"
121
- if TestUnitMethod.start_def?(current_line) and TestUnitMethod.end_def?(current_line)
122
- #let it ride
123
- elsif TestUnitMethod.start_def?(current_line)
124
- nesting_level += 1
125
- elsif TestUnitMethod.end_def?(current_line)
126
- nesting_level -= 1
127
- elsif nesting_level == 0
128
- eval commands #todo write tests breaking assumption that definitions are valid code, and impl separate eval's for definitions
129
- end
130
- end
131
- nil
132
- rescue Exception
133
- # delete offender and start again from the beginning
134
- @commands.delete_at index # todo: test if string equality is safe for delete()
135
- retry
136
- end
137
- end
138
-
139
70
  # Adapted from ActiveSupport Inflector
140
71
  def underscore(name)
141
72
  name.to_s.strip.
@@ -146,7 +77,5 @@ module ButterflyNet
146
77
  downcase
147
78
  end
148
79
 
149
-
150
-
151
80
  end
152
81
  end
@@ -1,5 +1,6 @@
1
1
  require "test/unit"
2
2
  $: << File.expand_path(File.dirname(__FILE__))
3
3
  $: << File.join(File.expand_path(File.dirname(__FILE__)), File.join("..", "lib"))
4
+ require "definitions_test"
4
5
  require "test_unit_method_test"
5
6
  require "test_case_test"
@@ -0,0 +1,77 @@
1
+ require "test/unit"
2
+ $: << File.expand_path(File.dirname(__FILE__))
3
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), File.join("..", "lib"))
4
+ require "butterfly_net/definitions"
5
+
6
+ class DefinitionsTest < Test::Unit::TestCase
7
+ include ButterflyNet
8
+
9
+ def setup
10
+ @definitions = Definitions.new
11
+ end
12
+
13
+
14
+ def test_method_def_true_whitespace
15
+ assert Definitions.start_def?(" def timestwo(i); i * 2; end ")
16
+ end
17
+
18
+ def test_class_def_true_whitespace
19
+ assert Definitions.start_def?(" class MyClass; end ")
20
+ end
21
+
22
+ def test_class_def_true_whitespace
23
+ assert Definitions.start_def?(" module MyModule; end ")
24
+ end
25
+
26
+ def test_method_def_false_variable
27
+ assert !Definitions.start_def?("definite == true ")
28
+ end
29
+
30
+
31
+ def test_start_def_true_inline
32
+ assert Definitions.start_def?(" def timestwo(i); i * 2; end ")
33
+ end
34
+
35
+ def test_end_def_true_inline
36
+ assert Definitions.end_def?(" def timestwo(i); i * 2; end ")
37
+ end
38
+
39
+ def test_end_def_true_whitespace
40
+ assert Definitions.end_def?(" end ")
41
+ end
42
+
43
+ def test_definitions_inline
44
+ line = "def timestwo(i); i * 2; end"
45
+ @definitions << line
46
+ assert @definitions.lines.include?(" def timestwo(i); i * 2; end\n\n")
47
+ end
48
+
49
+ def test_definitions_class_empty
50
+ line = "class MyClass"
51
+ line2 = "end"
52
+ @definitions << line
53
+ @definitions << line2
54
+ assert_equal([" class MyClass\n", " end\n\n"], @definitions.lines)
55
+ end
56
+
57
+ def test_to_s_method_inline
58
+ @definitions << "def timestwo(i); i * 2; end"
59
+ assert_equal(" def timestwo(i); i * 2; end\n\n", @definitions.to_s)
60
+ end
61
+
62
+ def test_to_s_class_with_method
63
+ @definitions << "class MyClass"
64
+ @definitions << "def name"
65
+ @definitions << "\"classy\""
66
+ @definitions << "end"
67
+ @definitions << "end"
68
+ assert_equal " class MyClass\n def name\n \"classy\"\n end\n end\n\n", @definitions.to_s
69
+ end
70
+
71
+ # todo write tests breaking assumption that definitions are valid code, and impl separate eval's for definitions
72
+ # def test_text_bad_input_constant
73
+ # @definitions << "BADCONSTANT"
74
+ # assert_equal " # BADCONSTANT # NameError: uninitialized constant BADCONSTANT", @definitions.to_s
75
+ # end
76
+
77
+ end
@@ -2,6 +2,7 @@ require "test/unit"
2
2
  $: << File.expand_path(File.dirname(__FILE__))
3
3
  $: << File.join(File.expand_path(File.dirname(__FILE__)), File.join("..", "lib"))
4
4
  require "butterfly_net/file_writer"
5
+ require "butterfly_net/definitions"
5
6
  require "butterfly_net/test_unit_method"
6
7
  require "butterfly_net/test_unit_adapter"
7
8
  require "butterfly_net/rails_test_unit_adapter"
@@ -105,7 +106,7 @@ class TestCaseTest < Test::Unit::TestCase
105
106
  def test_test_methods_bad_input
106
107
  @adapter.add_command("BADCOMMAND")
107
108
  @adapter.close_assertion_set
108
- assert_nil @adapter.test_methods.first
109
+ assert_equal " def test_1\n # BADCOMMAND # butterfly_net: Could not evaluate.\n end\n\n", @adapter.test_methods.first
109
110
  end
110
111
 
111
112
  def test_create_file
@@ -1,6 +1,7 @@
1
1
  require "test/unit"
2
2
  $: << File.expand_path(File.dirname(__FILE__))
3
3
  $: << File.join(File.expand_path(File.dirname(__FILE__)), File.join("..", "lib"))
4
+ require "butterfly_net/definitions"
4
5
  require "butterfly_net/test_unit_method"
5
6
 
6
7
  class TestUnitMethodTest < Test::Unit::TestCase
@@ -111,35 +112,6 @@ class TestUnitMethodTest < Test::Unit::TestCase
111
112
  assert !TestUnitMethod.assignment_or_require?("a *= 1")
112
113
  end
113
114
 
114
- def test_method_def_true_whitespace
115
- assert TestUnitMethod.start_def?(" def timestwo(i); i * 2; end ")
116
- end
117
-
118
- def test_class_def_true_whitespace
119
- assert TestUnitMethod.start_def?(" class MyClass; end ")
120
- end
121
-
122
- def test_class_def_true_whitespace
123
- assert TestUnitMethod.start_def?(" module MyModule; end ")
124
- end
125
-
126
- def test_method_def_false_variable
127
- assert !TestUnitMethod.start_def?("definite == true ")
128
- end
129
-
130
-
131
- def test_start_def_true_inline
132
- assert TestUnitMethod.start_def?(" def timestwo(i); i * 2; end ")
133
- end
134
-
135
- def test_end_def_true_inline
136
- assert TestUnitMethod.end_def?(" def timestwo(i); i * 2; end ")
137
- end
138
-
139
- def test_end_def_true_whitespace
140
- assert TestUnitMethod.end_def?(" end ")
141
- end
142
-
143
115
  def test_name_uppercase
144
116
  @method.name = "MYMETHOD"
145
117
  assert_equal("test_mymethod", @method.name)
@@ -172,7 +144,7 @@ class TestUnitMethodTest < Test::Unit::TestCase
172
144
 
173
145
 
174
146
 
175
- # def test_text_split_statements_into_lines todo
147
+ # def test_text_split_expressions_into_lines todo
176
148
  # @method << "a = 1; a + 1"
177
149
  # assert_equal "def test_1\n a = 1\n assert_equal(2, a + 1)\n end", @method.text
178
150
  # end
@@ -181,14 +153,14 @@ class TestUnitMethodTest < Test::Unit::TestCase
181
153
  @method << "a = 1"
182
154
  @method << "2b" # syntax error, unexpected tIDENTIFIER, expecting $end
183
155
  @method << "a += 1"
184
- assert_equal " def test_1\n a = 1\n assert_equal(2, a += 1)\n end\n\n", @method.text
156
+ assert_equal " def test_1\n a = 1\n # 2b # butterfly_net: Could not evaluate.\n assert_equal(2, a += 1)\n end\n\n", @method.text
185
157
  end
186
158
 
187
159
  def test_purge_unexpected_identifiers
188
160
  @method << "a += 1" # undefined method `+' for nil:NilClass
189
161
  @method << "a = 1"
190
162
  @method << "a += 1"
191
- assert_equal " def test_1\n a = 1\n assert_equal(2, a += 1)\n end\n\n", @method.text
163
+ assert_equal " def test_1\n # a += 1 # butterfly_net: Could not evaluate.\n a = 1\n assert_equal(2, a += 1)\n end\n\n", @method.text
192
164
  end
193
165
 
194
166
  def test_text_require
@@ -201,68 +173,68 @@ class TestUnitMethodTest < Test::Unit::TestCase
201
173
  def test_expected_boolean
202
174
  line = "1 == 1"
203
175
  @method << line
204
- assert_equal("assert(#{line})", @method.assertion(0))
176
+ assert_equal("assert(#{line})", @method.lines[0])
205
177
  end
206
178
 
207
179
  def test_assertion_fixnum
208
180
  line = "1"
209
181
  @method << line
210
- assert_equal("assert_equal(#{line}, #{line})", @method.assertion(0))
182
+ assert_equal("assert_equal(#{line}, #{line})", @method.lines[0])
211
183
  end
212
184
 
213
185
  def test_assertion_boolean_false
214
186
  line = "1 != 1"
215
187
  @method << line
216
- assert_equal("assert_equal(false, #{line})", @method.assertion(0))
188
+ assert_equal("assert_equal(false, #{line})", @method.lines[0])
217
189
  end
218
190
 
219
191
  def test_array_add
220
192
  @method << "a = []"
221
193
  line2 = "a << \"1\""
222
194
  @method << line2
223
- assert_equal("assert_equal([\"1\"], #{line2})", @method.assertion(1))
195
+ assert_equal("assert_equal([\"1\"], #{line2})", @method.lines[1])
224
196
  end
225
197
 
226
198
  def test_butterfly_net
227
199
  @method << "method = TestUnitMethod.new"
228
200
  @method << "method << \"1 + 1\""
229
- assert_equal("assert_equal([\"1 + 1\"], method << \"1 + 1\")", @method.assertion(1))
201
+ assert_equal("assert_not_nil(method << \"1 + 1\")", @method.lines[1])
230
202
  end
231
203
 
232
204
  def test_assertion_boolean
233
205
  line = "1 == 1"
234
206
  @method << line
235
- assert_equal("assert(#{line})", @method.assertion(0))
207
+ assert_equal("assert(#{line})", @method.lines[0])
236
208
  end
237
209
 
238
210
  def test_assertion_string
239
211
  line = "'a' + 'b'"
240
212
  @method << line
241
- assert_equal("assert_equal(\"ab\", #{line})", @method.assertion(0))
213
+ assert_equal("assert_equal(\"ab\", #{line})", @method.lines[0])
242
214
  end
243
215
 
244
216
  def test_assertion_nil
245
217
  line = "[].first"
246
218
  @method << line
247
- assert_equal("assert_nil(#{line})", @method.assertion(0))
219
+ assert_equal("assert_nil(#{line})", @method.lines[0])
248
220
  end
249
221
 
250
222
  def test_assertion_boolean
251
223
  line = "1 == 1"
252
224
  @method << line
253
- assert_equal("assert(#{line})", @method.assertion(0))
225
+ assert_equal("assert(#{line})", @method.lines[0])
254
226
  end
255
227
 
256
228
  def test_assertion_object_not_equal
257
229
  line = "Object.new"
258
230
  @method << line
259
- assert_equal("assert_not_equal((#{line}), #{line})", @method.assertion(0))
231
+ assert_equal("assert_not_nil(#{line})", @method.lines[0])
260
232
  end
261
233
 
262
234
  def test_assertion_array
263
235
  line = "([1,2,3])[0..0]"
264
236
  @method << line
265
- assert_equal("assert_equal([1], #{line})", @method.assertion(0))
237
+ assert_equal("assert_equal([1], #{line})", @method.lines[0])
266
238
  end
267
239
 
268
240
  def test_text_def_method_single_line
@@ -272,10 +244,10 @@ class TestUnitMethodTest < Test::Unit::TestCase
272
244
  assert_equal(" def timestwo(i); i * 2; end\n\n def test_1\n assert_equal(4, #{line})\n end\n\n", @method.text)
273
245
  end
274
246
 
275
- def test_assertion_illegal_input
247
+ def test_text_illegal_input
276
248
  line = "badtext"
277
249
  @method << line
278
- assert_nil @method.assertion(0)
250
+ assert_equal " def test_1\n # badtext # butterfly_net: Could not evaluate.\n end\n\n", @method.text
279
251
  end
280
252
 
281
253
  def test_text
@@ -289,17 +261,17 @@ class TestUnitMethodTest < Test::Unit::TestCase
289
261
  assert_equal " def test_1\n #{line}\n end\n\n", @method.text
290
262
  end
291
263
 
292
- def test_extract_definitions_class_multiline_empty
264
+ def test_definitions_class_multiline_empty
293
265
  line = "class MyClass"
294
266
  line2 = "end"
295
267
  line3 = "MyClass.new"
296
268
  @method << line
297
269
  @method << line2
298
270
  @method << line3
299
- assert_equal " #{line}\n #{line2}\n\n def test_1\n assert_not_equal((#{line3}), #{line3})\n end\n\n", @method.text
271
+ assert_equal " #{line}\n #{line2}\n\n def test_1\n assert_not_nil(#{line3})\n end\n\n", @method.text
300
272
  end
301
273
 
302
- def test_extract_definitions_class_with_method
274
+ def test_definitions_class_with_method
303
275
  @method << "class MyClass"
304
276
  @method << "def name"
305
277
  @method << "\"classy\""
@@ -311,8 +283,11 @@ class TestUnitMethodTest < Test::Unit::TestCase
311
283
 
312
284
  def test_text_bad_input_constant
313
285
  @method << "BADCONSTANT"
314
- assert_nil @method.text
286
+ assert_equal " def test_1\n # BADCONSTANT # butterfly_net: Could not evaluate.\n end\n\n", @method.text
315
287
  end
288
+
289
+
290
+
316
291
  # non-project tests (scratchpad)
317
292
 
318
293
  def test_eval_scope
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: butterfly_net
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Smith
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-24 00:00:00 -07:00
12
+ date: 2010-03-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -24,6 +24,7 @@ extra_rdoc_files: []
24
24
  files:
25
25
  - README.md
26
26
  - lib/butterfly_net/commands.rb
27
+ - lib/butterfly_net/definitions.rb
27
28
  - lib/butterfly_net/file_writer.rb
28
29
  - lib/butterfly_net/rails_test_unit_adapter.rb
29
30
  - lib/butterfly_net/readline_reader.rb
@@ -32,6 +33,7 @@ files:
32
33
  - lib/butterfly_net/test_unit_method.rb
33
34
  - lib/butterfly_net.rb
34
35
  - test/butterfly_net_tests.rb
36
+ - test/definitions_test.rb
35
37
  - test/test_case_test.rb
36
38
  - test/test_unit_method_test.rb
37
39
  has_rdoc: true
@@ -61,6 +63,6 @@ rubyforge_project:
61
63
  rubygems_version: 1.3.5
62
64
  signing_key:
63
65
  specification_version: 3
64
- summary: IRB and Rails console history captured as Test::Unit tests. (RSpec and others hopefully soon to come.)
66
+ summary: IRB and Rails console history captured as Test::Unit tests.
65
67
  test_files:
66
68
  - test/butterfly_net_tests.rb