butterfly_net 0.0.4 → 0.0.5

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.
@@ -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