shoulda-whenever 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b556da7fd43cfccee5935c3c6a63eb2fd51ec05b
4
+ data.tar.gz: e57ef2772b14aa2ea0b04ea4ad1ae5c34ef48d5e
5
+ SHA512:
6
+ metadata.gz: fed62e52acf39bd842e32adcf34192b7a431edd89bdf938dd3b0f24617eb7e77c48f87f12f075a883d5b866728a895a17a1aa27526b40262f20dbf23ac65e9af
7
+ data.tar.gz: 8a59abf46d0c53c03c24609c1fca40458a9ee444d9b9f69c4ded72cccff07e7153713c8e36b58f7e55472e2c22f104da1be2192c9895435f78be30deba286301
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ bin/
2
+ vendor/
3
+ .bundle
4
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rspec", "~> 3.3.0"
4
+ gem "whenever", "~> 0.9.4"
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ chronic (0.10.2)
5
+ diff-lcs (1.2.5)
6
+ rspec (3.3.0)
7
+ rspec-core (~> 3.3.0)
8
+ rspec-expectations (~> 3.3.0)
9
+ rspec-mocks (~> 3.3.0)
10
+ rspec-core (3.3.2)
11
+ rspec-support (~> 3.3.0)
12
+ rspec-expectations (3.3.1)
13
+ diff-lcs (>= 1.2.0, < 2.0)
14
+ rspec-support (~> 3.3.0)
15
+ rspec-mocks (3.3.2)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.3.0)
18
+ rspec-support (3.3.0)
19
+ whenever (0.9.4)
20
+ chronic (>= 0.6.3)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ rspec (~> 3.3.0)
27
+ whenever (~> 0.9.4)
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # shoulda-whenever
2
+
3
+ This gem was born out of a desire to test the schedule for tasks being scheduled with Whenever. Not to test if Whenever can generate the proper CRON schedule, but to test whether I can generate the proper `config/schedule.rb`. It turns out I can't sometimes.
4
+
5
+ ## How to use this Gem
6
+
7
+ Add this to you gemfile:
8
+
9
+ ```ruby
10
+ gem "shoulda-whenever", "~> 0.0.1", "https://github.com/MGerrior/shoulda-whenever.git"
11
+ ```
12
+
13
+ Create a new schedule to be tested at `config/schedule.rb` (or anywhere really, but for the sake of the README, that's where it is):
14
+
15
+ ```ruby
16
+ every :friday, at: "12:00 PM" do
17
+ runner "Notifier.send_team_lunch_email"
18
+ end
19
+ ```
20
+
21
+ Create a new test file for testing your schedule, perhaps something like `spec/schedule_spec.rb`:
22
+
23
+ ```ruby
24
+ describe "Schedule" do
25
+ include Shoulda::Whenever
26
+
27
+ let(:whenever) { Whenever::JobList.new(file: File.join(Rails.root, "config", "schedule.rb").to_s) }
28
+
29
+ it "sends out the team lunch reminder email every friday at noon" do
30
+ expect(whenever).to schedule("Notifier.send_team_lunch_email").every(:friday).at("12:00 PM")
31
+ end
32
+ end
33
+ ```
@@ -0,0 +1,149 @@
1
+ module Shoulda
2
+ module Whenever
3
+ def schedule(task)
4
+ ScheduleMatcher.new(task)
5
+ end
6
+
7
+ alias_method :schedule_rake, :schedule
8
+ alias_method :schedule_runner, :schedule
9
+ alias_method :schedule_command, :schedule
10
+
11
+ class ScheduleMatcher
12
+ attr_reader :duration, :time, :task, :roles
13
+
14
+ def initialize(task)
15
+ @task = task
16
+ @duration = nil
17
+ @time = nil
18
+ @roles = nil
19
+ end
20
+
21
+ def matches?(subject)
22
+ jobs = subject.instance_variable_get("@jobs")
23
+
24
+ jobs = filter_jobs_by_duration(jobs)
25
+ jobs = filter_jobs_by_time(jobs)
26
+ jobs = filter_jobs_by_roles(jobs)
27
+ jobs = filter_jobs_by_task(jobs)
28
+
29
+ jobs.any?
30
+ end
31
+
32
+ def filter_jobs_by_duration(jobs)
33
+ if duration.nil?
34
+ jobs.values.flatten
35
+ else
36
+ duration_to_fetch = if duration.is_a?(String) || duration.is_a?(Symbol)
37
+ duration
38
+ else
39
+ duration.to_i
40
+ end
41
+
42
+ jobs.fetch(duration_to_fetch) { [] }
43
+ end
44
+ end
45
+
46
+ def filter_jobs_by_time(jobs)
47
+ return jobs if time.nil?
48
+
49
+ jobs.select { |job| job.at == time }
50
+ end
51
+
52
+ def filter_jobs_by_roles(jobs)
53
+ return jobs if roles.nil? || roles.empty?
54
+
55
+ jobs.select { |job| job.roles == roles }
56
+ end
57
+
58
+ def filter_jobs_by_task(jobs)
59
+ jobs.select do |job|
60
+ job.instance_variable_get("@options")[:task] == task
61
+ end
62
+ end
63
+
64
+ def every(duration)
65
+ @duration = duration
66
+
67
+ self
68
+ end
69
+
70
+ def at(time)
71
+ @time = time
72
+
73
+ self
74
+ end
75
+
76
+ def with_roles(roles)
77
+ @roles = Array(roles)
78
+
79
+ self
80
+ end
81
+ alias_method :with_role, :with_roles
82
+
83
+ def description
84
+ [
85
+ base_description,
86
+ duration_description,
87
+ time_description,
88
+ roles_description
89
+ ].compact.join(' ')
90
+ end
91
+
92
+ def failure_message
93
+ [
94
+ base_failure_message,
95
+ duration_description,
96
+ time_description,
97
+ roles_description
98
+ ].compact.join(' ')
99
+ end
100
+
101
+ def failure_message_when_negated
102
+ [
103
+ base_failure_message_when_negated,
104
+ duration_description,
105
+ time_description,
106
+ roles_description
107
+ ].compact.join(' ')
108
+ end
109
+
110
+ private
111
+
112
+ def base_description
113
+ "schedule \"#{ task }\""
114
+ end
115
+
116
+ def duration_description
117
+ unless duration.nil?
118
+ if duration.is_a?(String) || duration.is_a?(Symbol)
119
+ "every \"#{ duration }\""
120
+ else
121
+ "every #{ duration.to_i } seconds"
122
+ end
123
+ end
124
+ end
125
+
126
+ def time_description
127
+ unless time.nil?
128
+ "at \"#{ time }\""
129
+ end
130
+ end
131
+
132
+ def roles_description
133
+ unless roles.nil? || roles.empty?
134
+ role_names = roles.map { |role| "\"#{ role }\"" }.join(", ")
135
+
136
+ "with #{ role_names } role(s)"
137
+ end
138
+ end
139
+
140
+ def base_failure_message
141
+ "expected to schedule \"#{ task }\""
142
+ end
143
+
144
+ def base_failure_message_when_negated
145
+ "expected not to schedule \"#{ task }\""
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,5 @@
1
+ module Shoulda
2
+ module Whenever
3
+ VERSION = "0.0.1".freeze
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ require "shoulda/whenever/schedule_matcher"
2
+
3
+ module Shoulda
4
+ module Whenever
5
+ end
6
+ end
data/lib/shoulda.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "shoulda/whenever"
2
+
3
+ module Shoulda
4
+ end
@@ -0,0 +1,23 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
2
+ require 'shoulda/whenever/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "shoulda-whenever"
6
+ s.version = Shoulda::Whenever::VERSION.dup
7
+ s.authors = ["Matthew Gerrior"]
8
+ s.date = Time.now.strftime("%Y-%m-%d")
9
+ s.email = "gerrior.matthew@gmail.com"
10
+ s.homepage = "http://rubygems.org/gems/shoulda-whenever"
11
+ s.summary = "Shoulda style matchers for whenever gem"
12
+ s.license = "MIT"
13
+ s.description = "This gem is designed to make it easier to test that the schedule you built with the 'whenever' gem is accurate."
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.require_paths = ["lib"]
18
+
19
+ s.required_ruby_version = '>= 1.9.3'
20
+
21
+ s.add_development_dependency "rspec", "~> 3.3.0"
22
+ s.add_development_dependency "whenever", "~> 0.9.4"
23
+ end
@@ -0,0 +1,228 @@
1
+ require "spec_helper"
2
+ require "whenever"
3
+ require "shoulda/whenever/schedule_matcher"
4
+ require "rspec/matchers/fail_matchers"
5
+
6
+ describe Shoulda::Whenever::ScheduleMatcher do
7
+ include Shoulda::Whenever
8
+ include RSpec::Matchers::FailMatchers
9
+
10
+ let(:whenever) { Whenever::JobList.new(string: schedule_string) }
11
+
12
+ describe "#description" do
13
+ context "basic schedule check" do
14
+ it "includes the task being scheduled" do
15
+ expect(described_class.new("rake:every:10:minutes").description).to eq("schedule \"rake:every:10:minutes\"")
16
+ end
17
+ end
18
+
19
+ context "with a duration" do
20
+ it "includes the duration at which the task is being scheduled" do
21
+ expect(
22
+ described_class.new("rake:every:10:minutes")
23
+ .every(Whenever::NumericSeconds.seconds(10, "minutes"))
24
+ .description
25
+ ).to eq("schedule \"rake:every:10:minutes\" every 600 seconds")
26
+ end
27
+ end
28
+
29
+ context "with a time to run" do
30
+ it "includes the time at which the task is scheduled to run" do
31
+ expect(
32
+ described_class.new("rake:every:10:minutes")
33
+ .at("12:00 PM")
34
+ .description
35
+ ).to eq("schedule \"rake:every:10:minutes\" at \"12:00 PM\"")
36
+ end
37
+ end
38
+
39
+ context "with a cron schedule" do
40
+ it "includes the schedule" do
41
+ expect(
42
+ described_class.new("rake:every:1:day:at:noon")
43
+ .every("0 0 27-31 * *")
44
+ .description
45
+ ).to eq("schedule \"rake:every:1:day:at:noon\" every \"0 0 27-31 * *\"")
46
+ end
47
+ end
48
+
49
+ context "with a symbol schedule" do
50
+ it "includes the schedule" do
51
+ expect(
52
+ described_class.new("rake:every:1:day:at:noon")
53
+ .every(:friday)
54
+ .description
55
+ ).to eq("schedule \"rake:every:1:day:at:noon\" every \"friday\"")
56
+ end
57
+ end
58
+
59
+ context "with a role" do
60
+ it "includes the role" do
61
+ expect(
62
+ described_class.new("rake:every:day").with_role(:app).description
63
+ ).to eq("schedule \"rake:every:day\" with \"app\" role(s)")
64
+ end
65
+ end
66
+
67
+ context "with multiple roles" do
68
+ it "includes the roles" do
69
+ expect(
70
+ described_class.new("rake:every:day").with_roles([:app, :database, :redis]).description
71
+ ).to eq("schedule \"rake:every:day\" with \"app\", \"database\", \"redis\" role(s)")
72
+ end
73
+ end
74
+ end
75
+
76
+ context "a task that is not scheduled" do
77
+ let(:schedule_string) { "" }
78
+
79
+ it "passes" do
80
+ expect(whenever).not_to schedule("MyTask.run")
81
+ end
82
+
83
+ it "fails" do
84
+ expect {
85
+ expect(whenever).to schedule("MyTask.run")
86
+ }.to fail_with("expected to schedule \"MyTask.run\"")
87
+ end
88
+ end
89
+
90
+ context "a task that is scheduled" do
91
+ let(:schedule_string) do
92
+ <<-SCHEDULE
93
+ every 3.hours do
94
+ rake "rake:every:3:hours"
95
+ end
96
+ SCHEDULE
97
+ end
98
+
99
+ it "passes" do
100
+ expect(whenever).to schedule("rake:every:3:hours")
101
+ end
102
+
103
+ it "fails" do
104
+ expect {
105
+ expect(whenever).not_to schedule("rake:every:3:hours")
106
+ }.to fail_with("expected not to schedule \"rake:every:3:hours\"")
107
+ end
108
+ end
109
+
110
+ context "a task that is scheduled after a certain duration" do
111
+ let(:schedule_string) do
112
+ <<-SCHEDULE
113
+ every 3.hours do
114
+ rake "rake:every:3:hours"
115
+ end
116
+ SCHEDULE
117
+ end
118
+
119
+ it "passes" do
120
+ expect(whenever).to schedule("rake:every:3:hours").every(Whenever::NumericSeconds.seconds(3, "hours"))
121
+ end
122
+ it "fails" do
123
+ expect {
124
+ expect(whenever).not_to schedule("rake:every:3:hours").every(Whenever::NumericSeconds.seconds(3, "hours"))
125
+ }.to fail_with("expected not to schedule \"rake:every:3:hours\" every 10800 seconds")
126
+ end
127
+ end
128
+
129
+ context "a task that is scheduled to run at a certain time" do
130
+ let(:schedule_string) do
131
+ <<-SCHEDULE
132
+ every 1.day, at: "12:00 PM" do
133
+ rake "rake:every:day:at:noon"
134
+ end
135
+ SCHEDULE
136
+ end
137
+
138
+ it "passes" do
139
+ expect(whenever).to schedule("rake:every:day:at:noon").every(Whenever::NumericSeconds.seconds(1, "day")).at("12:00 PM")
140
+ end
141
+
142
+ it "fails" do
143
+ expect {
144
+ expect(whenever).not_to schedule("rake:every:day:at:noon").every(Whenever::NumericSeconds.seconds(1, "day")).at("12:00 PM")
145
+ }.to fail_with("expected not to schedule \"rake:every:day:at:noon\" every 86400 seconds at \"12:00 PM\"")
146
+ end
147
+ end
148
+
149
+ context "a task that is scheduled for a certain day" do
150
+ let(:schedule_string) do
151
+ <<-SCHEDULE
152
+ every :friday do
153
+ rake "rake:every:friday"
154
+ end
155
+ SCHEDULE
156
+ end
157
+
158
+ it "passes" do
159
+ expect(whenever).to schedule("rake:every:friday").every(:friday)
160
+ end
161
+
162
+ it "fails" do
163
+ expect {
164
+ expect(whenever).not_to schedule("rake:every:friday").every(:friday)
165
+ }.to fail_with("expected not to schedule \"rake:every:friday\" every \"friday\"")
166
+ end
167
+ end
168
+
169
+ context "a task that is scheduled with cron syntax" do
170
+ let(:schedule_string) do
171
+ <<-SCHEDULE
172
+ every '0 0 27-31 * *' do
173
+ rake "rake:end:of:month"
174
+ end
175
+ SCHEDULE
176
+ end
177
+
178
+ it "passes" do
179
+ expect(whenever).to schedule("rake:end:of:month").every("0 0 27-31 * *")
180
+ end
181
+
182
+ it "fails" do
183
+ expect {
184
+ expect(whenever).not_to schedule("rake:end:of:month").every("0 0 27-31 * *")
185
+ }.to fail_with("expected not to schedule \"rake:end:of:month\" every \"0 0 27-31 * *\"")
186
+ end
187
+ end
188
+
189
+ context "a task that is scheduled for a certain role" do
190
+ let(:schedule_string) do
191
+ <<-SCHEDULE
192
+ every 10.minutes, roles: [:app] do
193
+ rake "rake:every:10:minutes"
194
+ end
195
+ SCHEDULE
196
+ end
197
+
198
+ it "passes" do
199
+ expect(whenever).to schedule("rake:every:10:minutes").with_role(:app)
200
+ end
201
+
202
+ it "fails" do
203
+ expect {
204
+ expect(whenever).not_to schedule("rake:every:10:minutes").with_role(:app)
205
+ }.to fail_with("expected not to schedule \"rake:every:10:minutes\" with \"app\" role(s)")
206
+ end
207
+ end
208
+
209
+ context "a task that is scheduled for multiple roles" do
210
+ let(:schedule_string) do
211
+ <<-SCHEDULE
212
+ every 10.minutes, roles: [:app, :database] do
213
+ rake "rake:every:10:minutes"
214
+ end
215
+ SCHEDULE
216
+ end
217
+
218
+ it "passes" do
219
+ expect(whenever).to schedule("rake:every:10:minutes").with_roles([:app, :database])
220
+ end
221
+
222
+ it "fails" do
223
+ expect {
224
+ expect(whenever).not_to schedule("rake:every:10:minutes").with_roles([:app, :database])
225
+ }.to fail_with("expected not to schedule \"rake:every:10:minutes\" with \"app\", \"database\" role(s)")
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,78 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, make a
10
+ # separate helper file that requires this one and then use it only in the specs
11
+ # that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # The settings below are suggested to provide a good initial experience
19
+ # with RSpec, but feel free to customize to your heart's content.
20
+ =begin
21
+ # These two settings work together to allow you to limit a spec run
22
+ # to individual examples or groups you care about by tagging them with
23
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
24
+ # get run.
25
+ config.filter_run :focus
26
+ config.run_all_when_everything_filtered = true
27
+
28
+ # Many RSpec users commonly either run the entire suite or an individual
29
+ # file, and it's useful to allow more verbose output when running an
30
+ # individual spec file.
31
+ if config.files_to_run.one?
32
+ # Use the documentation formatter for detailed output,
33
+ # unless a formatter has already been configured
34
+ # (e.g. via a command-line flag).
35
+ config.default_formatter = 'doc'
36
+ end
37
+
38
+ # Print the 10 slowest examples and example groups at the
39
+ # end of the spec run, to help surface which specs are running
40
+ # particularly slow.
41
+ config.profile_examples = 10
42
+
43
+ # Run specs in random order to surface order dependencies. If you find an
44
+ # order dependency and want to debug it, you can fix the order by providing
45
+ # the seed, which is printed after each run.
46
+ # --seed 1234
47
+ config.order = :random
48
+
49
+ # Seed global randomization in this process using the `--seed` CLI option.
50
+ # Setting this allows you to use `--seed` to deterministically reproduce
51
+ # test failures related to randomization by passing the same `--seed` value
52
+ # as the one that triggered the failure.
53
+ Kernel.srand config.seed
54
+
55
+ # rspec-expectations config goes here. You can use an alternate
56
+ # assertion/expectation library such as wrong or the stdlib/minitest
57
+ # assertions if you prefer.
58
+ config.expect_with :rspec do |expectations|
59
+ # Enable only the newer, non-monkey-patching expect syntax.
60
+ # For more details, see:
61
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
62
+ expectations.syntax = :expect
63
+ end
64
+
65
+ # rspec-mocks config goes here. You can use an alternate test double
66
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
67
+ config.mock_with :rspec do |mocks|
68
+ # Enable only the newer, non-monkey-patching expect syntax.
69
+ # For more details, see:
70
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
71
+ mocks.syntax = :expect
72
+
73
+ # Prevents you from mocking or stubbing a method that does not exist on
74
+ # a real object. This is generally recommended.
75
+ mocks.verify_partial_doubles = true
76
+ end
77
+ =end
78
+ end
@@ -0,0 +1,3 @@
1
+ every 3.hours do
2
+ rake "run:every:3:hours"
3
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shoulda-whenever
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Gerrior
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.3.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: whenever
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.4
41
+ description: This gem is designed to make it easier to test that the schedule you
42
+ built with the 'whenever' gem is accurate.
43
+ email: gerrior.matthew@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - README.md
52
+ - lib/shoulda.rb
53
+ - lib/shoulda/whenever.rb
54
+ - lib/shoulda/whenever/schedule_matcher.rb
55
+ - lib/shoulda/whenever/version.rb
56
+ - shoulda-whenever.gemspec
57
+ - spec/shoulda/whenever/schedule_matcher_spec.rb
58
+ - spec/spec_helper.rb
59
+ - spec/support/schedule.rb
60
+ homepage: http://rubygems.org/gems/shoulda-whenever
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.9.3
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.4.5
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Shoulda style matchers for whenever gem
84
+ test_files:
85
+ - spec/shoulda/whenever/schedule_matcher_spec.rb
86
+ - spec/spec_helper.rb
87
+ - spec/support/schedule.rb
88
+ has_rdoc: