butterfly_net 0.0.2 → 0.0.3
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.md +169 -0
- data/lib/butterfly_net/commands.rb +13 -1
- data/lib/butterfly_net/file_writer.rb +40 -13
- data/lib/butterfly_net/test_unit_adapter.rb +12 -11
- data/lib/butterfly_net/test_unit_method.rb +53 -34
- data/test/test_unit_adapter_test.rb +24 -8
- data/test/test_unit_method_test.rb +159 -68
- metadata +4 -4
- data/README +0 -71
data/README.md
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
Butterfly Net
|
2
|
+
=============
|
3
|
+
|
4
|
+
[Home page and source]: http://butterflynet.org
|
5
|
+
[Rubygems page]: http://rubygems.org/gems/butterfly_net
|
6
|
+
|
7
|
+
Author: Chris Smith (quartzmo -at- gmail.com)
|
8
|
+
|
9
|
+
|
10
|
+
## DESCRIPTION
|
11
|
+
|
12
|
+
IRB and Rails console history captured as Test::Unit tests. (RSpec and others hopefully soon to come.)
|
13
|
+
|
14
|
+
|
15
|
+
## INSTALL
|
16
|
+
|
17
|
+
Butterfly Net is available as a gem from rubygems.org (http://rubygems.org/gems/butterfly_net), or as source from
|
18
|
+
butterflynet.org.
|
19
|
+
|
20
|
+
sudo gem install butterfly_net
|
21
|
+
|
22
|
+
To automatically require Butterfly Net on every IRB session, add the following to your ~/.irbrc:
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'butterfly_net'
|
26
|
+
|
27
|
+
|
28
|
+
## USAGE
|
29
|
+
|
30
|
+
### Command methods
|
31
|
+
|
32
|
+
The following commands can be used in any IRB-based console.
|
33
|
+
|
34
|
+
* bn, bn_open- Open a new test case, closing the current test case if one exists. Args: file_name:string (optional; '.rb' will appended if needed)
|
35
|
+
* bnc, bn_close - Close the active test case, and write the output to a file.
|
36
|
+
* m, bn_method - Close the current test method (or block), naming it with the arg method_name:string (optional)
|
37
|
+
|
38
|
+
### Example Usage in IRB
|
39
|
+
|
40
|
+
$ irb
|
41
|
+
irb(main):001:0> bn 'irb_tests'
|
42
|
+
=> true
|
43
|
+
irb(main):002:0> a = 1
|
44
|
+
=> 1
|
45
|
+
irb(main):003:0> a += 2
|
46
|
+
=> 3
|
47
|
+
irb(main):004:0> m 'plusequals'
|
48
|
+
=> true
|
49
|
+
irb(main):005:0> require 'bigdecimal'
|
50
|
+
=> true
|
51
|
+
irb(main):006:0> infinity = BigDecimal('Infinity')
|
52
|
+
=> #<BigDecimal:114ed34,'Infinity',4(4)>
|
53
|
+
irb(main):007:0> BigDecimal.new("1.0") / BigDecimal.new("0.0") == infinity
|
54
|
+
=> true
|
55
|
+
irb(main):008:0> m 'bigdecimal_infinity'
|
56
|
+
=> true
|
57
|
+
irb(main):009:0> exit
|
58
|
+
butterfly_net: irb_tests.rb closed
|
59
|
+
true
|
60
|
+
$ cat irb_tests.rb
|
61
|
+
require "test/unit"
|
62
|
+
|
63
|
+
# IRB test capture courtesy of butterfly_net (butterflynet.org)
|
64
|
+
class MyTest < Test::Unit::TestCase
|
65
|
+
|
66
|
+
def test_plusequals
|
67
|
+
a = 1
|
68
|
+
assert_equal(3, a += 2)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_bigdecimal_infinity
|
72
|
+
require 'bigdecimal'
|
73
|
+
infinity = BigDecimal('Infinity')
|
74
|
+
assert(BigDecimal.new("1.0") / BigDecimal.new("0.0") == infinity)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
$ ruby irb_tests.rb
|
79
|
+
Loaded suite irb_tests
|
80
|
+
Started
|
81
|
+
..
|
82
|
+
Finished in 0.001603 seconds.
|
83
|
+
|
84
|
+
2 tests, 2 assertions, 0 failures, 0 errors
|
85
|
+
|
86
|
+
|
87
|
+
### Ruby on Rails console
|
88
|
+
|
89
|
+
For repeatable tests, be sure to load the Rails test environment with "./script/console test".
|
90
|
+
In a Rails project, you can run all tests with the standard rake command 'rake test',
|
91
|
+
or an individual test by adding the test directory to the path with the option -I when you invoke Ruby.
|
92
|
+
|
93
|
+
chris$ ./script/console test
|
94
|
+
Loading test environment (Rails 2.3.4)
|
95
|
+
>> bn "test/unit/person_console_test"
|
96
|
+
. . .
|
97
|
+
>> Person.count
|
98
|
+
=> 2
|
99
|
+
>> exit
|
100
|
+
. . .
|
101
|
+
chris$ ruby -Itest test/unit/person_console_test.rb
|
102
|
+
. . .
|
103
|
+
1 tests, 1 assertions, 0 failures, 0 errors
|
104
|
+
|
105
|
+
|
106
|
+
## KNOWN ISSUES
|
107
|
+
|
108
|
+
This section covers issues which may not be resolved quickly. Feel free to lend a hand!
|
109
|
+
|
110
|
+
### Object inspect output
|
111
|
+
|
112
|
+
Butterfly Net relies on an expectation value responding with valid Ruby code to the inspect method, which is the case for core
|
113
|
+
classes such as Hash and Array. However, it's not the case with most classes, many of which respond with the familiar
|
114
|
+
#<...> notation, which can't be interpreted.
|
115
|
+
|
116
|
+
For example:
|
117
|
+
|
118
|
+
assert_equal(#<BigDecimal:11511d8,'Infinity',4(24)>, BigDecimal.new("1.0") / BigDecimal.new("0.0")) # doesn't work
|
119
|
+
|
120
|
+
The workaround is to assign expected values to a variable. Of course, you have to know what to expect in order to do this,
|
121
|
+
which may take a few tries. Sorry.
|
122
|
+
|
123
|
+
|
124
|
+
### Inline variable assignment
|
125
|
+
|
126
|
+
Butterfly Net tries to detect simple assignments, such as "a = 1", in order to write them out clearly,
|
127
|
+
without enclosing assertions. In some cases this causes it to miss statements that should be tested.
|
128
|
+
|
129
|
+
For example:
|
130
|
+
|
131
|
+
irb(main):002:0> a = 1; a + 1
|
132
|
+
=> 2
|
133
|
+
irb(main):003:0> "a=1".split('=')
|
134
|
+
=> ["a", "1"]
|
135
|
+
|
136
|
+
results in
|
137
|
+
|
138
|
+
def test_1
|
139
|
+
a = 1; a + 1 # should have been a = 1; assert_equal(2, a + 1)
|
140
|
+
"a=1".split('=') # should have been assert_equal(["a", "1"],"a=1".split('='))
|
141
|
+
end
|
142
|
+
|
143
|
+
In order to avoid this issue, just put assignments (and anything that looks like an assignment) on separate lines.
|
144
|
+
|
145
|
+
|
146
|
+
## LICENSE
|
147
|
+
|
148
|
+
The MIT License
|
149
|
+
|
150
|
+
Copyright (c) 2010 Chris Smith
|
151
|
+
|
152
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
153
|
+
a copy of this software and associated documentation files (the
|
154
|
+
'Software'), to deal in the Software without restriction, including
|
155
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
156
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
157
|
+
permit persons to whom the Software is furnished to do so, subject to
|
158
|
+
the following conditions:
|
159
|
+
|
160
|
+
The above copyright notice and this permission notice shall be
|
161
|
+
included in all copies or substantial portions of the Software.
|
162
|
+
|
163
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
164
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
165
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
166
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
167
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
168
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
169
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -21,8 +21,9 @@ module ButterflyNet
|
|
21
21
|
file_name += ".rb" unless file_name =~ /.rb$/
|
22
22
|
@file = FileWriter.new(file_name, start_index)
|
23
23
|
Kernel.at_exit { puts @file.close if @file; @file = nil }
|
24
|
-
puts "butterfly_net: #{file_name} opened at Readline::HISTORY ##{start_index}"
|
25
24
|
true
|
25
|
+
rescue
|
26
|
+
false
|
26
27
|
end
|
27
28
|
|
28
29
|
def bn_close
|
@@ -37,9 +38,20 @@ module ButterflyNet
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
def bn_method(method_name=nil)
|
42
|
+
check_for_readline
|
43
|
+
if @file
|
44
|
+
@file.new_assertion_set(method_name)
|
45
|
+
else
|
46
|
+
puts "butterfly_net: First invoke 'bn' or 'bn_open' to begin a session"
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
40
51
|
|
41
52
|
alias :bn :bn_open
|
42
53
|
alias :bnc :bn_close
|
54
|
+
alias :m :bn_method
|
43
55
|
|
44
56
|
private
|
45
57
|
|
@@ -7,33 +7,60 @@ module ButterflyNet
|
|
7
7
|
def initialize(file_name, start_index)
|
8
8
|
@file_name = file_name
|
9
9
|
@start_index = start_index
|
10
|
+
@adapter = TestUnitAdapter.new
|
10
11
|
end
|
11
12
|
|
12
|
-
def new_assertion_set
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
def close
|
13
|
+
def new_assertion_set(method_name)
|
18
14
|
lines = Readline::HISTORY.to_a
|
19
15
|
@end_index ||= Readline::HISTORY.size - 3 # in case of no call to 'bn_close'
|
20
16
|
if @end_index < 0 || lines[@start_index..@end_index].empty?
|
21
|
-
puts "butterfly_net: #{@file_name} closed, no file written to disk"
|
22
17
|
false
|
23
18
|
else
|
24
|
-
|
19
|
+
|
25
20
|
|
26
21
|
lines[@start_index..@end_index].each do |line|
|
27
|
-
adapter.add_command(line)
|
22
|
+
@adapter.add_command(line)
|
28
23
|
end
|
29
24
|
|
30
|
-
adapter.
|
25
|
+
@adapter.close_assertion_set(method_name)
|
26
|
+
@start_index = Readline::HISTORY.size - 1
|
27
|
+
@end_index = nil
|
31
28
|
|
32
|
-
puts "butterfly_net: #{@file_name} closed after Readline::HISTORY ##{@end_index}"
|
33
29
|
true
|
34
30
|
end
|
35
|
-
rescue Exception =>
|
36
|
-
puts "butterfly_net: Error generating tests: #{
|
31
|
+
rescue Exception => e
|
32
|
+
puts "butterfly_net: Error generating tests: #{e}"
|
33
|
+
puts e.backtrace
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def close
|
39
|
+
lines = Readline::HISTORY.to_a
|
40
|
+
@end_index ||= Readline::HISTORY.size - 3 # in case of no call to 'bn_close'
|
41
|
+
# if @adapter.empty?
|
42
|
+
# puts "butterfly_net: #{@file_name} closed, no file written to disk."
|
43
|
+
#
|
44
|
+
# false
|
45
|
+
#
|
46
|
+
# else
|
47
|
+
if @end_index < 0 || lines[@start_index..@end_index].empty?
|
48
|
+
puts "butterfly_net: #{@file_name} closed"
|
49
|
+
else
|
50
|
+
lines[@start_index..@end_index].each do |line|
|
51
|
+
@adapter.add_command(line)
|
52
|
+
end
|
53
|
+
puts "butterfly_net: #{@file_name} closed, with #{@end_index - @start_index + 1} lines, from '#{lines[@start_index]}' to '#{lines[@end_index]}'"
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
@adapter.create_file(@file_name)
|
58
|
+
|
59
|
+
true
|
60
|
+
# end
|
61
|
+
rescue Exception => e
|
62
|
+
puts "butterfly_net: Error generating tests: #{e}"
|
63
|
+
puts e.backtrace
|
37
64
|
false
|
38
65
|
end
|
39
66
|
|
@@ -12,22 +12,28 @@ module ButterflyNet
|
|
12
12
|
@assertion_sets.last << line
|
13
13
|
end
|
14
14
|
|
15
|
-
def close_assertion_set
|
15
|
+
def close_assertion_set(method_name = nil)
|
16
|
+
@assertion_sets.last.name = (method_name ? method_name : @assertion_sets.size)
|
16
17
|
@assertion_sets << TestUnitMethod.new
|
17
18
|
end
|
18
19
|
|
20
|
+
def empty?
|
21
|
+
@assertion_sets.empty?
|
22
|
+
end
|
23
|
+
|
19
24
|
def create_file(filename)
|
20
|
-
return nil if
|
25
|
+
return nil if empty?
|
21
26
|
|
22
27
|
#todo detect existing file, and delete last 'end' line
|
23
28
|
file = File.open(filename, 'a+') # starts at end of file if file exists
|
24
29
|
|
25
30
|
if defined? ActiveSupport::TestCase # rails # todo support earlier versions of rails
|
26
|
-
file.puts "require \"test_helper\"\n\nclass
|
31
|
+
file.puts "require \"test_helper\"\n\n# script/console test capture courtesy of butterfly_net (butterflynet.org)\nclass MyTest < ActiveSupport::TestCase"
|
27
32
|
else
|
28
|
-
file.puts "require \"test/unit\"\n\nclass
|
33
|
+
file.puts "require \"test/unit\"\n\n# IRB test capture courtesy of butterfly_net (butterflynet.org)\nclass MyTest < Test::Unit::TestCase"
|
29
34
|
end
|
30
35
|
|
36
|
+
|
31
37
|
test_methods.each do |test_method|
|
32
38
|
file.puts "\n #{test_method}"
|
33
39
|
end
|
@@ -41,13 +47,8 @@ module ButterflyNet
|
|
41
47
|
end
|
42
48
|
|
43
49
|
def test_methods
|
44
|
-
|
45
|
-
@assertion_sets.
|
46
|
-
|
47
|
-
|
48
|
-
method_strings << assertions.text(i + 1)
|
49
|
-
end
|
50
|
-
method_strings
|
50
|
+
@assertion_sets.last.name = @assertion_sets.size unless @assertion_sets.last.name # done here for testing
|
51
|
+
@assertion_sets.collect {|i| i.text }.compact
|
51
52
|
end
|
52
53
|
|
53
54
|
end
|
@@ -1,67 +1,55 @@
|
|
1
1
|
module ButterflyNet
|
2
2
|
class TestUnitMethod
|
3
3
|
|
4
|
+
attr_accessor :name
|
5
|
+
|
4
6
|
def initialize
|
5
|
-
@
|
7
|
+
@commands = []
|
6
8
|
end
|
7
9
|
|
8
10
|
def <<(line)
|
9
|
-
@
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.simple_assignment_only?(line) # todo: extract to line class
|
13
|
-
line =~ /[^=<>!*%\/+-\\|&]=[^=~]/
|
11
|
+
@commands << line
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
elsif expected && expected == line # type not supported, assume object inequality
|
20
|
-
"assert_not_equal((#{expected}), #{line})"
|
21
|
-
elsif expected == "true" # use simple assert() for true boolean expressions
|
22
|
-
"assert(#{line})"
|
23
|
-
elsif expected
|
24
|
-
"assert_equal(#{expected}, #{line})"
|
25
|
-
else
|
26
|
-
nil
|
27
|
-
end
|
14
|
+
def name=(name)
|
15
|
+
name = underscore(name)
|
16
|
+
@name = name =~ /^test_/ ? name : "test_#{name}"
|
28
17
|
end
|
29
18
|
|
30
|
-
def
|
31
|
-
|
19
|
+
def self.assignment_or_require?(line) # todo: extract to line class
|
20
|
+
line =~ /require\s*['|"]\w+['|"]|[^=<>!*%\/+-\\|&]=[^=~]/
|
32
21
|
end
|
33
22
|
|
34
|
-
def text
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
def text
|
24
|
+
purge_bad_commands
|
25
|
+
lines_string = ""
|
26
|
+
@commands.each_index do |i|
|
27
|
+
text = assertion(i)
|
28
|
+
lines_string += " #{text}\n" if text
|
39
29
|
end
|
40
|
-
|
30
|
+
lines_string.empty? ? nil : "def #{@name}\n#{lines_string} end"
|
41
31
|
end
|
42
32
|
|
43
|
-
def
|
33
|
+
def assertion(current_i)
|
44
34
|
|
45
|
-
current_line = @
|
35
|
+
current_line = @commands[current_i]
|
46
36
|
commands = current_line
|
47
37
|
start_i = current_i
|
48
38
|
|
49
39
|
begin
|
50
40
|
retval = eval commands
|
51
|
-
rescue
|
41
|
+
rescue Exception
|
52
42
|
start_i -= 1
|
53
|
-
commands = @
|
43
|
+
commands = @commands[start_i..current_i].join("\n")
|
54
44
|
|
55
45
|
if start_i < 0
|
56
|
-
|
57
|
-
return nil
|
46
|
+
return nil # give up, can't go further back
|
58
47
|
else
|
59
48
|
retry
|
60
49
|
end
|
61
50
|
end
|
62
|
-
if
|
51
|
+
if TestUnitMethod.assignment_or_require?(current_line)
|
63
52
|
current_line
|
64
|
-
|
65
53
|
elsif instances_equal_by_value?(retval) # expression result supports value equality
|
66
54
|
|
67
55
|
if retval == true # use simple assert() for true boolean expressions
|
@@ -84,6 +72,37 @@ module ButterflyNet
|
|
84
72
|
instance == instance.dup rescue true # can't dup Fixnum, et al...
|
85
73
|
end
|
86
74
|
|
75
|
+
private
|
76
|
+
|
77
|
+
|
78
|
+
def purge_bad_commands
|
79
|
+
begin
|
80
|
+
commands = ""
|
81
|
+
index = 0
|
82
|
+
@commands.each_with_index do |current_line, i|
|
83
|
+
index = i
|
84
|
+
commands += current_line + "\n"
|
85
|
+
eval commands
|
86
|
+
end
|
87
|
+
|
88
|
+
rescue Exception
|
89
|
+
# delete offender and start again from the beginning
|
90
|
+
@commands.delete_at index
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
# Adapted from ActiveSupport Inflector
|
96
|
+
def underscore(name)
|
97
|
+
name.to_s.strip.
|
98
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
99
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
100
|
+
tr("-", "_").
|
101
|
+
tr(" ", "_").
|
102
|
+
downcase
|
103
|
+
end
|
104
|
+
|
105
|
+
|
87
106
|
|
88
107
|
end
|
89
108
|
end
|
@@ -22,7 +22,6 @@ class TestUnitAdapterTest < Test::Unit::TestCase
|
|
22
22
|
def test_test_methods_single
|
23
23
|
@adapter.add_command("1 + 1")
|
24
24
|
expected = "def test_1\n assert_equal(2, 1 + 1)\n end"
|
25
|
-
@adapter.test_methods
|
26
25
|
assert_equal expected, @adapter.test_methods.first
|
27
26
|
end
|
28
27
|
|
@@ -30,7 +29,6 @@ class TestUnitAdapterTest < Test::Unit::TestCase
|
|
30
29
|
@adapter.add_command("1 + 1")
|
31
30
|
@adapter.add_command("1 + 2")
|
32
31
|
expected = "def test_1\n assert_equal(2, 1 + 1)\n assert_equal(3, 1 + 2)\n end"
|
33
|
-
@adapter.test_methods
|
34
32
|
assert_equal expected, @adapter.test_methods.last
|
35
33
|
end
|
36
34
|
|
@@ -38,7 +36,13 @@ class TestUnitAdapterTest < Test::Unit::TestCase
|
|
38
36
|
@adapter.add_command("a = 1")
|
39
37
|
@adapter.add_command("a + 2")
|
40
38
|
expected = "def test_1\n a = 1\n assert_equal(3, a + 2)\n end"
|
41
|
-
@adapter.test_methods
|
39
|
+
assert_equal expected, @adapter.test_methods.last
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_test_methods_require
|
43
|
+
@adapter.add_command("require 'bigdecimal'")
|
44
|
+
@adapter.add_command("BigDecimal(\"1.0\") - 0.5")
|
45
|
+
expected = "def test_1\n require 'bigdecimal'\n assert_equal(0.5, BigDecimal(\"1.0\") - 0.5)\n end"
|
42
46
|
assert_equal expected, @adapter.test_methods.last
|
43
47
|
end
|
44
48
|
|
@@ -46,9 +50,20 @@ class TestUnitAdapterTest < Test::Unit::TestCase
|
|
46
50
|
@adapter.add_command("1 + 1")
|
47
51
|
@adapter.close_assertion_set
|
48
52
|
@adapter.add_command("1 + 2")
|
49
|
-
|
50
|
-
@adapter.test_methods
|
51
|
-
|
53
|
+
assert_equal "def test_1\n assert_equal(2, 1 + 1)\n end", @adapter.test_methods.first
|
54
|
+
assert_equal "def test_2\n assert_equal(3, 1 + 2)\n end", @adapter.test_methods.last
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_test_methods_naming
|
58
|
+
@adapter.add_command("1 + 1")
|
59
|
+
@adapter.close_assertion_set 'test_one_plus_one'
|
60
|
+
assert_equal "def test_one_plus_one\n assert_equal(2, 1 + 1)\n end", @adapter.test_methods.first
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_test_methods_bad_input
|
64
|
+
@adapter.add_command("BADCOMMAND")
|
65
|
+
@adapter.close_assertion_set
|
66
|
+
assert_nil @adapter.test_methods.first
|
52
67
|
end
|
53
68
|
|
54
69
|
def test_create_file
|
@@ -56,7 +71,8 @@ class TestUnitAdapterTest < Test::Unit::TestCase
|
|
56
71
|
expected = <<-EOF
|
57
72
|
require "test/unit"
|
58
73
|
|
59
|
-
|
74
|
+
# IRB test capture courtesy of butterfly_net (butterflynet.org)
|
75
|
+
class MyTest < Test::Unit::TestCase
|
60
76
|
|
61
77
|
def test_1
|
62
78
|
assert_equal(2, 1 + 1)
|
@@ -64,7 +80,7 @@ class TempTest < Test::Unit::TestCase
|
|
64
80
|
|
65
81
|
end
|
66
82
|
EOF
|
67
|
-
@adapter.create_file('temp_test.rb')
|
83
|
+
@adapter.create_file('temp_test.rb') # todo: write to memory instead of file...
|
68
84
|
assert_equal expected, File.open('temp_test.rb').readlines.join('')
|
69
85
|
end
|
70
86
|
|
@@ -8,174 +8,265 @@ class TestUnitMethodTest < Test::Unit::TestCase
|
|
8
8
|
|
9
9
|
def setup
|
10
10
|
@method = TestUnitMethod.new
|
11
|
+
@method.name = "1"
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
assert TestUnitMethod.
|
14
|
+
def test_assignment_or_require_true
|
15
|
+
assert TestUnitMethod.assignment_or_require? "a=1"
|
15
16
|
end
|
16
17
|
|
17
|
-
# def
|
18
|
-
# assert TestUnitMethod.
|
18
|
+
# def test_assignment_or_require_true_orequals todo: solve orequals in regex
|
19
|
+
# assert TestUnitMethod.assignment_or_require? "a ||= 1"
|
19
20
|
# end
|
20
21
|
|
21
|
-
def
|
22
|
-
assert TestUnitMethod.
|
22
|
+
def test_assignment_or_require_true_whitespace
|
23
|
+
assert TestUnitMethod.assignment_or_require? "a = 1"
|
23
24
|
end
|
24
25
|
|
25
|
-
def
|
26
|
-
assert TestUnitMethod.
|
26
|
+
def test_assignment_or_require_true_contains_equals
|
27
|
+
assert TestUnitMethod.assignment_or_require? "a = (1 == 1)"
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
assert
|
30
|
+
def test_assignment_or_require_true_require_bigdecimal
|
31
|
+
assert TestUnitMethod.assignment_or_require? "require 'bigdecimal'"
|
31
32
|
end
|
32
33
|
|
33
|
-
def
|
34
|
-
assert
|
34
|
+
def test_assignment_or_require_true_require
|
35
|
+
assert TestUnitMethod.assignment_or_require? "require 'rubygems'"
|
35
36
|
end
|
36
37
|
|
37
|
-
def
|
38
|
-
assert
|
38
|
+
def test_assignment_or_require_true_require_no_spaces
|
39
|
+
assert TestUnitMethod.assignment_or_require? "require\"rubygems\""
|
39
40
|
end
|
40
41
|
|
41
|
-
def
|
42
|
-
|
42
|
+
def test_assignment_or_require_false
|
43
|
+
assert !TestUnitMethod.assignment_or_require?("a + 1")
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
-
|
46
|
+
def test_assignment_or_require_false_with_equals
|
47
|
+
assert !TestUnitMethod.assignment_or_require?("a == 1")
|
47
48
|
end
|
48
49
|
|
49
|
-
def
|
50
|
-
|
50
|
+
def test_assignment_or_require_false_threequals
|
51
|
+
assert !TestUnitMethod.assignment_or_require?("a===1")
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
-
assert !TestUnitMethod.
|
54
|
+
def test_assignment_or_require_false_regex
|
55
|
+
assert !TestUnitMethod.assignment_or_require?("'a' =~ /a/")
|
55
56
|
end
|
56
57
|
|
57
|
-
def
|
58
|
-
assert !TestUnitMethod.
|
58
|
+
def test_assignment_or_require_false_regex
|
59
|
+
assert !TestUnitMethod.assignment_or_require?("'a' =~ /a/")
|
59
60
|
end
|
60
61
|
|
61
|
-
def
|
62
|
-
assert !TestUnitMethod.
|
62
|
+
def test_assignment_or_require_false_lessthanequals
|
63
|
+
assert !TestUnitMethod.assignment_or_require?("1 <= 1")
|
63
64
|
end
|
64
65
|
|
65
|
-
def
|
66
|
-
assert !TestUnitMethod.
|
66
|
+
def test_assignment_or_require_false_greaterthanequals
|
67
|
+
assert !TestUnitMethod.assignment_or_require?("1 >= 1")
|
67
68
|
end
|
68
69
|
|
69
|
-
def
|
70
|
-
assert !TestUnitMethod.
|
70
|
+
def test_assignment_or_require_false_flyingsaucer
|
71
|
+
assert !TestUnitMethod.assignment_or_require?("1 <=> 1")
|
71
72
|
end
|
72
73
|
|
73
|
-
def
|
74
|
-
assert !TestUnitMethod.
|
74
|
+
def test_assignment_or_require_false_notequal
|
75
|
+
assert !TestUnitMethod.assignment_or_require?("1 != 0")
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
-
assert !TestUnitMethod.
|
78
|
+
def test_assignment_or_require_false_modequal
|
79
|
+
assert !TestUnitMethod.assignment_or_require?("a %= 1")
|
79
80
|
end
|
80
81
|
|
81
|
-
def
|
82
|
-
assert !TestUnitMethod.
|
82
|
+
def test_assignment_or_require_false_orequal
|
83
|
+
assert !TestUnitMethod.assignment_or_require?("a |= 1")
|
83
84
|
end
|
84
85
|
|
85
|
-
def
|
86
|
-
assert !TestUnitMethod.
|
86
|
+
def test_assignment_or_require_false_plusequal
|
87
|
+
assert !TestUnitMethod.assignment_or_require?("a += 1")
|
87
88
|
end
|
88
89
|
|
89
|
-
def
|
90
|
-
assert !TestUnitMethod.
|
90
|
+
def test_assignment_or_require_false_minusequal
|
91
|
+
assert !TestUnitMethod.assignment_or_require?("a -= 1")
|
91
92
|
end
|
92
93
|
|
93
|
-
def
|
94
|
-
assert !TestUnitMethod.
|
94
|
+
def test_assignment_or_require_false_divideequal
|
95
|
+
assert !TestUnitMethod.assignment_or_require?("a /= 1")
|
95
96
|
end
|
96
97
|
|
97
|
-
def
|
98
|
-
assert !TestUnitMethod.
|
98
|
+
def test_assignment_or_require_false_andequal
|
99
|
+
assert !TestUnitMethod.assignment_or_require?("a &= 1")
|
99
100
|
end
|
100
101
|
|
102
|
+
def test_assignment_or_require_false_shiftrightequal
|
103
|
+
assert !TestUnitMethod.assignment_or_require?("a >>= 1")
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_assignment_or_require_false_shiftleftequal
|
107
|
+
assert !TestUnitMethod.assignment_or_require?("a <<= 1")
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_assignment_or_require_false_timesequal
|
111
|
+
assert !TestUnitMethod.assignment_or_require?("a *= 1")
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_name_uppercase
|
115
|
+
@method.name = "MYMETHOD"
|
116
|
+
assert_equal("test_mymethod", @method.name)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_name_camelcase
|
120
|
+
@method.name = "MyMethod"
|
121
|
+
assert_equal("test_my_method", @method.name)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_name_hyphenated
|
125
|
+
@method.name = "my-Method"
|
126
|
+
assert_equal("test_my_method", @method.name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_name_spaces
|
130
|
+
@method.name = " my Method "
|
131
|
+
assert_equal("test_my_method", @method.name)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_test_methods_naming_no_changes
|
135
|
+
@method.name = 'test_one_plus_one'
|
136
|
+
assert_equal("test_one_plus_one", @method.name)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_test_methods_naming_prepends_test
|
140
|
+
@method.name = 'one_plus_one'
|
141
|
+
assert_equal("test_one_plus_one", @method.name)
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
# def test_text_split_statements_into_lines todo
|
147
|
+
# @method << "a = 1; a + 1"
|
148
|
+
# assert_equal "def test_1\n a = 1\n assert_equal(2, a + 1)\n end", @method.text
|
149
|
+
# end
|
150
|
+
|
151
|
+
def test_purge_unexpected_identifier
|
152
|
+
@method << "a = 1"
|
153
|
+
@method << "2b" # syntax error, unexpected tIDENTIFIER, expecting $end
|
154
|
+
@method << "a += 1"
|
155
|
+
assert_equal "def test_1\n a = 1\n assert_equal(2, a += 1)\n end", @method.text
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_purge_unexpected_identifiers
|
159
|
+
@method << "a += 1" # undefined method `+' for nil:NilClass
|
160
|
+
@method << "a = 1"
|
161
|
+
@method << "a += 1"
|
162
|
+
assert_equal "def test_1\n a = 1\n assert_equal(2, a += 1)\n end", @method.text
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_text_require
|
166
|
+
@method << "require 'rubygems'"
|
167
|
+
@method << "require'active_support'"
|
168
|
+
@method << "'CamelCase'.underscore"
|
169
|
+
assert_equal "def test_1\n require 'rubygems'\n require'active_support'\n assert_equal(\"camel_case\", 'CamelCase'.underscore)\n end", @method.text
|
170
|
+
end
|
101
171
|
|
102
172
|
def test_expected_boolean
|
103
173
|
line = "1 == 1"
|
104
174
|
@method << line
|
105
|
-
assert_equal("assert(#{line})", @method.
|
175
|
+
assert_equal("assert(#{line})", @method.assertion(0))
|
106
176
|
end
|
107
177
|
|
108
178
|
def test_assertion_fixnum
|
109
179
|
line = "1"
|
110
180
|
@method << line
|
111
|
-
assert_equal("assert_equal(#{line}, #{line})", @method.
|
181
|
+
assert_equal("assert_equal(#{line}, #{line})", @method.assertion(0))
|
112
182
|
end
|
113
183
|
|
114
184
|
def test_assertion_boolean_false
|
115
185
|
line = "1 != 1"
|
116
186
|
@method << line
|
117
|
-
assert_equal("assert_equal(false, #{line})", @method.
|
187
|
+
assert_equal("assert_equal(false, #{line})", @method.assertion(0))
|
118
188
|
end
|
119
189
|
|
120
|
-
|
121
|
-
|
122
190
|
def test_array_add
|
123
191
|
@method << "a = []"
|
124
192
|
line2 = "a << \"1\""
|
125
193
|
@method << line2
|
126
|
-
assert_equal("assert_equal([\"1\"], #{line2})", @method.
|
194
|
+
assert_equal("assert_equal([\"1\"], #{line2})", @method.assertion(1))
|
127
195
|
end
|
128
196
|
|
129
197
|
def test_butterfly_net
|
130
198
|
@method << "method = TestUnitMethod.new"
|
131
199
|
@method << "method << \"1 + 1\""
|
132
|
-
assert_equal("assert_equal([\"1 + 1\"], method << \"1 + 1\")", @method.
|
200
|
+
assert_equal("assert_equal([\"1 + 1\"], method << \"1 + 1\")", @method.assertion(1))
|
133
201
|
end
|
134
202
|
|
135
|
-
|
136
|
-
|
137
|
-
def test_text_from_expression_boolean
|
203
|
+
def test_assertion_boolean
|
138
204
|
line = "1 == 1"
|
139
205
|
@method << line
|
140
|
-
assert_equal("assert(#{line})", @method.
|
206
|
+
assert_equal("assert(#{line})", @method.assertion(0))
|
141
207
|
end
|
142
208
|
|
143
|
-
def
|
209
|
+
def test_assertion_string
|
144
210
|
line = "'a' + 'b'"
|
145
211
|
@method << line
|
146
|
-
assert_equal("assert_equal(\"ab\", #{line})", @method.
|
212
|
+
assert_equal("assert_equal(\"ab\", #{line})", @method.assertion(0))
|
147
213
|
end
|
148
214
|
|
149
|
-
def
|
215
|
+
def test_assertion_nil
|
150
216
|
line = "[].first"
|
151
217
|
@method << line
|
152
|
-
assert_equal("assert_nil(#{line})", @method.
|
218
|
+
assert_equal("assert_nil(#{line})", @method.assertion(0))
|
153
219
|
end
|
154
220
|
|
155
|
-
def
|
221
|
+
def test_assertion_boolean
|
156
222
|
line = "1 == 1"
|
157
223
|
@method << line
|
158
|
-
assert_equal("assert(#{line})", @method.
|
224
|
+
assert_equal("assert(#{line})", @method.assertion(0))
|
159
225
|
end
|
160
226
|
|
161
|
-
def
|
227
|
+
def test_assertion_object_not_equal
|
162
228
|
line = "Object.new"
|
163
229
|
@method << line
|
164
|
-
assert_equal("assert_not_equal((#{line}), #{line})", @method.
|
230
|
+
assert_equal("assert_not_equal((#{line}), #{line})", @method.assertion(0))
|
165
231
|
end
|
166
232
|
|
167
|
-
def
|
233
|
+
def test_assertion_array
|
168
234
|
line = "([1,2,3])[0..0]"
|
169
235
|
@method << line
|
170
|
-
assert_equal("assert_equal([1], #{line})", @method.
|
236
|
+
assert_equal("assert_equal([1], #{line})", @method.assertion(0))
|
171
237
|
end
|
172
238
|
|
173
|
-
def
|
174
|
-
line = "
|
239
|
+
def test_assertion_illegal_input
|
240
|
+
line = "badtext"
|
175
241
|
@method << line
|
176
|
-
assert_nil @method.
|
242
|
+
assert_nil @method.assertion(0)
|
177
243
|
end
|
178
244
|
|
245
|
+
def test_text
|
246
|
+
@method << "1 + 1"
|
247
|
+
assert_equal "def test_1\n assert_equal(2, 1 + 1)\n end", @method.text
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
|
252
|
+
def test_text_bad_input_constant
|
253
|
+
@method << "BADCONSTANT"
|
254
|
+
assert_nil @method.text
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
|
179
270
|
# non-project tests (scratchpad)
|
180
271
|
|
181
272
|
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
|
+
version: 0.0.3
|
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-
|
12
|
+
date: 2010-02-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -22,7 +22,7 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
- README
|
25
|
+
- README.md
|
26
26
|
- lib/butterfly_net/commands.rb
|
27
27
|
- lib/butterfly_net/file_writer.rb
|
28
28
|
- lib/butterfly_net/test_unit_adapter.rb
|
@@ -32,7 +32,7 @@ files:
|
|
32
32
|
- test/test_unit_adapter_test.rb
|
33
33
|
- test/test_unit_method_test.rb
|
34
34
|
has_rdoc: true
|
35
|
-
homepage: http://
|
35
|
+
homepage: http://www.butterflynet.org
|
36
36
|
licenses: []
|
37
37
|
|
38
38
|
post_install_message:
|
data/README
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
butterfly_net
|
2
|
-
|
3
|
-
Version: 0.0.2
|
4
|
-
|
5
|
-
Author: Chris Smith
|
6
|
-
Email: quartzmo@gmail.com
|
7
|
-
Project homepage: http://github.com/quartzmo/butterfly_net
|
8
|
-
|
9
|
-
DESCRIPTION
|
10
|
-
|
11
|
-
IRB history captured as Test::Unit tests. (RSpec and others hopefully soon to come.)
|
12
|
-
|
13
|
-
INSTALL
|
14
|
-
|
15
|
-
1. gem sources -a http://gemcutter.org
|
16
|
-
2. sudo gem install butterfly_net
|
17
|
-
3. To automatically require butterfly_net on every IRB session, add the following to your ~/.irbrc:
|
18
|
-
|
19
|
-
require 'rubygems'
|
20
|
-
require 'butterfly_net'
|
21
|
-
|
22
|
-
USAGE
|
23
|
-
|
24
|
-
Command methods:
|
25
|
-
|
26
|
-
bn, bn_open - Open an active test case, with optional string arg file_name ('.rb' is appended if needed)
|
27
|
-
bnc, bn_close - Close the active test case, and write the output to a file
|
28
|
-
|
29
|
-
Ruby on Rails console:
|
30
|
-
|
31
|
-
For repeatable tests, be sure to load the Rails test environment with "./script/console test".
|
32
|
-
In a Rails project, you can run all tests with the standard rake command 'rake test',
|
33
|
-
or an individual test by adding the test directory to the path with the option -I when you invoke Ruby.
|
34
|
-
|
35
|
-
chris$ ./script/console test
|
36
|
-
Loading test environment (Rails 2.3.4)
|
37
|
-
>> bn "test/unit/person_console_test"
|
38
|
-
. . .
|
39
|
-
>> Person.count
|
40
|
-
=> 2
|
41
|
-
>> exit
|
42
|
-
. . .
|
43
|
-
chris$ ruby -Itest test/unit/person_console_test.rb
|
44
|
-
. . .
|
45
|
-
1 tests, 1 assertions, 0 failures, 0 errors
|
46
|
-
|
47
|
-
|
48
|
-
LICENSE
|
49
|
-
|
50
|
-
(The MIT License)
|
51
|
-
|
52
|
-
Copyright (c) 2010 Chris Smith
|
53
|
-
|
54
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
55
|
-
a copy of this software and associated documentation files (the
|
56
|
-
'Software'), to deal in the Software without restriction, including
|
57
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
58
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
59
|
-
permit persons to whom the Software is furnished to do so, subject to
|
60
|
-
the following conditions:
|
61
|
-
|
62
|
-
The above copyright notice and this permission notice shall be
|
63
|
-
included in all copies or substantial portions of the Software.
|
64
|
-
|
65
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
66
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
67
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
68
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
69
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
70
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
71
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|