erudite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MmMyNDJiNGZhYjc3YmY5NDJmNjA1ZWY2OWZmNDRkMDdiYjAwMzA0MQ==
5
+ data.tar.gz: !binary |-
6
+ NjA3YjdkZWY3OTVjMDM2OTI2NTUzZWU2YzRhNTViMjI5NmE4NjkxOQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NjllZjIyNjdkMWE2YjQwNGJmNmUxZTQyYTA5ODFhNmI5OGIxYTllYTU4NDNh
10
+ OWM5M2Y2N2ZhMWM0YzIxNzI4NzdjOTI3MTQ0YTFlNjdlNzU2ZjhhMjNmZDE4
11
+ ZDhhMWU1NTc5NzUwY2Q0ZWIxYzVmNDEzZjQzOGE1OWMxNzY4OTU=
12
+ data.tar.gz: !binary |-
13
+ MThjNzM2YTllMTY2NzBkNGY4ZjYwZTRmODljMGE1YTkzOGNmYmMzYzQzMDg4
14
+ N2Y1YzIwY2I4Y2JiMmJmNGVmMTBiMWQwMTY4YjIzZDcxMzk5NmJmZWQ4ZDFh
15
+ YjhlMGMyOTBmMjVkOTYyYzZkZTI3YTY1NWU1MDI4YzRlMGY2NzY=
@@ -0,0 +1 @@
1
+ # Changelog
@@ -0,0 +1,7 @@
1
+ # Contributing
2
+
3
+ 1. **Fork** the repository.
4
+ 2. Create a **branch** for your feature (`git checkout -b feature`).
5
+ 3. **Commit** your changes (`git commit -a -m 'Feature'`).
6
+ 4. **Push** to your branch (`git push origin feature`).
7
+ 5. Create a **pull request**.
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2014 Taylor Fausak <taylor@fausak.me>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # [Erudite][1]
2
+
3
+ Executable documentation.
4
+
5
+ ``` rb
6
+ examples = Erudite::Parser.parse(<<-'RUBY')
7
+ >> 1 + 2
8
+ => 3
9
+
10
+ >> Object.new
11
+ => #<Object:0x...>
12
+
13
+ >> gets
14
+ => nil
15
+
16
+ >> puts 'hello world'
17
+ hello world
18
+ => nil
19
+
20
+ >> warn 'oh noes'
21
+ oh noes
22
+ => nil
23
+
24
+ >> fail 'catastrophe!'
25
+ RuntimeError: catastrophe!
26
+
27
+ >> puts 'chunky
28
+ .. bacon'
29
+ chunky
30
+ bacon
31
+ => nil
32
+
33
+ >> def double(n)
34
+ .. 2 * n
35
+ .. end
36
+ >> double(3)
37
+ => 6
38
+ RUBY
39
+
40
+ examples.each do |example|
41
+ if example.pass?
42
+ puts 'PASS'
43
+ else
44
+ puts 'FAIL'
45
+ puts " expected : #{example.expected.result.inspect}"
46
+ puts " : #{example.expected.output.inspect}"
47
+ puts " actual : #{example.actual.result.inspect}"
48
+ puts " : #{example.actual.output.inspect}"
49
+ end
50
+ end
51
+ ```
52
+
53
+ [1]: https://github.com/tfausak/erudite
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+
3
+ require 'erudite/example'
4
+ require 'erudite/outcome'
5
+ require 'erudite/parser'
6
+
7
+ # Executable documentation.
8
+ module Erudite
9
+ end
@@ -0,0 +1,79 @@
1
+ # coding: utf-8
2
+
3
+ require 'stringio'
4
+
5
+ module Erudite
6
+ # Code to be run and compared against its expected outcome.
7
+ class Example
8
+ attr_reader :source
9
+ attr_reader :expected
10
+ attr_writer :binding
11
+
12
+ def initialize(source, result = nil, output = nil)
13
+ @source = source
14
+ @expected = Outcome.new(result, output)
15
+ end
16
+
17
+ def binding
18
+ @binding ||= TOPLEVEL_BINDING.dup
19
+ end
20
+
21
+ def run!
22
+ binding.eval(source, __FILE__, __LINE__)
23
+ end
24
+
25
+ def run
26
+ [run!, nil]
27
+ rescue Exception => exception # rubocop:disable Lint/RescueException
28
+ [nil, exception]
29
+ end
30
+
31
+ def self.without_stdio
32
+ stdin, stdout, stderr = $stdin, $stdout, $stderr
33
+ $stdin = $stdout = $stderr = io = StringIO.new
34
+ [yield, io]
35
+ ensure
36
+ $stdin, $stdout, $stderr = stdin, stdout, stderr
37
+ end
38
+
39
+ def self.format_exception(exception)
40
+ "#{exception.class.name}: #{exception.message}"
41
+ end
42
+
43
+ def actual
44
+ return @actual if defined?(@actual)
45
+
46
+ result, io = self.class.without_stdio do
47
+ result, exception = run
48
+ warn(self.class.format_exception(exception)) if exception
49
+ result.inspect
50
+ end
51
+
52
+ @actual = Outcome.new(result, io.string)
53
+ end
54
+
55
+ def self.pattern(string)
56
+ Regexp.new(Regexp.escape(string).gsub('\.\.\.', '.*?'))
57
+ end
58
+
59
+ def valid_result?
60
+ return true unless expected.result
61
+ self.class.pattern(expected.result).match(actual.result)
62
+ end
63
+
64
+ def valid_output?
65
+ return true unless expected.output
66
+ self.class.pattern(expected.output).match(actual.output)
67
+ end
68
+
69
+ def pass?
70
+ actual
71
+ valid_result? && valid_output?
72
+ end
73
+
74
+ def ==(other)
75
+ source == other.source &&
76
+ expected == other.expected
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ module Erudite
4
+ # Information about an expected or actual outcome.
5
+ class Outcome
6
+ attr_reader :result
7
+ attr_reader :output
8
+
9
+ def initialize(result, output)
10
+ @result = result
11
+ @output = output
12
+ end
13
+
14
+ def ==(other)
15
+ result == other.result &&
16
+ output == other.output
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+
3
+ module Erudite
4
+ # Parses IRB output into examples.
5
+ class Parser
6
+ def self.parse(string)
7
+ group(string).map { |lines| exemplify(lines) }
8
+ end
9
+
10
+ def self.group(string)
11
+ buffer = []
12
+
13
+ groups = string.each_line.each_with_object([]) do |line, array|
14
+ if line.start_with?('>> ') && !buffer.empty?
15
+ array.push(buffer)
16
+ buffer = []
17
+ end
18
+
19
+ buffer.push(line)
20
+ end
21
+
22
+ buffer.empty? ? groups : groups.push(buffer)
23
+ end
24
+
25
+ def self.exemplify(lines)
26
+ source = extract_source(lines)
27
+ result = extract_result(lines)
28
+ output = extract_output(lines)
29
+
30
+ Example.new(source, result, output)
31
+ end
32
+
33
+ def self.extract_source(lines)
34
+ source = lines
35
+ .select { |line| line.start_with?('>> ', '.. ') }
36
+ .map { |line| line[3..-1].chomp }
37
+ source.join("\n") unless source.empty?
38
+ end
39
+
40
+ def self.extract_result(lines)
41
+ result = lines
42
+ .select { |line| line.start_with?('=> ') }
43
+ .map { |line| line[3..-1].chomp }
44
+ result.join("\n") unless result.empty?
45
+ end
46
+
47
+ def self.extract_output(lines)
48
+ output = lines
49
+ .reject { |line| line.start_with?('>> ', '.. ', '=> ') }
50
+ .map { |line| line.chomp }
51
+ output.join("\n") unless output.empty?
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,352 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Erudite::Example do
6
+ it 'requires some source' do
7
+ expect { described_class.new }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ it 'can be initialized' do
11
+ expect(described_class.new(nil)).to be_a(described_class)
12
+ end
13
+
14
+ it 'sets the source' do
15
+ source = double
16
+ example = described_class.new(source)
17
+ expect(example.source).to eql(source)
18
+ end
19
+
20
+ it 'uses the default expected outcome' do
21
+ example = described_class.new(nil)
22
+ expect(example.expected).to be_an(Erudite::Outcome)
23
+ expect(example.expected.result).to be(nil)
24
+ expect(example.expected.output).to be(nil)
25
+ end
26
+
27
+ it 'sets the expected result' do
28
+ result = double
29
+ example = described_class.new(nil, result)
30
+ expect(example.expected.result).to eql(result)
31
+ end
32
+
33
+ it 'sets the expected output' do
34
+ output = double
35
+ example = described_class.new(nil, nil, output)
36
+ expect(example.expected.output).to eql(output)
37
+ end
38
+
39
+ describe '#binding' do
40
+ it 'uses the default binding' do
41
+ example = described_class.new(nil)
42
+ expect(example.binding).to be_a(Binding)
43
+ expect(example.binding.eval('self')).to be(TOPLEVEL_BINDING.eval('self'))
44
+ expect(example.binding).to_not be(TOPLEVEL_BINDING)
45
+ end
46
+
47
+ it 'memoizes the binding' do
48
+ example = described_class.new(nil)
49
+ binding = example.binding
50
+ expect(example.binding).to be(binding)
51
+ end
52
+
53
+ it 'sets the binding' do
54
+ example = described_class.new(nil)
55
+ binding = TOPLEVEL_BINDING.dup
56
+ example.binding = binding
57
+ expect(example.binding).to be(binding)
58
+ end
59
+ end
60
+
61
+ describe '#run!' do
62
+ it 'evaluates the source' do
63
+ source = ':something'
64
+ example = described_class.new(source)
65
+ expect(example.run!).to eql(TOPLEVEL_BINDING.eval(source))
66
+ end
67
+
68
+ it 'evaluates the source in the binding' do
69
+ source = 'variable'
70
+ example = described_class.new(source)
71
+ example.binding.eval('variable = :something')
72
+ expect(example.run!).to eql(example.binding.eval(source))
73
+ end
74
+
75
+ it 'sets the file name' do
76
+ example = described_class.new('fail')
77
+ begin
78
+ example.run!
79
+ rescue => error
80
+ expect(error.backtrace.first).to_not start_with('<main>:')
81
+ end
82
+ end
83
+
84
+ it 'sets the line number' do
85
+ example = described_class.new('fail')
86
+ begin
87
+ example.run!
88
+ rescue => error
89
+ expect(error.backtrace.first).to_not end_with(":1:in `<main>'")
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '#run' do
95
+ it 'returns the result' do
96
+ source = ':something'
97
+ example = described_class.new(source)
98
+ expect(example.run.first).to eql(TOPLEVEL_BINDING.eval(source))
99
+ expect(example.run.last).to be(nil)
100
+ end
101
+
102
+ it 'returns the exception' do
103
+ source = 'fail'
104
+ example = described_class.new(source)
105
+ expect(example.run.first).to be(nil)
106
+ expect(example.run.last).to be_a(StandardError)
107
+ end
108
+ end
109
+
110
+ describe '.without_stdio' do
111
+ it 'requires a block' do
112
+ expect { described_class.without_stdio }.to raise_error(LocalJumpError)
113
+ end
114
+
115
+ it 'calls the block' do
116
+ result = double
117
+ expect(described_class.without_stdio { result }.first).to eql(result)
118
+ end
119
+
120
+ it 'redirects STDIN' do
121
+ stdin = $stdin
122
+ expect(described_class.without_stdio { $stdin }).to_not eq(stdin)
123
+ end
124
+
125
+ it 'redirects STDOUT' do
126
+ stdout = $stdout
127
+ expect(described_class.without_stdio { $stdout }).to_not eq(stdout)
128
+ end
129
+
130
+ it 'redirects STDERR' do
131
+ stderr = $stderr
132
+ expect(described_class.without_stdio { $stderr }).to_not eq(stderr)
133
+ end
134
+
135
+ it 'reconnects STDIN' do
136
+ stdin = $stdin
137
+ begin
138
+ described_class.without_stdio { fail }
139
+ rescue
140
+ nil
141
+ end
142
+ expect($stdin).to eq(stdin)
143
+ end
144
+
145
+ it 'reconnects STDOUT' do
146
+ stdout = $stdout
147
+ begin
148
+ described_class.without_stdio { fail }
149
+ rescue
150
+ nil
151
+ end
152
+ expect($stdout).to eq(stdout)
153
+ end
154
+
155
+ it 'reconnects STDERR' do
156
+ stderr = $stderr
157
+ begin
158
+ described_class.without_stdio { fail }
159
+ rescue
160
+ nil
161
+ end
162
+ expect($stderr).to eq(stderr)
163
+ end
164
+
165
+ it 'returns the redirected IO' do
166
+ expect(described_class.without_stdio {}.last).to be_a(StringIO)
167
+ end
168
+
169
+ it 'handles STDIN' do
170
+ result, _ = described_class.without_stdio { gets }
171
+ expect(result).to be(nil)
172
+ end
173
+
174
+ it 'handles STDOUT' do
175
+ _, io = described_class.without_stdio { puts 'something' }
176
+ expect(io.string).to eql("something\n")
177
+ end
178
+
179
+ it 'handles STDERR' do
180
+ _, io = described_class.without_stdio { warn 'something' }
181
+ expect(io.string).to eql("something\n")
182
+ end
183
+ end
184
+
185
+ describe '.format_exception' do
186
+ it 'formats the exception' do
187
+ exception = StandardError.new('something')
188
+ expect(described_class.format_exception(exception))
189
+ .to eql("#{exception.class.name}: #{exception.message}")
190
+ end
191
+ end
192
+
193
+ describe '#actual' do
194
+ it 'sets the result' do
195
+ example = described_class.new('"something"')
196
+ expect(example.actual.result).to eql('"something"')
197
+ expect(example.actual.output).to eql('')
198
+ end
199
+
200
+ it 'handles STDIN' do
201
+ example = described_class.new('gets')
202
+ expect(example.actual.result).to eql('nil')
203
+ expect(example.actual.output).to eql('')
204
+ end
205
+
206
+ it 'handles STDOUT' do
207
+ example = described_class.new('puts "something"')
208
+ expect(example.actual.result).to eql('nil')
209
+ expect(example.actual.output).to eql("something\n")
210
+ end
211
+
212
+ it 'handles STDERR' do
213
+ example = described_class.new('warn "something"')
214
+ expect(example.actual.result).to eql('nil')
215
+ expect(example.actual.output).to eql("something\n")
216
+ end
217
+
218
+ it 'handles exceptions' do
219
+ example = described_class.new('fail StandardError, "something"')
220
+ expect(example.actual.result).to eql('nil')
221
+ expect(example.actual.output).to eql("StandardError: something\n")
222
+ end
223
+
224
+ it 'memoizes the result' do
225
+ example = described_class.new('')
226
+ actual = example.actual
227
+ expect(example.actual).to be(actual)
228
+ end
229
+ end
230
+
231
+ describe '.pattern' do
232
+ it 'returns a Regexp' do
233
+ pattern = described_class.pattern('something')
234
+ expect(pattern).to be_a(Regexp)
235
+ end
236
+
237
+ it 'escapes meta characters' do
238
+ pattern = described_class.pattern('some.thing')
239
+ expect(pattern).to eql(/some\.thing/)
240
+ end
241
+
242
+ it 'replaces "..."' do
243
+ pattern = described_class.pattern('some...thing')
244
+ expect(pattern).to eql(/some.*?thing/)
245
+ end
246
+ end
247
+
248
+ describe '#valid_result?' do
249
+ it 'returns true without an expected result' do
250
+ example = described_class.new(nil, nil)
251
+ expect(example).to be_valid_result
252
+ end
253
+
254
+ it 'returns true when the results match' do
255
+ example = described_class.new('"something"', '"something"')
256
+ expect(example).to be_valid_result
257
+ end
258
+
259
+ it "returns false when the results don't match" do
260
+ example = described_class.new('"something"', '"something else"')
261
+ expect(example).to_not be_valid_result
262
+ end
263
+
264
+ it 'allows wildcards' do
265
+ example = described_class.new('Object.new', '#<Object:0x...>')
266
+ expect(example).to be_valid_result
267
+ end
268
+ end
269
+
270
+ describe '#valid_output?' do
271
+ it 'returns true without expected output' do
272
+ example = described_class.new(nil, nil)
273
+ expect(example).to be_valid_output
274
+ end
275
+
276
+ it 'returns true when the output matches' do
277
+ example = described_class.new('puts "something"', nil, 'something')
278
+ expect(example).to be_valid_output
279
+ end
280
+
281
+ it "returns false when the output doesn't match" do
282
+ example = described_class.new('puts "something"', nil, 'something else')
283
+ expect(example).to_not be_valid_output
284
+ end
285
+
286
+ it 'allows wildcards' do
287
+ example = described_class.new('puts Object.new', nil, '#<Object:0x...>')
288
+ expect(example).to be_valid_output
289
+ end
290
+ end
291
+
292
+ describe '#pass?' do
293
+ it 'realizes the actual outcome' do
294
+ example = described_class.new('x = 1')
295
+ example.pass?
296
+ expect(example.binding.eval('x')).to eql(1)
297
+ end
298
+
299
+ it 'returns true if both the result and output match' do
300
+ example = described_class
301
+ .new('p "something"', '"something"', '"something"')
302
+ expect(example).to be_pass
303
+ end
304
+
305
+ it "returns false if the result doesn't match" do
306
+ example = described_class
307
+ .new('p "something"', '"something else"', '"something"')
308
+ expect(example).to_not be_pass
309
+ end
310
+
311
+ it "returns false if the output doesn't match" do
312
+ example = described_class
313
+ .new('p "something"', '"something"', '"something else"')
314
+ expect(example).to_not be_pass
315
+ end
316
+ end
317
+
318
+ describe '#==' do
319
+ it 'returns true when they have the same source, result, and output' do
320
+ source = 'x'
321
+ result = 'y'
322
+ output = 'z'
323
+ a = described_class.new(source, result, output)
324
+ b = described_class.new(source, result, output)
325
+ expect(a).to eq(b)
326
+ end
327
+
328
+ it "returns false when they don't have the same source" do
329
+ result = 'y'
330
+ output = 'z'
331
+ a = described_class.new('a', result, output)
332
+ b = described_class.new('b', result, output)
333
+ expect(a).to_not eq(b)
334
+ end
335
+
336
+ it "returns false when they don't have the same result" do
337
+ source = 'x'
338
+ output = 'z'
339
+ a = described_class.new(source, 'a', output)
340
+ b = described_class.new(source, 'b', output)
341
+ expect(a).to_not eq(b)
342
+ end
343
+
344
+ it "returns false when they don't have the same output" do
345
+ source = 'x'
346
+ result = 'y'
347
+ a = described_class.new(source, result, 'a')
348
+ b = described_class.new(source, result, 'b')
349
+ expect(a).to_not eq(b)
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,53 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Erudite::Outcome do
6
+ it 'requires a result' do
7
+ expect { described_class.new }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ it 'requires some output' do
11
+ expect { described_class.new(nil) }.to raise_error(ArgumentError)
12
+ end
13
+
14
+ it 'can be initialized' do
15
+ expect(described_class.new(nil, nil)).to be_a(described_class)
16
+ end
17
+
18
+ it 'sets the result' do
19
+ result = double
20
+ outcome = described_class.new(result, nil)
21
+ expect(outcome.result).to eql(result)
22
+ end
23
+
24
+ it 'sets the output' do
25
+ output = double
26
+ outcome = described_class.new(nil, output)
27
+ expect(outcome.output).to eql(output)
28
+ end
29
+
30
+ describe '#==' do
31
+ it 'returns true if they have the same result and output' do
32
+ result = 'some'
33
+ output = 'thing'
34
+ a = described_class.new(result, output)
35
+ b = described_class.new(result, output)
36
+ expect(a).to eq(b)
37
+ end
38
+
39
+ it "returns false if they don't have the same result" do
40
+ output = 'something'
41
+ a = described_class.new('a', output)
42
+ b = described_class.new('b', output)
43
+ expect(a).to_not eq(b)
44
+ end
45
+
46
+ it "returns false if they don't have the same output" do
47
+ result = 'something'
48
+ a = described_class.new(result, 'a')
49
+ b = described_class.new(result, 'b')
50
+ expect(a).to_not eq(b)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,104 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ # Monkey patch String to add ability to strip leading whitespace.
6
+ class String
7
+ def dedent
8
+ gsub(/^#{self[/\A\s*/]}/, '')
9
+ end
10
+ end
11
+
12
+ describe Erudite::Parser do
13
+ describe '.parse' do
14
+ it 'parses an example without output or a result' do
15
+ examples = described_class.parse(<<-'RUBY'.dedent)
16
+ >> :something
17
+ RUBY
18
+ expect(examples).to eq([
19
+ Erudite::Example.new(':something')])
20
+ end
21
+
22
+ it 'parses an example with a result' do
23
+ examples = described_class.parse(<<-'RUBY'.dedent)
24
+ >> :something
25
+ => :something
26
+ RUBY
27
+ expect(examples).to eq([
28
+ Erudite::Example.new(':something', ':something')])
29
+ end
30
+
31
+ it 'parses an example with output' do
32
+ examples = described_class.parse(<<-'RUBY'.dedent)
33
+ >> puts :something
34
+ something
35
+ RUBY
36
+ expect(examples).to eq([
37
+ Erudite::Example.new('puts :something', nil, 'something')])
38
+ end
39
+
40
+ it 'handles STDIN' do
41
+ examples = described_class.parse(<<-'RUBY'.dedent)
42
+ >> gets
43
+ => nil
44
+ RUBY
45
+ expect(examples).to eq([
46
+ Erudite::Example.new('gets', 'nil')])
47
+ end
48
+
49
+ it 'handles STDOUT' do
50
+ examples = described_class.parse(<<-'RUBY'.dedent)
51
+ >> puts :something
52
+ something
53
+ => nil
54
+ RUBY
55
+ expect(examples).to eq([
56
+ Erudite::Example.new('puts :something', 'nil', 'something')])
57
+ end
58
+
59
+ it 'handles STDERR' do
60
+ examples = described_class.parse(<<-'RUBY'.dedent)
61
+ >> warn :something
62
+ something
63
+ => nil
64
+ RUBY
65
+ expect(examples).to eq([
66
+ Erudite::Example.new('warn :something', 'nil', 'something')])
67
+ end
68
+
69
+ it 'handles exceptions' do
70
+ examples = described_class.parse(<<-'RUBY'.dedent)
71
+ >> fail 'something'
72
+ RuntimeError: something
73
+ RUBY
74
+ expect(examples).to eq([
75
+ Erudite::Example.new(
76
+ "fail 'something'", nil, 'RuntimeError: something')])
77
+ end
78
+
79
+ it 'handles multi-line source and output' do
80
+ examples = described_class.parse(<<-'RUBY'.dedent)
81
+ >> puts 'some
82
+ .. thing'
83
+ some
84
+ thing
85
+ => nil
86
+ RUBY
87
+ expect(examples).to eq([
88
+ Erudite::Example.new("puts 'some\nthing'", 'nil', "some\nthing")])
89
+ end
90
+
91
+ it 'handles multiple examples' do
92
+ examples = described_class.parse(<<-'RUBY'.dedent)
93
+ >> def some
94
+ .. :thing
95
+ .. end
96
+ >> some
97
+ => :thing
98
+ RUBY
99
+ expect(examples).to eq([
100
+ Erudite::Example.new("def some\n :thing\nend"),
101
+ Erudite::Example.new('some', ':thing')])
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Erudite do
6
+ pending
7
+ end
@@ -0,0 +1,3 @@
1
+ # coding: utf-8
2
+
3
+ require 'erudite'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erudite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Taylor Fausak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 10.3.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 10.3.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.25.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.25.0
55
+ description: Executable documentation.
56
+ email: taylor@fausak.me
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - CHANGELOG.md
62
+ - CONTRIBUTING.md
63
+ - LICENSE.md
64
+ - README.md
65
+ - lib/erudite.rb
66
+ - lib/erudite/example.rb
67
+ - lib/erudite/outcome.rb
68
+ - lib/erudite/parser.rb
69
+ - spec/erudite/example_spec.rb
70
+ - spec/erudite/outcome_spec.rb
71
+ - spec/erudite/parser_spec.rb
72
+ - spec/erudite_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: https://github.com/tfausak/erudite
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: 1.9.3
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.4.1
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Executable documentation.
98
+ test_files:
99
+ - spec/erudite/example_spec.rb
100
+ - spec/erudite/outcome_spec.rb
101
+ - spec/erudite/parser_spec.rb
102
+ - spec/erudite_spec.rb
103
+ - spec/spec_helper.rb