Update to RDoc 2.1.0 r112
[rbx.git] / mspec / README
blob5400b0834d45cb8a0365e30b6e2f062b1d8fae29
1 = Overview
3 MSpec is a specialized framework that is syntax-compatible with RSpec for
4 basic things like +describe+, +it+ blocks and +before+, +after+ actions. MSpec
5 contains additional features that assist in writing the RubySpecs used by
6 multiple Ruby implementations.
8 MSpec attempts to use the simplest Ruby language features so that beginning
9 Ruby implementations can run the Ruby specs. So, for example, there is not
10 great concern given to constant clashes. Namespacing (or module scoping) is
11 not used because implementing this correctly took a significant amount of work
12 in Rubinius and it is likely that other implementations would also face
13 difficulties.
15 MSpec is not intended as a replacement for RSpec. MSpec attempts to provide a
16 subset of RSpec's features in some cases and a superset in others. It does not
17 provide all the matchers, for instance. However, MSpec provides several
18 extensions to facilitate writing the Ruby specs in a manner compatible with
19 multiple Ruby implementations.
21 First, MSpec offers a set of guards to control execution of the specs. These
22 guards not only enable or disable execution but also annotate the specs with
23 additional information about why they are run or not run. Second, MSpec
24 provides a different shared spec implementation specifically designed to ease
25 writing specs for the numerous aliased methods in Ruby. The MSpec shared spec
26 implementation should not conflict with RSpec's own shared behavior facility.
27 Third, MSpec provides various helper methods to simplify some specs, for
28 example, creating temporary file names. Finally, MSpec has several specialized
29 runner scripts that includes a configuration facility with a default project
30 file and user-specific overrides.
32 Caveats:
34 * Use RSpec to run the MSpec specs. There are no plans currently to make
35   the MSpec specs runnable by MSpec.
36 * Don't mock the #hash method as MSpec's Mock implementation uses Hash
37   internally. This can be replaced if necessary, but at this point there is no
38   compelling need to do so.
41 == Architecture
44 == Matchers
46 Matchers are additional aids for the verification process. The default
47 is of course to #should or #should_not using the #== operator and its
48 friends but the matchers add a new set of 'operators' to help in the
49 task. They reside in `mspec/matchers/`. There are two broad categories,
50 those that apply to an individual object and those that apply to a
51 block:
53 === Object
55 - `base` implements the standard #==, #< #<= #>= #> and #=~ with their
56   normal semantics for the objects that you invoke them on.
58 - `be_ancestor_of` is equivalent to checking `obj.ancestors.include?`.
60 - `be_close` is a "delta" for floating-point math. Due to the very
61   nature of it, floating-point comparisons should never be treated as
62   exact. By default the tolerance is 0.00003 but it can be altered if
63   so desired. So `0.23154.should be_close(0.23157)` would succeed
64   (which is usually close enough for floating point unless you are
65   doing some scientific computing.)
67 - `be_empty` checks `obj.empty?`
69 - `be_kind_of` is equivalent to `obj.kind_of?`
71 - `include` is `obj.include?`
73 === Block
75 All of these should be applied to a block created with `lambda` or `proc`:
77 - `complain` is probably clearer stated as `lambda {...}.should complain`;
78   it checks that the block issues a warning. The message can be checked
79   against either a String or a Regexp.
81 - `output` checks that the block produces the given output (stdout as well
82   as stderr, in that order) matched either to a String or a Regexp. This one
83   uses overrides so if that is a problem (for e.g. speccing Readline or
84   something) see below.
86 - `output_to_fd` is a lower-level version and actually verifies that output
87   to a certain file descriptor is correct whether from an in-/output stream
88   or an actual file. Also can check with either a String or a Regexp.
90 - `raise_error` verifies the exception type (if any) raised by the block it
91   is associated with. The exception class can be given for finer-grained
92   control (inheritance works normally so Exception would catch everything.)
94 == Nested 'describe' blocks
96 MSpec supports nesting one 'describe' block inside another. The examples in
97 the nested block are evaluated with all the before/after blocks of all the
98 containing 'describe' blocks. The following example illustrates this:
100 describe "Some#method" do
101   before :each do
102     @obj = 1
103   end
105   describe "when passed String" do
106     before :each do
107       @meth = :to_s
108     end
110     it "returns false" do
111       # when this example is evaluated, @obj = 1 and @meth = :to_s
112     end
113   end
116 The output when using the SpecdocFormatter (selected with -fs to the runners)
117 will be as follows:
119 Some#method when passed String
120 - returns false
123 == Shared 'describe' blocks
125 MSpec supports RSpec-style shared 'describe' blocks. MSpec also provides a
126 convenience method to assist in writing specs for the numerous aliased methods
127 that Ruby provides. The following example illustrates shared blocks:
129 describe :someclass_some_method, :shared => true do
130   it "does something" do
131   end
134 describe "SomeClass#some_method" do
135   it_should_behave_like "someclass_some_method"
138 The first argument to 'describe' for a shared block is an object that
139 duck-types as a String. The representation of the object must be unique. This
140 example uses a symbol. This was the convention for the previous facility that
141 MSpec provided for aliased method (#it_behaves_like). However, this convention
142 is not set in stone (but the uniqueness requirement is). Note that the
143 argument to the #it_should_behave_like is a String because at this time RSpec
144 will not find the shared block by the symbol.
146 MSpec continues to support the #it_behaves_like convenience method for
147 specifying aliased methods. The syntax is as follows:
149 it_behaves_like :symbol_matching_shared_describe, :method [, :object]
151 describe :someclass_some_method, :shared => true do
152   it "returns true" do
153     obj.send(@method).should be_true
154   end
156   it "returns something else" do
157     @object.send(@method).should be_something_else
158   end
161 # example #1
162 describe "SomeClass#some_method" do
163   it_behaves_like :someclass_some_method, :other_method
166 # example #2
167 describe "SomeOtherClass#some_method" do
168   it_behaves_like :someclass_some_method, :some_method, OtherClass
171 The first form above (#1) is used for typical aliases. That is, methods with
172 different names on the same class that behave identically. The
173 #it_behaves_like helper creates a before(:all) block that sets @method to
174 :other_method. The form of the first example block in the shared block
175 illustrates the typical form of a spec for an aliased method.
177 The second form above (#2) is used for methods on different classes that are
178 essentially aliases, even though Ruby does not provide a syntax for specifying
179 such methods as aliases. Examples are the methods on File, FileTest, and
180 File::Stat. In this case, the #it_behaves_like helper sets both @method and
181 @object in the before(:all) block (@method = :some_method, @object =
182 OtherClass in this example).
184 For shared specs that fall outside of either of these two narrow categories,
185 use nested or shared 'describe' blocks as appropriate and use the
186 #it_should_behave_like method directly.
188 == Guards
191 == Helpers
194 == Runners