mspec 1.5.6 → 1.5.7

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/Rakefile CHANGED
@@ -18,7 +18,7 @@ spec = Gem::Specification.new do |s|
18
18
 
19
19
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
20
20
  s.authors = ["Brian Ford"]
21
- s.date = %q{2008-12-29}
21
+ s.date = %q{2009-2-5}
22
22
  s.email = %q{bford@engineyard.com}
23
23
  s.has_rdoc = true
24
24
  s.extra_rdoc_files = %w[ README LICENSE ]
@@ -41,6 +41,9 @@ class MSpecCI < MSpecScript
41
41
  options.version MSpec::VERSION
42
42
  options.help
43
43
 
44
+ options.doc "\n Custom options"
45
+ custom_options options
46
+
44
47
  options.doc "\n How might this work in the real world?"
45
48
  options.doc "\n 1. To simply run the known good specs"
46
49
  options.doc "\n $ mspec ci"
@@ -53,6 +53,9 @@ class MSpecRun < MSpecScript
53
53
  options.version MSpec::VERSION
54
54
  options.help
55
55
 
56
+ options.doc "\n Custom options"
57
+ custom_options options
58
+
56
59
  options.doc "\n How might this work in the real world?"
57
60
  options.doc "\n 1. To simply run some specs"
58
61
  options.doc "\n $ mspec path/to/the/specs"
@@ -75,6 +75,9 @@ class MSpecTag < MSpecScript
75
75
  options.version MSpec::VERSION
76
76
  options.help
77
77
 
78
+ options.doc "\n Custom options"
79
+ custom_options options
80
+
78
81
  options.doc "\n How might this work in the real world?"
79
82
  options.doc "\n 1. To add the 'fails' tag to failing specs"
80
83
  options.doc "\n $ mspec tag path/to/the_file_spec.rb"
@@ -24,9 +24,9 @@ class MSpecMain < MSpecScript
24
24
 
25
25
  options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config
26
26
 
27
- options.doc " The mspec command sets up and invokes the sub-commands"
28
- options.doc " (see below) to enable, for instance, running the specs"
29
- options.doc " with different implementations like ruby, jruby, rbx, etc.\n"
27
+ options.doc " The mspec command sets up and invokes the sub-commands"
28
+ options.doc " (see below) to enable, for instance, running the specs"
29
+ options.doc " with different implementations like ruby, jruby, rbx, etc.\n"
30
30
 
31
31
  options.configure do |f|
32
32
  load f
@@ -66,12 +66,15 @@ class MSpecMain < MSpecScript
66
66
  end
67
67
  end
68
68
 
69
+ options.doc "\n Custom options"
70
+ custom_options options
71
+
69
72
  # The rest of the help output
70
- options.doc "\n where COMMAND is one of:\n"
71
- options.doc " run - Run the specified specs (default)"
72
- options.doc " ci - Run the known good specs"
73
- options.doc " tag - Add or remove tags\n"
74
- options.doc " mspec COMMAND -h for more options\n"
73
+ options.doc "\n where COMMAND is one of:\n"
74
+ options.doc " run - Run the specified specs (default)"
75
+ options.doc " ci - Run the known good specs"
76
+ options.doc " tag - Add or remove tags\n"
77
+ options.doc " mspec COMMAND -h for more options\n"
75
78
 
76
79
  options.on_extra { |o| config[:options] << o }
77
80
  config[:options].concat options.parse(argv)
@@ -11,6 +11,8 @@ require 'mspec/matchers/eql'
11
11
  require 'mspec/matchers/equal'
12
12
  require 'mspec/matchers/equal_element'
13
13
  require 'mspec/matchers/equal_utf16'
14
+ require 'mspec/matchers/have_instance_method'
15
+ require 'mspec/matchers/have_private_instance_method'
14
16
  require 'mspec/matchers/include'
15
17
  require 'mspec/matchers/match_yaml'
16
18
  require 'mspec/matchers/raise_error'
@@ -0,0 +1,30 @@
1
+ require 'mspec/utils/version'
2
+
3
+ class HaveInstanceMethodMatcher
4
+ def initialize(method, include_super=true)
5
+ @include_super = include_super
6
+ version = SpecVersion.new(RUBY_VERSION) <=> "1.9"
7
+ @method = version < 0 ? method.to_s : method
8
+ end
9
+
10
+ def matches?(mod)
11
+ @mod = mod
12
+ mod.instance_methods(@include_super).include? @method
13
+ end
14
+
15
+ def failure_message
16
+ ["Expected #{@mod} to have private method '#{@method.to_s}'",
17
+ "but it does not"]
18
+ end
19
+
20
+ def negative_failure_message
21
+ ["Expected #{@mod} NOT to have private method '#{@method.to_s}'",
22
+ "but it does"]
23
+ end
24
+ end
25
+
26
+ class Object
27
+ def have_instance_method(method, include_super=true)
28
+ HaveInstanceMethodMatcher.new method, include_super
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'mspec/utils/version'
2
+
3
+ class HavePrivateInstanceMethodMatcher
4
+ def initialize(method, include_super=true)
5
+ @include_super = include_super
6
+ version = SpecVersion.new(RUBY_VERSION) <=> "1.9"
7
+ @method = version < 0 ? method.to_s : method
8
+ end
9
+
10
+ def matches?(mod)
11
+ @mod = mod
12
+ mod.private_instance_methods(@include_super).include? @method
13
+ end
14
+
15
+ def failure_message
16
+ ["Expected #{@mod} to have private method '#{@method.to_s}'",
17
+ "but it does not"]
18
+ end
19
+
20
+ def negative_failure_message
21
+ ["Expected #{@mod} NOT to have private method '#{@method.to_s}'",
22
+ "but it does"]
23
+ end
24
+ end
25
+
26
+ class Object
27
+ def have_private_instance_method(method, include_super=true)
28
+ HavePrivateInstanceMethodMatcher.new method, include_super
29
+ end
30
+ end
data/lib/mspec/runner.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'mspec/mocks'
2
2
  require 'mspec/runner/mspec'
3
+ require 'mspec/runner/context'
4
+ require 'mspec/runner/example'
3
5
  require 'mspec/runner/object'
4
6
  require 'mspec/runner/formatters'
5
7
  require 'mspec/runner/actions'
@@ -25,15 +25,32 @@ class Tally
25
25
  @errors += add
26
26
  end
27
27
 
28
+ def file
29
+ pluralize files, "file"
30
+ end
31
+
32
+ def example
33
+ pluralize examples, "example"
34
+ end
35
+
36
+ def expectation
37
+ pluralize expectations, "expectation"
38
+ end
39
+
40
+ def failure
41
+ pluralize failures, "failure"
42
+ end
43
+
44
+ def error
45
+ pluralize errors, "error"
46
+ end
47
+
28
48
  def format
29
- [ [@files, 'file'],
30
- [@examples, 'example'],
31
- [@expectations, 'expectation'],
32
- [@failures, 'failure'],
33
- [@errors, 'error']
34
- ].map { |count, word| pluralize count, word }.join(", ")
49
+ [ file, example, expectation, failure, error ].join(", ")
35
50
  end
36
51
 
52
+ alias_method :to_s, :format
53
+
37
54
  def pluralize(count, singular)
38
55
  "#{count} #{singular}#{'s' unless count == 1}"
39
56
  end
@@ -1,6 +1,3 @@
1
- require 'mspec/runner/mspec'
2
- require 'mspec/runner/example'
3
-
4
1
  # Holds the state of the +describe+ block that is being
5
2
  # evaluated. Every example (i.e. +it+ block) is evaluated
6
3
  # in a context, which may include state set up in <tt>before
@@ -1,3 +1,4 @@
1
+ require 'mspec/runner/formatters/describe'
1
2
  require 'mspec/runner/formatters/dotted'
2
3
  require 'mspec/runner/formatters/file'
3
4
  require 'mspec/runner/formatters/specdoc'
@@ -0,0 +1,24 @@
1
+ require 'mspec/runner/formatters/dotted'
2
+ require 'mspec/runner/actions/tally'
3
+
4
+ class DescribeFormatter < DottedFormatter
5
+ # Callback for the MSpec :finish event. Prints a summary of
6
+ # the number of errors and failures for each +describe+ block.
7
+ def finish
8
+ describes = Hash.new { |h,k| h[k] = Tally.new }
9
+
10
+ @exceptions.each do |exc|
11
+ desc = describes[exc.describe]
12
+ exc.failure? ? desc.failures! : desc.errors!
13
+ end
14
+
15
+ print "\n"
16
+ describes.each do |d, t|
17
+ text = d.size > 40 ? "#{d[0,37]}..." : d.ljust(40)
18
+ print "\n#{text} #{t.failure}, #{t.error}"
19
+ end
20
+ print "\n" unless describes.empty?
21
+
22
+ print "\n#{@timer.format}\n\n#{@tally.format}\n"
23
+ end
24
+ end
@@ -293,7 +293,7 @@ module MSpec
293
293
  # file if it is empty.
294
294
  def self.delete_tag(tag)
295
295
  deleted = false
296
- pattern = /#{tag.tag}.*#{Regexp.escape tag.description}/
296
+ pattern = /#{tag.tag}.*#{Regexp.escape(tag.escape(tag.description))}/
297
297
  file = tags_file
298
298
  if File.exist? file
299
299
  lines = IO.readlines(file)
@@ -6,12 +6,24 @@ class SpecTag
6
6
  end
7
7
 
8
8
  def parse(string)
9
- m = /^([^()#:]+)(\(([^)]+)?\))?:(.*)/.match string
10
- @tag, @comment, @description = m.values_at(1, 3, 4) if m
9
+ m = /^([^()#:]+)(\(([^)]+)?\))?:(.*)$/.match string
10
+ @tag, @comment, description = m.values_at(1, 3, 4) if m
11
+ @description = unescape description
12
+ end
13
+
14
+ def unescape(str)
15
+ return unless str
16
+ str = str[1..-2] if str[0] == ?" and str[-1] == ?"
17
+ str.gsub(/\\n/, "\n")
18
+ end
19
+
20
+ def escape(str)
21
+ str = %["#{str.gsub(/\n/, '\n')}"] if /\n/ =~ str
22
+ str
11
23
  end
12
24
 
13
25
  def to_s
14
- "#{@tag}#{ "(#{@comment})" if @comment }:#{@description}"
26
+ "#{@tag}#{ "(#{@comment})" if @comment }:#{escape @description}"
15
27
  end
16
28
 
17
29
  def ==(o)
@@ -210,7 +210,7 @@ class MSpecOptions
210
210
  when 'r', 'ruby'
211
211
  config[:target] = 'ruby'
212
212
  when 'r19', 'ruby19'
213
- config[:target] = 'ruby19'
213
+ config[:target] = 'ruby1.9'
214
214
  when 'x', 'rubinius'
215
215
  config[:target] = './bin/rbx'
216
216
  when 'X', 'rbx'
@@ -225,12 +225,12 @@ class MSpecOptions
225
225
  end
226
226
 
227
227
  doc ""
228
- doc " r or ruby invokes ruby in PATH"
229
- doc " r19 or ruby19 invokes ruby19 in PATH"
230
- doc " x or rubinius invokes ./bin/rbx"
231
- doc " X or rbx invokes rbx in PATH"
232
- doc " j or jruby invokes jruby in PATH"
233
- doc " i or ironruby invokes ir in PATH\n"
228
+ doc " r or ruby invokes ruby in PATH"
229
+ doc " r19, ruby19 or ruby1.9 invokes ruby1.9 in PATH"
230
+ doc " x or rubinius invokes ./bin/rbx"
231
+ doc " X or rbx invokes rbx in PATH"
232
+ doc " j or jruby invokes jruby in PATH"
233
+ doc " i or ironruby invokes ir in PATH\n"
234
234
 
235
235
  on("-T", "--target-opt", "OPT",
236
236
  "Pass OPT as a flag to the target implementation") do |t|
@@ -256,6 +256,8 @@ class MSpecOptions
256
256
  config[:formatter] = HtmlFormatter
257
257
  when 'd', 'dot', 'dotted'
258
258
  config[:formatter] = DottedFormatter
259
+ when 'b', 'describe'
260
+ config[:formatter] = DescribeFormatter
259
261
  when 'f', 'file'
260
262
  config[:formatter] = FileFormatter
261
263
  when 'u', 'unit', 'unitdiff'
@@ -96,12 +96,24 @@ class MSpecScript
96
96
  load "#{engine}.#{SpecGuard.ruby_version}.mspec"
97
97
  end
98
98
 
99
+ # Callback for enabling custom options. This version is a no-op.
100
+ # Provide an implementation specific version in a config file.
101
+ # Called by #options after the MSpec-provided options are added.
102
+ def custom_options(options)
103
+ options.doc " No custom options registered"
104
+ end
105
+
99
106
  # Registers all filters and actions.
100
107
  def register
101
108
  if config[:formatter].nil?
102
109
  config[:formatter] = @files.size < 50 ? DottedFormatter : FileFormatter
103
110
  end
104
- config[:formatter].new(config[:output]).register if config[:formatter]
111
+
112
+ if config[:formatter]
113
+ formatter = config[:formatter].new(config[:output])
114
+ formatter.register
115
+ MSpec.store :formatter, formatter
116
+ end
105
117
 
106
118
  MatchFilter.new(:include, *config[:includes]).register unless config[:includes].empty?
107
119
  MatchFilter.new(:exclude, *config[:excludes]).register unless config[:excludes].empty?
@@ -114,6 +126,14 @@ class MSpecScript
114
126
 
115
127
  DebugAction.new(config[:atags], config[:astrings]).register if config[:debugger]
116
128
  GdbAction.new(config[:atags], config[:astrings]).register if config[:gdb]
129
+
130
+ custom_register
131
+ end
132
+
133
+ # Callback for enabling custom actions, etc. This version is a
134
+ # no-op. Provide an implementation specific version in a config
135
+ # file. Called by #register.
136
+ def custom_register
117
137
  end
118
138
 
119
139
  # Sets up signal handlers. Only a handler for SIGINT is
data/lib/mspec/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'mspec/utils/version'
2
2
 
3
3
  module MSpec
4
- VERSION = SpecVersion.new "1.5.6"
4
+ VERSION = SpecVersion.new "1.5.7"
5
5
  end
@@ -87,6 +87,11 @@ describe MSpecCI, "#options" do
87
87
  @options.should_receive(:help)
88
88
  @script.options
89
89
  end
90
+
91
+ it "calls #custom_options" do
92
+ @script.should_receive(:custom_options).with(@options)
93
+ @script.options
94
+ end
90
95
  end
91
96
 
92
97
  describe MSpecCI, "#run" do
@@ -124,6 +124,11 @@ describe MSpecRun, "#options" do
124
124
  @script.options
125
125
  $stdout.should =~ /No files specified/
126
126
  end
127
+
128
+ it "calls #custom_options" do
129
+ @script.should_receive(:custom_options).with(@options)
130
+ @script.options @argv
131
+ end
127
132
  end
128
133
 
129
134
  describe MSpecRun, "#run" do
@@ -37,6 +37,11 @@ describe MSpecMain, "#options" do
37
37
  @script.options [".", "-G", "fail", "-X", "ARG", "--list", "unstable", "some/file.rb"]
38
38
  @config[:options].should == [".", "-G", "fail", "--list", "unstable", "some/file.rb"]
39
39
  end
40
+
41
+ it "calls #custom_options" do
42
+ @script.should_receive(:custom_options).with(@options)
43
+ @script.options
44
+ end
40
45
  end
41
46
 
42
47
  describe MSpecMain, "#parallel" do
@@ -98,6 +98,11 @@ describe MSpecTag, "#options" do
98
98
  @script.options @argv
99
99
  end
100
100
 
101
+ it "calls #custom_options" do
102
+ @script.should_receive(:custom_options).with(@options)
103
+ @script.options @argv
104
+ end
105
+
101
106
  it "exits if there are no files to process" do
102
107
  @options.should_receive(:parse).and_return([])
103
108
  @script.should_receive(:exit)
@@ -110,7 +110,7 @@ describe Object, "#should_not" do
110
110
  end
111
111
 
112
112
  it "returns a NegativeOperatorMatcher instance when not passed a matcher" do
113
- matcher = should_not
113
+ matcher = should_not nil
114
114
  class Object; alias_method :should, :rspec_should; end
115
115
  matcher.should be_instance_of(NegativeOperatorMatcher)
116
116
  end
@@ -1,4 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'mspec/utils/ruby_name'
2
3
  require 'mspec/guards/bug'
3
4
 
4
5
  describe BugGuard, "#match? when #implementation? is 'ruby'" do
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'mspec/expectations/expectations'
3
+ require 'mspec/matchers/have_instance_method'
4
+
5
+ class HIMMSpecs
6
+ def instance_method
7
+ end
8
+
9
+ class Subclass < HIMMSpecs
10
+ def instance_sub_method
11
+ end
12
+ end
13
+ end
14
+
15
+ describe HaveInstanceMethodMatcher do
16
+ it "matches when mod has the private instance method" do
17
+ matcher = HaveInstanceMethodMatcher.new :instance_method
18
+ matcher.matches?(HIMMSpecs).should be_true
19
+ matcher.matches?(HIMMSpecs::Subclass).should be_true
20
+ end
21
+
22
+ it "does not match when mod does not have the private instance method" do
23
+ matcher = HaveInstanceMethodMatcher.new :another_method
24
+ matcher.matches?(HIMMSpecs).should be_false
25
+ end
26
+
27
+ it "does not match if the method is in a superclass and include_super is false" do
28
+ matcher = HaveInstanceMethodMatcher.new :instance_method, false
29
+ matcher.matches?(HIMMSpecs::Subclass).should be_false
30
+ end
31
+
32
+ it "provides a failure message for #should" do
33
+ matcher = HaveInstanceMethodMatcher.new :some_method
34
+ matcher.matches?(HIMMSpecs)
35
+ matcher.failure_message.should == [
36
+ "Expected HIMMSpecs to have private method 'some_method'",
37
+ "but it does not"
38
+ ]
39
+ end
40
+
41
+ it "provides a failure messoge for #should_not" do
42
+ matcher = HaveInstanceMethodMatcher.new :some_method
43
+ matcher.matches?(HIMMSpecs)
44
+ matcher.negative_failure_message.should == [
45
+ "Expected HIMMSpecs NOT to have private method 'some_method'",
46
+ "but it does"
47
+ ]
48
+ end
49
+ end
50
+
51
+ describe HaveInstanceMethodMatcher do
52
+ before :all do
53
+ @verbose = $VERBOSE
54
+ $VERBOSE = nil
55
+ end
56
+
57
+ after :all do
58
+ $VERBOSE = @verbose
59
+ end
60
+
61
+ before :each do
62
+ @ruby_version = Object.const_get :RUBY_VERSION
63
+
64
+ @method = mock("method name")
65
+ end
66
+
67
+ after :each do
68
+ Object.const_set :RUBY_VERSION, @ruby_version
69
+ end
70
+
71
+ it "converts the method name to a string if RUBY_VERSION < 1.9" do
72
+ Object.const_set :RUBY_VERSION, "1.8.6"
73
+ @method.should_receive(:to_s).and_return("method_name")
74
+ HaveInstanceMethodMatcher.new @method
75
+ end
76
+
77
+ it "does not convert the method name to a string if RUBY_VERSION >= 1.9" do
78
+ Object.const_set :RUBY_VERSION, "1.9.0"
79
+ @method.should_not_receive(:to_s)
80
+ HaveInstanceMethodMatcher.new @method
81
+ end
82
+ end
@@ -0,0 +1,86 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'mspec/expectations/expectations'
3
+ require 'mspec/matchers/have_private_instance_method'
4
+
5
+ class HPIMMSpecs
6
+ private
7
+
8
+ def private_method
9
+ end
10
+
11
+ class Subclass < HPIMMSpecs
12
+ private
13
+
14
+ def private_sub_method
15
+ end
16
+ end
17
+ end
18
+
19
+ describe HavePrivateInstanceMethodMatcher do
20
+ it "matches when mod has the private instance method" do
21
+ matcher = HavePrivateInstanceMethodMatcher.new :private_method
22
+ matcher.matches?(HPIMMSpecs).should be_true
23
+ matcher.matches?(HPIMMSpecs::Subclass).should be_true
24
+ end
25
+
26
+ it "does not match when mod does not have the private instance method" do
27
+ matcher = HavePrivateInstanceMethodMatcher.new :another_method
28
+ matcher.matches?(HPIMMSpecs).should be_false
29
+ end
30
+
31
+ it "does not match if the method is in a superclass and include_super is false" do
32
+ matcher = HavePrivateInstanceMethodMatcher.new :private_method, false
33
+ matcher.matches?(HPIMMSpecs::Subclass).should be_false
34
+ end
35
+
36
+ it "provides a failure message for #should" do
37
+ matcher = HavePrivateInstanceMethodMatcher.new :some_method
38
+ matcher.matches?(HPIMMSpecs)
39
+ matcher.failure_message.should == [
40
+ "Expected HPIMMSpecs to have private method 'some_method'",
41
+ "but it does not"
42
+ ]
43
+ end
44
+
45
+ it "provides a failure messoge for #should_not" do
46
+ matcher = HavePrivateInstanceMethodMatcher.new :some_method
47
+ matcher.matches?(HPIMMSpecs)
48
+ matcher.negative_failure_message.should == [
49
+ "Expected HPIMMSpecs NOT to have private method 'some_method'",
50
+ "but it does"
51
+ ]
52
+ end
53
+ end
54
+
55
+ describe HavePrivateInstanceMethodMatcher do
56
+ before :all do
57
+ @verbose = $VERBOSE
58
+ $VERBOSE = nil
59
+ end
60
+
61
+ after :all do
62
+ $VERBOSE = @verbose
63
+ end
64
+
65
+ before :each do
66
+ @ruby_version = Object.const_get :RUBY_VERSION
67
+
68
+ @method = mock("method name")
69
+ end
70
+
71
+ after :each do
72
+ Object.const_set :RUBY_VERSION, @ruby_version
73
+ end
74
+
75
+ it "converts the method name to a string if RUBY_VERSION < 1.9" do
76
+ Object.const_set :RUBY_VERSION, "1.8.6"
77
+ @method.should_receive(:to_s).and_return("method_name")
78
+ HavePrivateInstanceMethodMatcher.new @method
79
+ end
80
+
81
+ it "does not convert the method name to a string if RUBY_VERSION >= 1.9" do
82
+ Object.const_set :RUBY_VERSION, "1.9.0"
83
+ @method.should_not_receive(:to_s)
84
+ HavePrivateInstanceMethodMatcher.new @method
85
+ end
86
+ end
@@ -4,47 +4,147 @@ require 'mspec/runner/actions/tally'
4
4
  require 'mspec/runner/mspec'
5
5
  require 'mspec/runner/example'
6
6
 
7
- describe Tally do
7
+ describe Tally, "#files!" do
8
8
  before :each do
9
9
  @tally = Tally.new
10
10
  end
11
11
 
12
- it "responds to #files! by incrementing the count returned by #files" do
12
+ it "increments the count returned by #files" do
13
13
  @tally.files! 3
14
14
  @tally.files.should == 3
15
15
  @tally.files!
16
16
  @tally.files.should == 4
17
17
  end
18
+ end
19
+
20
+ describe Tally, "#examples!" do
21
+ before :each do
22
+ @tally = Tally.new
23
+ end
18
24
 
19
- it "responds to #examples! by incrementing the count returned by #examples" do
25
+ it "increments the count returned by #examples" do
20
26
  @tally.examples! 2
21
27
  @tally.examples.should == 2
22
28
  @tally.examples! 2
23
29
  @tally.examples.should == 4
24
30
  end
31
+ end
25
32
 
26
- it "responds to #expectations! by incrementing the count returned by #expectations" do
33
+ describe Tally, "#expectations!" do
34
+ before :each do
35
+ @tally = Tally.new
36
+ end
37
+
38
+ it "increments the count returned by #expectations" do
27
39
  @tally.expectations!
28
40
  @tally.expectations.should == 1
29
41
  @tally.expectations! 3
30
42
  @tally.expectations.should == 4
31
43
  end
44
+ end
45
+
46
+ describe Tally, "#failures!" do
47
+ before :each do
48
+ @tally = Tally.new
49
+ end
32
50
 
33
- it "responds to #failures! by incrementing the count returned by #failures" do
51
+ it "increments the count returned by #failures" do
34
52
  @tally.failures! 1
35
53
  @tally.failures.should == 1
36
54
  @tally.failures!
37
55
  @tally.failures.should == 2
38
56
  end
57
+ end
39
58
 
40
- it "responds to #errors! by incrementing the count returned by #errors" do
59
+ describe Tally, "#errors!" do
60
+ before :each do
61
+ @tally = Tally.new
62
+ end
63
+
64
+ it "increments the count returned by #errors" do
41
65
  @tally.errors!
42
66
  @tally.errors.should == 1
43
67
  @tally.errors! 2
44
68
  @tally.errors.should == 3
45
69
  end
70
+ end
71
+
72
+ describe Tally, "#file" do
73
+ before :each do
74
+ @tally = Tally.new
75
+ end
76
+
77
+ it "returns a formatted string of the number of #files" do
78
+ @tally.file.should == "0 files"
79
+ @tally.files!
80
+ @tally.file.should == "1 file"
81
+ @tally.files!
82
+ @tally.file.should == "2 files"
83
+ end
84
+ end
85
+
86
+ describe Tally, "#example" do
87
+ before :each do
88
+ @tally = Tally.new
89
+ end
90
+
91
+ it "returns a formatted string of the number of #examples" do
92
+ @tally.example.should == "0 examples"
93
+ @tally.examples!
94
+ @tally.example.should == "1 example"
95
+ @tally.examples!
96
+ @tally.example.should == "2 examples"
97
+ end
98
+ end
99
+
100
+ describe Tally, "#expectation" do
101
+ before :each do
102
+ @tally = Tally.new
103
+ end
104
+
105
+ it "returns a formatted string of the number of #expectations" do
106
+ @tally.expectation.should == "0 expectations"
107
+ @tally.expectations!
108
+ @tally.expectation.should == "1 expectation"
109
+ @tally.expectations!
110
+ @tally.expectation.should == "2 expectations"
111
+ end
112
+ end
113
+
114
+ describe Tally, "#failure" do
115
+ before :each do
116
+ @tally = Tally.new
117
+ end
118
+
119
+ it "returns a formatted string of the number of #failures" do
120
+ @tally.failure.should == "0 failures"
121
+ @tally.failures!
122
+ @tally.failure.should == "1 failure"
123
+ @tally.failures!
124
+ @tally.failure.should == "2 failures"
125
+ end
126
+ end
127
+
128
+ describe Tally, "#error" do
129
+ before :each do
130
+ @tally = Tally.new
131
+ end
132
+
133
+ it "returns a formatted string of the number of #errors" do
134
+ @tally.error.should == "0 errors"
135
+ @tally.errors!
136
+ @tally.error.should == "1 error"
137
+ @tally.errors!
138
+ @tally.error.should == "2 errors"
139
+ end
140
+ end
46
141
 
47
- it "responds to #format by returning a formatted string of counts" do
142
+ describe Tally, "#format" do
143
+ before :each do
144
+ @tally = Tally.new
145
+ end
146
+
147
+ it "returns a formatted string of counts" do
48
148
  @tally.files!
49
149
  @tally.examples! 2
50
150
  @tally.expectations! 4
@@ -53,35 +153,63 @@ describe Tally do
53
153
  end
54
154
  end
55
155
 
56
- describe TallyAction do
156
+ describe TallyAction, "#counter" do
57
157
  before :each do
58
158
  @tally = TallyAction.new
59
159
  @state = ExampleState.new("describe", "it")
60
160
  end
61
161
 
62
- it "responds to #counter by returning the Tally object" do
162
+ it "returns the Tally object" do
63
163
  @tally.counter.should be_kind_of(Tally)
64
164
  end
165
+ end
65
166
 
66
- it "responds to #load by incrementing the count returned by Tally#files" do
167
+ describe TallyAction, "#load" do
168
+ before :each do
169
+ @tally = TallyAction.new
170
+ @state = ExampleState.new("describe", "it")
171
+ end
172
+
173
+ it "increments the count returned by Tally#files" do
67
174
  @tally.load
68
175
  @tally.counter.files.should == 1
69
176
  end
177
+ end
178
+
179
+ describe TallyAction, "#expectation" do
180
+ before :each do
181
+ @tally = TallyAction.new
182
+ @state = ExampleState.new("describe", "it")
183
+ end
70
184
 
71
- it "responds to #expectation by incrementing the count returned by Tally#expectations" do
185
+ it "increments the count returned by Tally#expectations" do
72
186
  @tally.expectation @state
73
187
  @tally.counter.expectations.should == 1
74
188
  end
189
+ end
75
190
 
76
- it "responds to #example by incrementing counts returned by Tally#examples" do
191
+ describe TallyAction, "#example" do
192
+ before :each do
193
+ @tally = TallyAction.new
194
+ @state = ExampleState.new("describe", "it")
195
+ end
196
+
197
+ it "increments counts returned by Tally#examples" do
77
198
  @tally.example @state, nil
78
199
  @tally.counter.examples.should == 1
79
200
  @tally.counter.expectations.should == 0
80
201
  @tally.counter.failures.should == 0
81
202
  @tally.counter.errors.should == 0
82
203
  end
204
+ end
205
+
206
+ describe TallyAction, "#exception" do
207
+ before :each do
208
+ @tally = TallyAction.new
209
+ @state = ExampleState.new("describe", "it")
210
+ end
83
211
 
84
- it "responds to #exception by incrementing counts returned by Tally#failures" do
212
+ it "increments counts returned by Tally#failures" do
85
213
  exc = ExceptionState.new nil, nil, ExpectationNotMetError.new("Failed!")
86
214
  @tally.exception exc
87
215
  @tally.counter.examples.should == 0
@@ -89,8 +217,15 @@ describe TallyAction do
89
217
  @tally.counter.failures.should == 1
90
218
  @tally.counter.errors.should == 0
91
219
  end
220
+ end
92
221
 
93
- it "responds to #exception by incrementing counts returned by Tally#errors" do
222
+ describe TallyAction, "#exception" do
223
+ before :each do
224
+ @tally = TallyAction.new
225
+ @state = ExampleState.new("describe", "it")
226
+ end
227
+
228
+ it "increments counts returned by Tally#errors" do
94
229
  exc = ExceptionState.new nil, nil, Exception.new("Error!")
95
230
  @tally.exception exc
96
231
  @tally.counter.examples.should == 0
@@ -98,8 +233,15 @@ describe TallyAction do
98
233
  @tally.counter.failures.should == 0
99
234
  @tally.counter.errors.should == 1
100
235
  end
236
+ end
101
237
 
102
- it "responds to #format by returning a readable string of counts" do
238
+ describe TallyAction, "#format" do
239
+ before :each do
240
+ @tally = TallyAction.new
241
+ @state = ExampleState.new("describe", "it")
242
+ end
243
+
244
+ it "returns a readable string of counts" do
103
245
  @tally.load
104
246
  @tally.example @state, nil
105
247
  @tally.expectation @state
@@ -108,16 +250,30 @@ describe TallyAction do
108
250
  @tally.exception exc
109
251
  @tally.format.should == "1 file, 1 example, 2 expectations, 1 failure, 0 errors"
110
252
  end
253
+ end
254
+
255
+ describe TallyAction, "#register" do
256
+ before :each do
257
+ @tally = TallyAction.new
258
+ @state = ExampleState.new("describe", "it")
259
+ end
111
260
 
112
- it "responds to #register by registering itself with MSpec for appropriate actions" do
261
+ it "registers itself with MSpec for appropriate actions" do
113
262
  MSpec.should_receive(:register).with(:load, @tally)
114
263
  MSpec.should_receive(:register).with(:example, @tally)
115
264
  MSpec.should_receive(:register).with(:exception, @tally)
116
265
  MSpec.should_receive(:register).with(:expectation, @tally)
117
266
  @tally.register
118
267
  end
268
+ end
269
+
270
+ describe TallyAction, "#unregister" do
271
+ before :each do
272
+ @tally = TallyAction.new
273
+ @state = ExampleState.new("describe", "it")
274
+ end
119
275
 
120
- it "responds to #unregister by unregistering itself with MSpec for appropriate actions" do
276
+ it "unregisters itself with MSpec for appropriate actions" do
121
277
  MSpec.should_receive(:unregister).with(:load, @tally)
122
278
  MSpec.should_receive(:unregister).with(:exception, @tally)
123
279
  MSpec.should_receive(:unregister).with(:example, @tally)
@@ -4,6 +4,7 @@ require 'mspec/matchers/base'
4
4
  require 'mspec/runner/mspec'
5
5
  require 'mspec/mocks/mock'
6
6
  require 'mspec/runner/context'
7
+ require 'mspec/runner/example'
7
8
 
8
9
  describe ContextState, "#describe" do
9
10
  before :each do
@@ -0,0 +1,67 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'mspec/runner/formatters/describe'
3
+ require 'mspec/runner/example'
4
+
5
+ describe DescribeFormatter, "#finish" do
6
+ before :each do
7
+ MSpec.stub!(:register)
8
+ MSpec.stub!(:unregister)
9
+
10
+ @timer = mock("timer", :null_object => true)
11
+ TimerAction.stub!(:new).and_return(@timer)
12
+ @timer.stub!(:format).and_return("Finished in 2.0 seconds")
13
+
14
+ $stdout = @out = IOStub.new
15
+ context = ContextState.new "Class#method"
16
+ @state = ExampleState.new(context, "runs")
17
+
18
+ @formatter = DescribeFormatter.new
19
+ @formatter.register
20
+
21
+ @tally = @formatter.tally
22
+ @counter = @tally.counter
23
+
24
+ @counter.files!
25
+ @counter.examples!
26
+ @counter.expectations! 2
27
+ end
28
+
29
+ after :each do
30
+ $stdout = STDOUT
31
+ end
32
+
33
+ it "prints a summary of elapsed time" do
34
+ @formatter.finish
35
+ @out.should =~ /^Finished in 2.0 seconds$/
36
+ end
37
+
38
+ it "prints a tally of counts" do
39
+ @formatter.finish
40
+ @out.should =~ /^1 file, 1 example, 2 expectations, 0 failures, 0 errors$/
41
+ end
42
+
43
+ it "does not print exceptions" do
44
+ @formatter.finish
45
+ @out.should == %[
46
+
47
+ Finished in 2.0 seconds
48
+
49
+ 1 file, 1 example, 2 expectations, 0 failures, 0 errors
50
+ ]
51
+ end
52
+
53
+ it "prints a summary of failures and errors for each describe block" do
54
+ exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken")
55
+ exc.stub!(:backtrace).and_return("path/to/some/file.rb:35:in method")
56
+ @formatter.exception exc
57
+ @formatter.finish
58
+ @out.should == %[
59
+
60
+ Class#method 0 failures, 1 error
61
+
62
+ Finished in 2.0 seconds
63
+
64
+ 1 file, 1 example, 2 expectations, 0 failures, 0 errors
65
+ ]
66
+ end
67
+ end
@@ -2,6 +2,7 @@ require File.dirname(__FILE__) + '/../spec_helper'
2
2
  require 'mspec/helpers/tmp'
3
3
  require 'mspec/matchers/base'
4
4
  require 'mspec/runner/mspec'
5
+ require 'mspec/runner/example'
5
6
 
6
7
  describe MSpec, ".register_files" do
7
8
  it "records which spec files to run" do
@@ -415,6 +416,7 @@ describe MSpec, ".write_tags" do
415
416
  IO.read(tmp("tags.txt")).should == %[fail(broken):Some#method? works
416
417
  incomplete(20%):The#best method ever
417
418
  benchmark(0.01825):The#fastest method today
419
+ extended():\"Multi-line\\ntext\\ntag\"
418
420
  ]
419
421
  MSpec.write_tags [@tag1, @tag2]
420
422
  IO.read(tmp("tags.txt")).should == %[check(broken):Tag#rewrite works
@@ -461,6 +463,15 @@ describe MSpec, ".delete_tag" do
461
463
  MSpec.delete_tag(@tag).should == true
462
464
  IO.read(tmp("tags.txt")).should == %[incomplete(20%):The#best method ever
463
465
  benchmark(0.01825):The#fastest method today
466
+ extended():\"Multi-line\\ntext\\ntag\"
467
+ ]
468
+ end
469
+
470
+ it "deletes a tag with escaped newlines" do
471
+ MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true
472
+ IO.read(tmp("tags.txt")).should == %[fail(broken):Some#method? works
473
+ incomplete(20%):The#best method ever
474
+ benchmark(0.01825):The#fastest method today
464
475
  ]
465
476
  end
466
477
 
@@ -470,6 +481,7 @@ benchmark(0.01825):The#fastest method today
470
481
  IO.read(tmp("tags.txt")).should == %[fail(broken):Some#method? works
471
482
  incomplete(20%):The#best method ever
472
483
  benchmark(0.01825):The#fastest method today
484
+ extended():\"Multi-line\\ntext\\ntag\"
473
485
  ]
474
486
  end
475
487
 
@@ -477,6 +489,7 @@ benchmark(0.01825):The#fastest method today
477
489
  MSpec.delete_tag(@tag).should == true
478
490
  MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever")).should == true
479
491
  MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today")).should == true
492
+ MSpec.delete_tag(SpecTag.new("extended:\"Multi-line\ntext\ntag\"")).should == true
480
493
  File.exist?(tmp("tags.txt")).should == false
481
494
  end
482
495
  end
@@ -57,6 +57,13 @@ describe SpecTag, "#parse" do
57
57
  @tag.description.should == "Another#method"
58
58
  end
59
59
 
60
+ it "accepts 'tag(comment):\"Multi-line\\ntext\"'" do
61
+ @tag.parse 'tag(comment):"Multi-line\ntext"'
62
+ @tag.tag.should == "tag"
63
+ @tag.comment.should == "comment"
64
+ @tag.description.should == "Multi-line\ntext"
65
+ end
66
+
60
67
  it "ignores '#anything'" do
61
68
  @tag.parse "# this could be a comment"
62
69
  @tag.tag.should == nil
@@ -67,19 +74,30 @@ end
67
74
 
68
75
  describe SpecTag, "#to_s" do
69
76
  it "formats itself as 'tag(comment):description'" do
70
- tag = SpecTag.new("tag(comment):description")
77
+ txt = "tag(comment):description"
78
+ tag = SpecTag.new txt
71
79
  tag.tag.should == "tag"
72
80
  tag.comment.should == "comment"
73
81
  tag.description.should == "description"
74
- tag.to_s.should == "tag(comment):description"
82
+ tag.to_s.should == txt
75
83
  end
76
84
 
77
85
  it "formats itself as 'tag:description" do
78
- tag = SpecTag.new("tag:description")
86
+ txt = "tag:description"
87
+ tag = SpecTag.new txt
79
88
  tag.tag.should == "tag"
80
89
  tag.comment.should == nil
81
90
  tag.description.should == "description"
82
- tag.to_s.should == "tag:description"
91
+ tag.to_s.should == txt
92
+ end
93
+
94
+ it "formats itself as 'tag(comment):\"multi-line\\ntext\\ntag\"'" do
95
+ txt = 'tag(comment):"multi-line\ntext\ntag"'
96
+ tag = SpecTag.new txt
97
+ tag.tag.should == "tag"
98
+ tag.comment.should == "comment"
99
+ tag.description.should == "multi-line\ntext\ntag"
100
+ tag.to_s.should == txt
83
101
  end
84
102
  end
85
103
 
data/spec/runner/tags.txt CHANGED
@@ -1,3 +1,4 @@
1
1
  fail(broken):Some#method? works
2
2
  incomplete(20%):The#best method ever
3
3
  benchmark(0.01825):The#fastest method today
4
+ extended():"Multi-line\ntext\ntag"
@@ -549,11 +549,11 @@ describe "The -t, --target TARGET option" do
549
549
  end
550
550
  end
551
551
 
552
- it "sets the target to 'ruby19' with TARGET 'r19' or 'ruby19'" do
552
+ it "sets the target to 'ruby1.9' with TARGET 'r19', 'ruby19' or 'ruby1.9'" do
553
553
  ["-t", "--target"].each do |opt|
554
- ["r19", "ruby19"].each do |t|
554
+ ["r19", "ruby19", "ruby1.9"].each do |t|
555
555
  @options.parse [opt, t]
556
- @config[:target].should == "ruby19"
556
+ @config[:target].should == "ruby1.9"
557
557
  end
558
558
  end
559
559
  end
@@ -702,6 +702,16 @@ describe "The -f, --format FORMAT option" do
702
702
  end
703
703
  end
704
704
 
705
+ it "sets the DescribeFormatter with FORMAT 'b' or 'describe'" do
706
+ ["-f", "--format"].each do |opt|
707
+ ["b", "describe"].each do |f|
708
+ @config[:formatter] = nil
709
+ @options.parse [opt, f]
710
+ @config[:formatter].should == DescribeFormatter
711
+ end
712
+ end
713
+ end
714
+
705
715
  it "sets the FileFormatter with FORMAT 'f', 'file'" do
706
716
  ["-f", "--format"].each do |opt|
707
717
  ["f", "file"].each do |f|
@@ -193,6 +193,21 @@ describe MSpecScript, "#load" do
193
193
  end
194
194
  end
195
195
 
196
+ describe MSpecScript, "#custom_options" do
197
+ before :each do
198
+ @script = MSpecScript.new
199
+ end
200
+
201
+ after :each do
202
+ end
203
+
204
+ it "prints 'None'" do
205
+ options = mock("options")
206
+ options.should_receive(:doc).with(" No custom options registered")
207
+ @script.custom_options options
208
+ end
209
+ end
210
+
196
211
  describe MSpecScript, "#register" do
197
212
  before :each do
198
213
  @script = MSpecScript.new
@@ -211,6 +226,23 @@ describe MSpecScript, "#register" do
211
226
  @script.config[:formatter] = false
212
227
  @script.register
213
228
  end
229
+
230
+ it "calls #custom_register" do
231
+ @script.should_receive(:custom_register)
232
+ @script.register
233
+ end
234
+
235
+ it "registers :formatter with the formatter instance" do
236
+ @formatter.stub!(:new).and_return(@formatter)
237
+ MSpec.should_receive(:store).with(:formatter, @formatter)
238
+ @script.register
239
+ end
240
+
241
+ it "does not register :formatter if config[:formatter] is false" do
242
+ @script.config[:formatter] = false
243
+ MSpec.should_not_receive(:store)
244
+ @script.register
245
+ end
214
246
  end
215
247
 
216
248
  describe MSpecScript, "#register" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6
4
+ version: 1.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Ford
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-29 00:00:00 -08:00
12
+ date: 2009-02-05 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -76,6 +76,8 @@ files:
76
76
  - lib/mspec/matchers/equal.rb
77
77
  - lib/mspec/matchers/equal_element.rb
78
78
  - lib/mspec/matchers/equal_utf16.rb
79
+ - lib/mspec/matchers/have_instance_method.rb
80
+ - lib/mspec/matchers/have_private_instance_method.rb
79
81
  - lib/mspec/matchers/include.rb
80
82
  - lib/mspec/matchers/match_yaml.rb
81
83
  - lib/mspec/matchers/output.rb
@@ -104,6 +106,7 @@ files:
104
106
  - lib/mspec/runner/filters/regexp.rb
105
107
  - lib/mspec/runner/filters/tag.rb
106
108
  - lib/mspec/runner/filters.rb
109
+ - lib/mspec/runner/formatters/describe.rb
107
110
  - lib/mspec/runner/formatters/dotted.rb
108
111
  - lib/mspec/runner/formatters/file.rb
109
112
  - lib/mspec/runner/formatters/html.rb
@@ -180,6 +183,8 @@ files:
180
183
  - spec/matchers/equal_element_spec.rb
181
184
  - spec/matchers/equal_spec.rb
182
185
  - spec/matchers/equal_utf16_spec.rb
186
+ - spec/matchers/have_instance_method_spec.rb
187
+ - spec/matchers/have_private_instance_method_spec.rb
183
188
  - spec/matchers/include_spec.rb
184
189
  - spec/matchers/match_yaml_spec.rb
185
190
  - spec/matchers/output_spec.rb
@@ -203,6 +208,7 @@ files:
203
208
  - spec/runner/filters/profile_spec.rb
204
209
  - spec/runner/filters/regexp_spec.rb
205
210
  - spec/runner/filters/tag_spec.rb
211
+ - spec/runner/formatters/describe_spec.rb
206
212
  - spec/runner/formatters/dotted_spec.rb
207
213
  - spec/runner/formatters/file_spec.rb
208
214
  - spec/runner/formatters/html_spec.rb