marsh_grass 0.1.3 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 75c25a9fd71d7bc9e868b9d82a590e6c98ec1d3b
4
- data.tar.gz: 73e7f8bac791254293a91121b7f63850f438e440
2
+ SHA256:
3
+ metadata.gz: ed2c3a6f128c38e323853492d7edb4708c28baa992d65dbe4a2eb9f12b0214ce
4
+ data.tar.gz: 6af8c822dd47d3453a1ff2c1a04f8d70243b9422e4278447ff7b0873559936ff
5
5
  SHA512:
6
- metadata.gz: 746ab6c822be5085e6bde4152d27974ba55b9981ec8aee2fd24feef188b8f9744efdd6e7d290f888506c80f86a6b397ad62df49916bf5fcde19c81469dd1455a
7
- data.tar.gz: a6ee7aae1fef25f098f76319047185c8760403c159500ff1496e0834eae2a3d681eae4786e59e8bb0d95a4094ff365d6cbedee1187aafc1812ec12b32de47105
6
+ metadata.gz: 0e160807e814ce374666835b7a8fa65411c294a892191fb32a4e6f75fd0c6740f694354d2d9028b59f31fe10278f8df0cdbaa67ecbad59b749a2a6ae483365fa
7
+ data.tar.gz: 14fb47d883f776c885cedf7d278ec7311f914423a8d1670d96146d1d183050bad816633ad7d2dd3a61b0a068f03fffbea48683ac0edc3638a3a6f6342952f823
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.4
5
- before_install: gem install bundler -v 1.15.3
4
+ - 2.3.6
5
+ before_install: gem install bundler -v 1.16.1
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 Wes Rich
3
+ Copyright (c) 2017 RoleModel Software
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,8 +1,28 @@
1
1
  # MarshGrass
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/marsh_grass`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Finally! A way to examine the behavior of intermittent failures in RSpec.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ This gem allows you to subject an intermittently failing test to a variety of circumstances in an attempt to discern what combination of events leads to failure.
6
+
7
+ ## Background
8
+
9
+ Intermittent failures are challenging because the failure conditions are more difficult to pinpoint than with tests that fail 100% of the time.
10
+
11
+ Intermittent failures are also more likely to make it into production. They often pass during CI testing and code review and then crop up days or weeks later.
12
+
13
+ In programming, there is no such thing as a "random" failure. Every intermittent failure actually fails consistently, every single time... under the right set of circumstances. Perhaps your test only fails on Friday afternoons. Or, 10% of the time under race conditions. We once had a test that failed on every power of 2 run: on the 2nd, 4th, 8th, 16th run, etc. The more we ran it, the more elusive it became.
14
+
15
+ Often, the first step in fixing such a failure is to make it fail consistently. That way, as you change your code, you can use the test to confirm when you've fixed the root cause. After all, that is the purpose of the test!
16
+
17
+ ## Features
18
+ This gem subjects a given test to the following circumstances:
19
+ - repetitions
20
+ - range of speeds in execution
21
+ - execution at all times of day
22
+ - execution in all time zones
23
+ - execution at all the milliseconds surrounding a particular time of day
24
+
25
+ In our experience, repetitions is the option we use the most often. It gives the broadest feedback and is very effective at uncovering race conditions.
6
26
 
7
27
  ## Installation
8
28
 
@@ -21,18 +41,100 @@ Or install it yourself as:
21
41
  $ gem install marsh_grass
22
42
 
23
43
  ## Usage
44
+ Feature use:
45
+ - N repetitions (default: 1000, or specify integer)
46
+ - Times of day (default: all hours, minutes, seconds or specify :hours, :minutes, :seconds)
47
+ - Time zones (executes against each time zone offset from ActiveSupport::TimeZone)
48
+ - Elapsed time during test execution (default: (1..10) execution slow-down multipliers or specify range)
49
+ - Surrounding time, i.e., clock change over during the test (must specify hour: <integer>, minute: <integer>, second: <integer>)
50
+
51
+ Surrounding time runs test at every millisecond from 1 sec before to 1 sec after specified time. This is particularly useful for discerning rate of failure near and at midnight.
52
+
53
+ ### Examples
54
+ Simple examples:
55
+ ```ruby
56
+ it 'uses default repetitions', :repetitions do
57
+ ...
58
+ end
59
+
60
+ it 'uses specific repetitions', repetitions: 20 do
61
+ ...
62
+ end
63
+
64
+ it 'uses just hours for default surrounding_time', :time_of_day do
65
+ ...
66
+ end
67
+
68
+ it 'uses each hour of day', time_of_day: :hours do
69
+ ...
70
+ end
24
71
 
25
- TODO: Write usage instructions here
72
+ it 'uses each hour and minute of the day', time_of_day: [:hours, :minutes] do
73
+ ...
74
+ end
26
75
 
27
- ## Development
76
+ it 'uses each second of current minute', time_of_day: :seconds do
77
+ ...
78
+ end
28
79
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
80
+ it 'uses current time for default surrounding_time', :surrounding_time do
81
+ ...
82
+ end
30
83
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
84
+ it 'uses each millisecond around hour of day', surrounding_time: { hour: 17 } do
85
+ ...
86
+ end
87
+
88
+ it 'uses each millisecond around specified time (noon)', surrounding_time: { hour: 12, minute: 0, second: 0 } do
89
+ ...
90
+ end
91
+
92
+ it 'uses 10 different speeds for default elapsed_time', :elapsed_time do
93
+ ...
94
+ end
95
+
96
+ it 'uses array of different speeds for elapsed_time', elapsed_time: [1, 5, 10] do
97
+ ...
98
+ end
99
+
100
+ it 'uses range of different speeds for elapsed_time', elapsed_time: (1..5) do
101
+ ...
102
+ end
103
+
104
+ it 'uses 34 different timezones for default time_zones', :time_zones do
105
+ ...
106
+ end
107
+
108
+ it 'uses single named timezone for time_zone (singular)', time_zone: 'Eastern Time (US & Canada)' do
109
+ ...
110
+ end
111
+
112
+ it 'uses a specific frozen time with a string', frozen_time: '2025-08-22 17:00:00' do
113
+ ...
114
+ end
115
+
116
+ it 'uses a specific frozen time with a Time', frozen_time: Time.new(2025, 8, 22, 17) do
117
+ ...
118
+ end
119
+
120
+ it 'uses a specific moving time with a string', moving_time: '2025-08-22 17:00:00' do
121
+ ...
122
+ end
123
+
124
+ it 'uses a specific moving time with a Time', moving_time: Time.new(2025, 8, 22, 17) do
125
+ ...
126
+ end
127
+
128
+ it 'uses a specific time scalar', scaling_time: 8 do
129
+ ...
130
+ end
131
+
132
+ ```
133
+ [Further Examples](./spec/marsh_grass_spec.rb) of tests using each feature.
32
134
 
33
135
  ## Contributing
34
136
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/wesrich/marsh_grass.
137
+ Bug reports and pull requests are welcome on GitHub at https://github.com/RoleModel/marsh_grass.
36
138
 
37
139
  ## License
38
140
 
@@ -1,13 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rspec'
4
+ require 'time'
4
5
  require 'timecop'
5
- require 'pry'
6
6
 
7
7
  RSpec.configure do |config|
8
8
  def untag_example(example, tag)
9
9
  example.example_group.metadata.delete(tag) if example.metadata[:turnip]
10
- example.metadata.delete(tag)
10
+ return_value = example.metadata[tag]
11
+ example.metadata[tag] = false # Set to false to avoid recursive nested repetitions
12
+ return_value
13
+ end
14
+
15
+ def add_example_to_group(original_example, test_description, metadata_overrides = {})
16
+ repetition = original_example.duplicate_with(metadata_overrides)
17
+ repetition.metadata[:description] = test_description
18
+ original_example.example_group.context.add_example(repetition)
11
19
  end
12
20
 
13
21
  def run_example_or_duplicate(original_example, test_description)
@@ -16,9 +24,7 @@ RSpec.configure do |config|
16
24
  original_example.metadata[:description] = test_description
17
25
  original_example.run
18
26
  else
19
- repetition = original_example.duplicate_with
20
- repetition.metadata[:description] = test_description
21
- original_example.example_group.context.add_example(repetition)
27
+ add_example_to_group(original_example, test_description)
22
28
  end
23
29
  end
24
30
 
@@ -27,7 +33,7 @@ RSpec.configure do |config|
27
33
 
28
34
  now = Time.now
29
35
  time_of_day = untag_example(original_example, :time_of_day)
30
- test_segments = time_of_day.is_a?(Array) ? time_of_day : [time_of_day]
36
+ test_segments = Array(time_of_day)
31
37
  test_segments = [:hours] if test_segments == [true]
32
38
  hours_to_run = test_segments.include?(:hours) ? (0..23) : [now.hour]
33
39
  minutes_to_run = test_segments.include?(:minutes) ? (0..59) : [now.min]
@@ -36,13 +42,12 @@ RSpec.configure do |config|
36
42
  hours_to_run.each do |hour|
37
43
  minutes_to_run.each do |minute|
38
44
  seconds_to_run.each do |second|
39
- # Freeze time at the specified hour, minute, and/or second.
40
- # We need to run the test within the Timecop.freeze block,
41
- # in order to actually be affected by Timecop.
42
- Timecop.freeze(now.year, now.month, now.day, hour, minute, second) do
43
- test_description = "Run Time #{hour}:#{minute}:#{second}: #{shared_description}"
44
- run_example_or_duplicate(original_example, test_description)
45
- end
45
+ frozen_time = Time.new(now.year, now.month, now.day, hour, minute, second)
46
+ test_description = "Run Time #{frozen_time.strftime('%H:%M:%S')}: #{shared_description}"
47
+ add_example_to_group(original_example, test_description, frozen_time: frozen_time)
48
+
49
+ # To avoid the original example being shown as "PENDING", mark it as executed
50
+ original_example.instance_variable_set(:@executed, true)
46
51
  end
47
52
  end
48
53
  end
@@ -62,30 +67,27 @@ RSpec.configure do |config|
62
67
  (-1000..1000).each do |millisecond|
63
68
  # Travel to the specified hour, minute, second, and millisecond, allowing
64
69
  # for time to elapse.
65
- # We need to run the test within the Timecop.freeze block,
66
- # in order to actually be affected by Timecop.
67
- test_time = Time.at(test_time_float + millisecond.to_f / 1000)
68
- Timecop.travel(test_time) do
69
- test_description = "Run Time #{test_time.strftime('%H:%M:%S:%L')}: #{shared_description}"
70
- run_example_or_duplicate(original_example, test_description)
71
- end
70
+ moving_time = Time.at(test_time_float + millisecond.to_f / 1000)
71
+ test_description = "Run Time #{moving_time.strftime('%H:%M:%S:%L')}: #{shared_description}"
72
+ add_example_to_group(original_example, test_description, moving_time: moving_time)
73
+
74
+ # To avoid the original example being shown as "PENDING", mark it as executed
75
+ original_example.instance_variable_set(:@executed, true)
72
76
  end
73
77
  end
74
78
 
75
79
  config.around(elapsed_time: true) do |original_example|
76
80
  shared_description = original_example.metadata[:description]
77
81
 
78
- # Freeze time at the specified hour, minute, and/or second.
79
- # We need to run the test within the Timecop.freeze block,
80
- # in order to actually be affected by Timecop.
81
82
  time_multipliers = untag_example(original_example, :elapsed_time)
82
83
  time_multipliers = (1..10) unless time_multipliers.respond_to?(:each)
83
84
 
84
85
  time_multipliers.each do |seconds_multiplier|
85
- Timecop.scale(seconds_multiplier) do
86
- test_description = "Run Speed #{seconds_multiplier}x Slower: #{shared_description}"
87
- run_example_or_duplicate(original_example, test_description)
88
- end
86
+ test_description = "Run Speed #{seconds_multiplier}x Slower: #{shared_description}"
87
+ add_example_to_group(original_example, test_description, scaling_time: seconds_multiplier)
88
+
89
+ # To avoid the original example being shown as "PENDING", mark it as executed
90
+ original_example.instance_variable_set(:@executed, true)
89
91
  end
90
92
  end
91
93
 
@@ -93,21 +95,16 @@ RSpec.configure do |config|
93
95
  shared_description = original_example.metadata[:description]
94
96
  untag_example(original_example, :time_zones)
95
97
 
96
- utc = Time.now.utc
97
- time_zone_hours = %w[-12 -11 -10 -09 -08 -07 -06 -05 -04 -03 -02 -01 +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +10 +11 +12 +13 +14]
98
- time_zone_minutes = %w[00 30]
99
-
100
- time_zone_hours.each do |time_zone_hour|
101
- time_zone_minutes.each do |time_zone_minute|
102
- # We need to run the test within the Timecop.freeze block,
103
- # in order to actually be affected by Timecop.
104
- adjustment = "#{time_zone_hour}:#{time_zone_minute}"
105
- adjusted_time = Time.new(utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec, adjustment)
106
- Timecop.travel(adjusted_time) do
107
- test_description = "Time Zone Offset #{time_zone_hour}:#{time_zone_minute}: #{shared_description}"
108
- run_example_or_duplicate(original_example, test_description)
109
- end
110
- end
98
+ timezone_hash = ActiveSupport::TimeZone.all.each_with_object({}) do |tz, memo|
99
+ memo[tz.formatted_offset] = tz.name
100
+ end
101
+
102
+ timezone_hash.each do |time_zone_offset, time_zone_name|
103
+ test_description = "Time Zone Offset #{time_zone_offset}: #{shared_description}"
104
+ add_example_to_group(original_example, test_description, time_zone: time_zone_name)
105
+
106
+ # To avoid the original example being shown as "PENDING", mark it as executed
107
+ original_example.instance_variable_set(:@executed, true)
111
108
  end
112
109
  end
113
110
 
@@ -122,4 +119,46 @@ RSpec.configure do |config|
122
119
  run_example_or_duplicate(original_example, test_description)
123
120
  end
124
121
  end
122
+
123
+ config.before(:each, frozen_time: true) do |example|
124
+ time = example.metadata[:frozen_time]
125
+ time = Time.parse(example.metadata[:frozen_time]) if time.is_a?(String)
126
+ # Freeze time at the specified hour, minute, and/or second.
127
+ Timecop.freeze(time)
128
+ end
129
+
130
+ config.after(:each, frozen_time: true) do
131
+ Timecop.return
132
+ end
133
+
134
+ config.before(:each, moving_time: true) do |example|
135
+ time = example.metadata[:moving_time]
136
+ time = Time.parse(example.metadata[:moving_time]) if time.is_a?(String)
137
+ # Travel to time at the specified hour, minute, and/or second.
138
+ Timecop.travel(time)
139
+ end
140
+
141
+ config.after(:each, moving_time: true) do
142
+ Timecop.return
143
+ end
144
+
145
+ config.before(:each, scaling_time: true) do |example|
146
+ time_multiplier = example.metadata[:scaling_time]
147
+ # Scale time by the specified multiplier.
148
+ Timecop.scale(time_multiplier)
149
+ end
150
+
151
+ config.after(:each, scaling_time: true) do
152
+ Timecop.return
153
+ end
154
+
155
+ config.before(:each, time_zone: true) do |example|
156
+ ENV['OLD_TIME_ZONE'] = Time.zone&.name
157
+ # Switch to the given time zone for the duration of the example.
158
+ Time.zone = example.metadata[:time_zone]
159
+ end
160
+
161
+ config.after(:each, time_zone: true) do
162
+ Time.zone = ENV['OLD_TIME_ZONE']
163
+ end
125
164
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MarshGrass
4
- VERSION = '0.1.3'
4
+ VERSION = '0.2.0'
5
5
  end
data/marsh_grass.gemspec CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # coding: utf-8
4
3
  lib = File.expand_path('../lib', __FILE__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require 'marsh_grass/version'
@@ -10,16 +9,16 @@ Gem::Specification.new do |spec|
10
9
  spec.version = MarshGrass::VERSION
11
10
  spec.authors = [
12
11
  'Wes Rich',
13
- 'Amanda Simon'
12
+ 'Amanda Pouget'
14
13
  ]
15
14
  spec.email = [
16
15
  'wes.rich@rolemodelsoftware.com',
17
- 'amanda.simon@rolemodelsoftware.com'
16
+ 'amanda.pouget@rolemodelsoftware.com'
18
17
  ]
19
18
 
20
- spec.summary = %q{A set of tools to help diagnose random test failures.}
21
- spec.description = %q{Currently works with RSpec tags to run against possible test failure scenarios.}
22
- spec.homepage = ""
19
+ spec.summary = 'A set of tools to help diagnose random test failures.'
20
+ spec.description = 'Currently works with RSpec tags to run against possible test failure scenarios.'
21
+ spec.homepage = 'https://github.com/RoleModel/marsh_grass'
23
22
  spec.license = 'MIT'
24
23
 
25
24
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -29,10 +28,13 @@ Gem::Specification.new do |spec|
29
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
29
  spec.require_paths = ['lib']
31
30
 
32
- spec.add_development_dependency 'bundler', '~> 1.15'
33
- spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.required_ruby_version = '>= 3.0'
32
+
33
+ spec.add_development_dependency 'bundler', '>= 2.0', '< 5.0'
34
34
  spec.add_development_dependency 'pry-byebug', '~> 3'
35
- spec.add_development_dependency 'pry-doc', '~> 0'
35
+ spec.add_development_dependency 'rake', '~> 13.0'
36
+ spec.add_dependency 'activesupport', '>= 7.1', '< 8.1'
36
37
  spec.add_dependency 'rspec', '~> 3.6'
37
- spec.add_dependency 'timecop', '~> 0'
38
+ spec.add_dependency 'rspec-rails', '~> 6'
39
+ spec.add_dependency 'timecop', '~> 0.9'
38
40
  end
metadata CHANGED
@@ -1,72 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marsh_grass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wes Rich
8
- - Amanda Simon
9
- autorequire:
8
+ - Amanda Pouget
10
9
  bindir: exe
11
10
  cert_chain: []
12
- date: 2017-10-20 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ - - "<"
19
21
  - !ruby/object:Gem::Version
20
- version: '1.15'
22
+ version: '5.0'
21
23
  type: :development
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
24
26
  requirements:
25
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - "<"
26
31
  - !ruby/object:Gem::Version
27
- version: '1.15'
32
+ version: '5.0'
28
33
  - !ruby/object:Gem::Dependency
29
- name: rake
34
+ name: pry-byebug
30
35
  requirement: !ruby/object:Gem::Requirement
31
36
  requirements:
32
37
  - - "~>"
33
38
  - !ruby/object:Gem::Version
34
- version: '10.0'
39
+ version: '3'
35
40
  type: :development
36
41
  prerelease: false
37
42
  version_requirements: !ruby/object:Gem::Requirement
38
43
  requirements:
39
44
  - - "~>"
40
45
  - !ruby/object:Gem::Version
41
- version: '10.0'
46
+ version: '3'
42
47
  - !ruby/object:Gem::Dependency
43
- name: pry-byebug
48
+ name: rake
44
49
  requirement: !ruby/object:Gem::Requirement
45
50
  requirements:
46
51
  - - "~>"
47
52
  - !ruby/object:Gem::Version
48
- version: '3'
53
+ version: '13.0'
49
54
  type: :development
50
55
  prerelease: false
51
56
  version_requirements: !ruby/object:Gem::Requirement
52
57
  requirements:
53
58
  - - "~>"
54
59
  - !ruby/object:Gem::Version
55
- version: '3'
60
+ version: '13.0'
56
61
  - !ruby/object:Gem::Dependency
57
- name: pry-doc
62
+ name: activesupport
58
63
  requirement: !ruby/object:Gem::Requirement
59
64
  requirements:
60
- - - "~>"
65
+ - - ">="
61
66
  - !ruby/object:Gem::Version
62
- version: '0'
63
- type: :development
67
+ version: '7.1'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '8.1'
71
+ type: :runtime
64
72
  prerelease: false
65
73
  version_requirements: !ruby/object:Gem::Requirement
66
74
  requirements:
67
- - - "~>"
75
+ - - ">="
68
76
  - !ruby/object:Gem::Version
69
- version: '0'
77
+ version: '7.1'
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '8.1'
70
81
  - !ruby/object:Gem::Dependency
71
82
  name: rspec
72
83
  requirement: !ruby/object:Gem::Requirement
@@ -81,25 +92,39 @@ dependencies:
81
92
  - - "~>"
82
93
  - !ruby/object:Gem::Version
83
94
  version: '3.6'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rspec-rails
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '6'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '6'
84
109
  - !ruby/object:Gem::Dependency
85
110
  name: timecop
86
111
  requirement: !ruby/object:Gem::Requirement
87
112
  requirements:
88
113
  - - "~>"
89
114
  - !ruby/object:Gem::Version
90
- version: '0'
115
+ version: '0.9'
91
116
  type: :runtime
92
117
  prerelease: false
93
118
  version_requirements: !ruby/object:Gem::Requirement
94
119
  requirements:
95
120
  - - "~>"
96
121
  - !ruby/object:Gem::Version
97
- version: '0'
122
+ version: '0.9'
98
123
  description: Currently works with RSpec tags to run against possible test failure
99
124
  scenarios.
100
125
  email:
101
126
  - wes.rich@rolemodelsoftware.com
102
- - amanda.simon@rolemodelsoftware.com
127
+ - amanda.pouget@rolemodelsoftware.com
103
128
  executables: []
104
129
  extensions: []
105
130
  extra_rdoc_files: []
@@ -115,11 +140,10 @@ files:
115
140
  - lib/marsh_grass/rspec.rb
116
141
  - lib/marsh_grass/version.rb
117
142
  - marsh_grass.gemspec
118
- homepage: ''
143
+ homepage: https://github.com/RoleModel/marsh_grass
119
144
  licenses:
120
145
  - MIT
121
146
  metadata: {}
122
- post_install_message:
123
147
  rdoc_options: []
124
148
  require_paths:
125
149
  - lib
@@ -127,16 +151,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
151
  requirements:
128
152
  - - ">="
129
153
  - !ruby/object:Gem::Version
130
- version: '0'
154
+ version: '3.0'
131
155
  required_rubygems_version: !ruby/object:Gem::Requirement
132
156
  requirements:
133
157
  - - ">="
134
158
  - !ruby/object:Gem::Version
135
159
  version: '0'
136
160
  requirements: []
137
- rubyforge_project:
138
- rubygems_version: 2.6.13
139
- signing_key:
161
+ rubygems_version: 3.7.1
140
162
  specification_version: 4
141
163
  summary: A set of tools to help diagnose random test failures.
142
164
  test_files: []