forked from troessner/reek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spec.rb
146 lines (134 loc) · 3.7 KB
/
spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
require 'reek/source'
module Reek
#
# Provides matchers for Rspec, making it easy to check code quality.
#
# If you require this module somewhere within your spec (or in your spec_helper),
# Reek will arrange to update Spec::Runner's config so that it knows about the
# matchers defined here.
#
# === Examples
#
# Here's a spec that ensures there are no smell warnings in the current project:
#
# describe 'source code quality' do
# Dir['lib/**/*.rb'].each do |path|
# it "reports no smells in #{path}" do
# File.new(path).should_not reek
# end
# end
# end
#
# And here's an even simpler way to do the same:
#
# it 'has no code smells' do
# Dir['lib/**/*.rb'].should_not reek
# end
#
# Here's a simple check of a code fragment:
#
# 'def equals(other) other.thing == self.thing end'.should_not reek
#
# And a more complex example, making use of one of the factory methods for
# +Source+ so that the code is parsed and analysed only once:
#
# ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'.to_source
# ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
# ruby.should reek_of(:Duplication, /@other.thing.foo/)
# ruby.should_not reek_of(:FeatureEnvy)
#
module Spec
class ShouldReek # :nodoc:
def matches?(actual)
@source = actual.to_source
@source.smelly?
end
def failure_message_for_should
"Expected source to reek, but it didn't"
end
def failure_message_for_should_not
"Expected no smells, but got:\n#{@source.full_report}"
end
end
#
# Returns +true+ if and only if the target source code contains smells.
#
def reek
ShouldReek.new
end
class ShouldReekOf # :nodoc:
def initialize(klass, patterns)
@klass = klass
@patterns = patterns
end
def matches?(actual)
@source = actual.to_source
@source.has_smell?(@klass, @patterns)
end
def failure_message_for_should
"Expected #{@source} to reek of #{@klass}, but it didn't"
end
def failure_message_for_should_not
"Expected #{@source} not to reek of #{@klass}, but got:\n#{@source.freport}"
end
end
#
# Checks the target source code for instances of +smell_class+,
# and returns +true+ only if one of them has a report string matching
# all of the +patterns+.
#
def reek_of(smell_class, *patterns)
ShouldReekOf.new(smell_class, patterns)
end
class ShouldReekOnlyOf # :nodoc:
def initialize(klass, patterns)
@klass = klass
@patterns = patterns
end
def matches?(actual)
@source = actual.to_source
@source.report.length == 1 and @source.has_smell?(@klass, @patterns)
end
def failure_message_for_should
"Expected source to reek only of #{@klass}, but got:\n#{@source.report}"
end
def failure_message_for_should_not
"Expected source not to reek only of #{@klass}, but it did"
end
end
#
# As for reek_of, but the matched smell warning must be the only warning of
# any kind in the target source code's Reek report.
#
def reek_only_of(smell_class, *patterns)
ShouldReekOnlyOf.new(smell_class, patterns)
end
end
end
class File
def to_source
Reek::Source.from_f(self)
end
end
class String
def to_source
Reek::Source.from_s(self)
end
end
class Array
def to_source
Reek::Source.from_pathlist(self)
end
end
module Reek
class Source
def to_source
self
end
end
end
if Object.const_defined?(:Spec)
Spec::Runner.configure do |config|
config.include(Reek::Spec)
end
end