orb 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/TODO +4 -0
- data/lib/orb.rb +4 -154
- data/lib/orb/drivers/test-unit.rb +26 -0
- data/lib/orb/pry_extensions.rb +48 -0
- data/lib/orb/runner.rb +35 -0
- data/lib/orb/test_buffer.rb +39 -0
- data/lib/orb/version.rb +3 -0
- data/orb.gemspec +17 -14
- metadata +60 -47
- data/LICENSE +0 -19
- data/README.md +0 -33
- data/lib/orb/adapters/rspec.rb +0 -40
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/TODO
ADDED
data/lib/orb.rb
CHANGED
@@ -1,154 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# It's not uncommon to run some code in IRB, then copy parts of it almost
|
6
|
-
# verbatim into a test file for use as a test. ORB makes this a much more smooth
|
7
|
-
# process.
|
8
|
-
|
9
|
-
# The basic workflow with ORB is:
|
10
|
-
|
11
|
-
# 1. Add `ORB{}` to each new test, at the point where you'd like to insert code.
|
12
|
-
# 2. Run your test suite with `orb` loaded. See `adapters/rspec.rb`.
|
13
|
-
# 3. Use the REPL provided for each call to ORB to create a new test.
|
14
|
-
|
15
|
-
# When a call to `ORB` is encountered, you'll be dropped to to a REPL with full
|
16
|
-
# access to the test's context (much like a debugger). You can run code, and
|
17
|
-
# interact with the context however you like. When you're ready to write your
|
18
|
-
# test, you simply run the commands, then add them to a buffer. Once your
|
19
|
-
# buffer contains the code you'd like to save as a test, you can write
|
20
|
-
# it back to the file in place of the call to `ORB` with just two keystrokes.
|
21
|
-
|
22
|
-
# The REPL uses readline for line editing.
|
23
|
-
require 'readline'
|
24
|
-
|
25
|
-
# Adapters are near-trivial to write, and provide test-framework integration.
|
26
|
-
require 'orb/adapters/rspec'
|
27
|
-
|
28
|
-
class ORB
|
29
|
-
@@index=0
|
30
|
-
|
31
|
-
# Once ORB is called, the user is presented with a minimal IRB-like REPL,
|
32
|
-
# where they can evaluate arbitrary ruby code or execute a set of built-in
|
33
|
-
# commands to build up a test and save it back to the test file.
|
34
|
-
def orb_it_up
|
35
|
-
while line = Readline.readline(prompt, true)
|
36
|
-
case line
|
37
|
-
|
38
|
-
# The `a` command appends one or more recent lines to the test buffer.
|
39
|
-
when /^a\s?(\d*)$/
|
40
|
-
append_to_buffer($1.to_i)
|
41
|
-
next
|
42
|
-
|
43
|
-
# The `h` command shows this session's history. Each line starts with
|
44
|
-
# a coloured space. A red space indicates that this line is not in
|
45
|
-
# the buffer, and a green space indicates that this line is in the
|
46
|
-
# buffer, and will be written back to the file when the test is saved.
|
47
|
-
when "h"
|
48
|
-
red = "\x1B[41m \x1B[m"
|
49
|
-
green = "\x1B[42m \x1B[m"
|
50
|
-
@hist.each do |line, in_buf|
|
51
|
-
print in_buf ? green : red
|
52
|
-
print ' '
|
53
|
-
puts line
|
54
|
-
end
|
55
|
-
next
|
56
|
-
|
57
|
-
# The `p` command prints the current contents of the buffer. If the test
|
58
|
-
# is written back to the file right now, this is what will be inserted.
|
59
|
-
when "p"
|
60
|
-
puts @buf
|
61
|
-
next
|
62
|
-
|
63
|
-
# The `q` command exits this session without writing a test. Next time
|
64
|
-
# the suite is run, you'll get a REPL here again.
|
65
|
-
when "q"
|
66
|
-
break
|
67
|
-
|
68
|
-
# The `s` command writes the contents of the buffer out to the file.
|
69
|
-
when "s"
|
70
|
-
write_buf_to_file
|
71
|
-
break
|
72
|
-
|
73
|
-
# If this line wasn't a command, evaluate it in the context of the code
|
74
|
-
# that called `ORB{}`. We're stealing that context from the block.
|
75
|
-
# There are other, trickier tricks to get it without requiring a block,
|
76
|
-
# but they haven't been reliable since ruby 1.8.5.
|
77
|
-
else
|
78
|
-
@hist << [line,false]
|
79
|
-
begin
|
80
|
-
this = @binding.eval("self")
|
81
|
-
ret = this.send(:eval, line, @binding)
|
82
|
-
rescue => e
|
83
|
-
puts e.message
|
84
|
-
else
|
85
|
-
puts ret.inspect
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# It's up to the adapters to figure out the context we need to evaluate code
|
93
|
-
# in. Typically, they'll grab it from an empty block. Adapters call this
|
94
|
-
# intializer with a `Binding`, and we set a few instance variables for the
|
95
|
-
# REPL to use. Notably, `@line` and `@file` are the location of the call
|
96
|
-
# to ORB, where we should insert our code when the test is written out.
|
97
|
-
def initialize(bind)
|
98
|
-
@@index += 1
|
99
|
-
@binding = bind
|
100
|
-
@buf, @hist = [], []
|
101
|
-
@line, @file = bind.eval("[__LINE__, __FILE__]")
|
102
|
-
|
103
|
-
# This is normally used for the test's description. It's not a strict
|
104
|
-
# requirement of an adapter, but will be set and shown if present.
|
105
|
-
@header = ORB::Adapter.header(bind) if ORB::Adapter.respond_to?(:header)
|
106
|
-
puts "\n\n[[ #{@header} ]]" if @header
|
107
|
-
|
108
|
-
# Gentlemen, start your REPLs.
|
109
|
-
orb_it_up
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
# Append some number of recent lines to the test buffer. This is triggered
|
115
|
-
# by the command `a` or `a <n>`, eg. `a 3`. If called with no number, just
|
116
|
-
# appends the last command run, otherwise, appends n lines.
|
117
|
-
def append_to_buffer(n=1)
|
118
|
-
@hist.last[1] = true
|
119
|
-
@buf << @hist.last[0]
|
120
|
-
end
|
121
|
-
|
122
|
-
# When this command is run, ORB will save the contents of the test buffer
|
123
|
-
# back into the file where `ORB{}` was called from. It does this by reading
|
124
|
-
# in the entire file, then rewriting it with ORB{} replaced by the buffer.
|
125
|
-
def write_buf_to_file
|
126
|
-
lines = File.read(@file).lines.to_a
|
127
|
-
|
128
|
-
File.open(@file,"w") do |f|
|
129
|
-
f.puts lines[0...@line-1]
|
130
|
-
|
131
|
-
orbline = lines[@line-1]
|
132
|
-
indentation = orbline.index(/[^\s]/)
|
133
|
-
|
134
|
-
# Here we're indenting the inserted code to the same level as `ORB{}`
|
135
|
-
# was indented.
|
136
|
-
@buf.each do |bufline|
|
137
|
-
f.print " "*indentation
|
138
|
-
f.puts bufline
|
139
|
-
end
|
140
|
-
|
141
|
-
f.puts lines[@line..-1]
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# ORB's prompt looks like `1:0 >>`. The first number is the index of this
|
146
|
-
# test, starting at one, and incrementing with each test during an
|
147
|
-
# ORB-enhanced run of your test suite. The second number is the current size
|
148
|
-
# of the test buffer; that is, the number of lines that will be written to
|
149
|
-
# the file if the test is saved right now.
|
150
|
-
def prompt
|
151
|
-
"#{@@index}:#{@buf.size} >> "
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
1
|
+
require 'orb/test_buffer'
|
2
|
+
require 'orb/pry_extensions'
|
3
|
+
require 'orb/drivers/test-unit'
|
4
|
+
require 'orb/runner'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/unit/testcase'
|
2
|
+
|
3
|
+
class Test::Unit::TestCase
|
4
|
+
def self.orb!
|
5
|
+
define_method("test_orb_#{rand 100000}") { orb!(self) }
|
6
|
+
end
|
7
|
+
|
8
|
+
def orb!(ctx)
|
9
|
+
with_immediate_asserts(ctx) { Orb::Runner.new(ctx).run }
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_immediate_asserts(ctx)
|
13
|
+
class << self
|
14
|
+
alias_method :_original_wrap_assertion, :_wrap_assertion
|
15
|
+
def _wrap_assertion ; yield ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
yield
|
19
|
+
|
20
|
+
class << self
|
21
|
+
alias_method :_wrap_assertion, :_original_wrap_assertion
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
Pry.config.prompt = proc { |_, _, pry| "orb[#{pry.instance_variable_get("@orb_test_buffer")}]> " }
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
attr_accessor :orb_test_buffer
|
7
|
+
|
8
|
+
module Helpers::CommandHelpers
|
9
|
+
def orb_test_buffer
|
10
|
+
_pry_.instance_variable_get("@orb_test_buffer")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Orb
|
16
|
+
Commands = Pry::CommandSet.new do
|
17
|
+
command ",a", "Append the previous line to the buffer" do |*code|
|
18
|
+
if code.empty?
|
19
|
+
orb_test_buffer << _pry_.input_array[-1].chomp
|
20
|
+
else
|
21
|
+
orb_test_buffer << code.join(" ")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
command ",p", "Print contents of buffer" do
|
26
|
+
puts orb_test_buffer
|
27
|
+
end
|
28
|
+
|
29
|
+
command ",e", "Edit contents of buffer" do
|
30
|
+
orb_test_buffer.edit_contents!
|
31
|
+
end
|
32
|
+
|
33
|
+
command ",n", "Name or rename the current test" do |*name|
|
34
|
+
orb_test_buffer.name = name.join(" ")
|
35
|
+
end
|
36
|
+
|
37
|
+
command ",r", "Run contents of buffer" do
|
38
|
+
orb_test_buffer.run
|
39
|
+
end
|
40
|
+
|
41
|
+
command ",w", "Write the buffer to file" do
|
42
|
+
orb_test_buffer.write
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Pry.config.commands.import Orb::Commands
|
48
|
+
|
data/lib/orb/runner.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
module Orb
|
4
|
+
class Runner
|
5
|
+
attr_reader :test_buffer
|
6
|
+
class << self
|
7
|
+
attr_accessor :current
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(context)
|
11
|
+
@context = context
|
12
|
+
@test_buffer = TestBuffer.new
|
13
|
+
setup_pry
|
14
|
+
Orb::Runner.current = self
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_pry
|
18
|
+
Pry.instance_eval do
|
19
|
+
if initial_session?
|
20
|
+
load_rc if Pry.config.should_load_rc
|
21
|
+
# load_plugins if Pry.config.plugins.enabled
|
22
|
+
load_requires if Pry.config.should_load_requires
|
23
|
+
load_history if Pry.config.history.should_load
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@pry = Pry.new
|
27
|
+
@pry.instance_variable_set("@orb_test_buffer", @test_buffer)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
@pry.repl(@context)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
class TestBuffer < Array
|
4
|
+
attr_accessor :name
|
5
|
+
|
6
|
+
def edit_contents!
|
7
|
+
path = "#{Dir::tmpdir}/orb-#{Kernel.rand 1000000}.rb"
|
8
|
+
begin
|
9
|
+
File.open(path, "w") do |f|
|
10
|
+
f.write(join('\n'))
|
11
|
+
f.flush
|
12
|
+
system("#{ENV['EDITOR'] || '/usr/bin/vim'} #{f.path}")
|
13
|
+
replace(File.read(f.path).lines.map(&:chomp))
|
14
|
+
end
|
15
|
+
ensure
|
16
|
+
File.unlink(path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
each do |line|
|
22
|
+
eval(line)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def write
|
27
|
+
str = "".tap do |test|
|
28
|
+
test << "test \"#{name}\" do\n"
|
29
|
+
each do |line|
|
30
|
+
test << " " << line << "\n"
|
31
|
+
end
|
32
|
+
test << "end\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
puts str
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
data/lib/orb/version.rb
ADDED
data/orb.gemspec
CHANGED
@@ -1,18 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "orb/version"
|
4
4
|
|
5
|
-
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "orb"
|
7
|
+
s.version = Orb::VERSION
|
8
|
+
s.authors = ["Burke Libbey"]
|
9
|
+
s.email = ["burke.libbey@shopify.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{REPL-driven testing for ruby}
|
12
|
+
s.description = %q{REPL-driven testing for ruby -- integrates with pry and lets you build tests incrementally in the REPL}
|
6
13
|
|
7
|
-
|
8
|
-
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
9
18
|
|
10
|
-
|
11
|
-
|
12
|
-
gem.files = %w[
|
13
|
-
LICENSE
|
14
|
-
README.md
|
15
|
-
lib
|
16
|
-
orb.gemspec
|
17
|
-
] + Dir["**/*.rb"]
|
19
|
+
s.add_runtime_dependency 'pry', '0.9.8.2'
|
20
|
+
s.add_runtime_dependency 'test-unit'
|
18
21
|
end
|
metadata
CHANGED
@@ -1,66 +1,79 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: orb
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 6
|
9
|
-
version: 0.0.6
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Burke Libbey
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
date: 2012-02-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: pry
|
16
|
+
requirement: &70298440802600 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - =
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.8.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70298440802600
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: test-unit
|
27
|
+
requirement: &70298440801600 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70298440801600
|
36
|
+
description: REPL-driven testing for ruby -- integrates with pry and lets you build
|
37
|
+
tests incrementally in the REPL
|
38
|
+
email:
|
39
|
+
- burke.libbey@shopify.com
|
23
40
|
executables: []
|
24
|
-
|
25
41
|
extensions: []
|
26
|
-
|
27
42
|
extra_rdoc_files: []
|
28
|
-
|
29
|
-
|
30
|
-
-
|
31
|
-
-
|
32
|
-
-
|
33
|
-
- lib/orb/adapters/rspec.rb
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- Rakefile
|
47
|
+
- TODO
|
34
48
|
- lib/orb.rb
|
35
|
-
|
36
|
-
|
49
|
+
- lib/orb/drivers/test-unit.rb
|
50
|
+
- lib/orb/pry_extensions.rb
|
51
|
+
- lib/orb/runner.rb
|
52
|
+
- lib/orb/test_buffer.rb
|
53
|
+
- lib/orb/version.rb
|
54
|
+
- orb.gemspec
|
55
|
+
homepage: ''
|
37
56
|
licenses: []
|
38
|
-
|
39
57
|
post_install_message:
|
40
58
|
rdoc_options: []
|
41
|
-
|
42
|
-
require_paths:
|
59
|
+
require_paths:
|
43
60
|
- lib
|
44
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
requirements:
|
53
|
-
- -
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
|
56
|
-
- 0
|
57
|
-
version: "0"
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
58
73
|
requirements: []
|
59
|
-
|
60
74
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.
|
75
|
+
rubygems_version: 1.8.11
|
62
76
|
signing_key:
|
63
77
|
specification_version: 3
|
64
|
-
summary:
|
78
|
+
summary: REPL-driven testing for ruby
|
65
79
|
test_files: []
|
66
|
-
|
data/LICENSE
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
Copyright (c) 2010 Burke Libbey <burke@burkelibbey.org>
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
of this software and associated documentation files (the "Software"), to deal
|
5
|
-
in the Software without restriction, including without limitation the rights
|
6
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
copies of the Software, and to permit persons to whom the Software is
|
8
|
-
furnished to do so, subject to the following conditions:
|
9
|
-
|
10
|
-
The above copyright notice and this permission notice shall be included in
|
11
|
-
all 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,
|
15
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
THE SOFTWARE.
|
data/README.md
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# ORB
|
2
|
-
|
3
|
-
# What is it?
|
4
|
-
|
5
|
-
ORB is a tool to write tests interactively. Add `ORB{}` to one of your
|
6
|
-
tests, then when you run your test suite, you'll get dropped to a
|
7
|
-
REPL, where you can explore the test's context and build an
|
8
|
-
implementation for the test, before automatically writing it out to
|
9
|
-
the file and replacing the `ORB{}` call.
|
10
|
-
|
11
|
-
# Wait... What?
|
12
|
-
|
13
|
-
[Watch the video](#) (Coming Soon).
|
14
|
-
|
15
|
-
# I just want to use it with Rspec. How?
|
16
|
-
|
17
|
-
Add `ORB{}` to a pending example, then run your spec suite with
|
18
|
-
`-r orb`, for example, `spec -rorb spec/**/*_spec.rb`, or add it to `spec_opts`.
|
19
|
-
|
20
|
-
# Can I use this with \#{framework}?
|
21
|
-
|
22
|
-
Probably. Have a look at `lib/orb/adapters/rspec.rb`. It's a pretty simple
|
23
|
-
format.
|
24
|
-
|
25
|
-
# Why do I have to call ORB with an empty block?
|
26
|
-
|
27
|
-
Ruby 1.8.6 and onward doesn't have a reliable way to evaluate code in
|
28
|
-
the context that calls a method without explicitly passing it, or
|
29
|
-
grabbing the binding from a block. The block is easier to type.
|
30
|
-
|
31
|
-
# I have a great idea...
|
32
|
-
|
33
|
-
Great! Let me know, or even better, send me a pull request.
|
data/lib/orb/adapters/rspec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
### ORB RSpec Adapter
|
2
|
-
# This integrates ORB with RSpec. To run your test suite with ORB enabled,
|
3
|
-
# run `spec` with `-rorb`, or add `-rorb` to `spec_opts`, or simply
|
4
|
-
# `require 'orb'` in your `spec_helper.rb`.
|
5
|
-
|
6
|
-
# ORB's requirements of an adapter are minimal:
|
7
|
-
|
8
|
-
# - (optional) Some convenient way to start an ORB session.
|
9
|
-
# - (optional) A header describing this specific instance.
|
10
|
-
# Each RSpec example has a description that's printed when it fails.
|
11
|
-
# We re-create that here to provide context when an ORB session is started.
|
12
|
-
class ORB
|
13
|
-
module Adapters
|
14
|
-
module RSpec
|
15
|
-
def self.header(bind)
|
16
|
-
this = bind.eval("self")
|
17
|
-
ancestry = [this.class, this]
|
18
|
-
ancestry.map(&:description).join(" ")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Initially, I wanted to override `pending` as the method to start ORB,
|
25
|
-
# but as it turns out, the Object hackery I need to do to make ORB work
|
26
|
-
# requires a block. Requiring that pending be called with a block seems like
|
27
|
-
# an odd design choice, so instead I've made the method ORB,
|
28
|
-
# called like `ORB{}`.
|
29
|
-
module Spec
|
30
|
-
module Example
|
31
|
-
module Pending
|
32
|
-
def ORB(&block)
|
33
|
-
ORB.new(block.binding)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Finally, now that the RSpec Adapter is defined, set ORB's default Adapter.
|
40
|
-
ORB::Adapter = ORB::Adapters::RSpec
|