rspecq 0.5.0 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/README.md +35 -2
- data/bin/rspecq +28 -3
- data/lib/rspecq/formatters/failure_recorder.rb +4 -3
- data/lib/rspecq/queue.rb +35 -3
- data/lib/rspecq/reporter.rb +15 -7
- data/lib/rspecq/version.rb +1 -1
- data/lib/rspecq/worker.rb +28 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d62ec9f80b28ee9acd347b82b484eeeb0e7a6b21f76e201a19d14477840f91a3
|
4
|
+
data.tar.gz: 8b20f8f635cc3bec96707e29f6547a060baf7131c6e53527e3e1ce8583e5e27b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 327351debae5f53a3a0be189fc7ff59877030d38d640e3310bb6cd24ec8944e7b38f7761f88e05fa5fa5804d37bbc5fd4889839829f88d96f1d84e1545de6625
|
7
|
+
data.tar.gz: 4ba95049a709afb17feebd22617c7018528fe9f2379170f93913e66e10ddb2723eb01411b228087efe8cfb27a255a7dacce7cddd283246da89c34dbbfe2d5fc0
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,29 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
Breaking changes are prefixed with a "[BREAKING]" label.
|
4
|
+
|
3
5
|
## master (unreleased)
|
4
6
|
|
5
|
-
|
7
|
+
## 0.7.2 (2021-11-15)
|
8
|
+
|
9
|
+
- Add tag option to filter specs (@jorge-wonolo)
|
10
|
+
|
11
|
+
## 0.7.1 (2021-04-08)
|
12
|
+
|
13
|
+
- New env variable RSPECQ_REPORTER_RERUN_COMMAND_SKIP. When set, the reporter
|
14
|
+
does not include the flaky test's rerun command.
|
15
|
+
|
16
|
+
## 0.7.0 (2021-04-01)
|
17
|
+
|
18
|
+
- New cli parameter `reproduction`.
|
19
|
+
When passed, primary worker publishes the queue in the same order as passed
|
20
|
+
in the command.
|
21
|
+
- Reporter now includes a reproduction command for flaky tests.
|
22
|
+
|
23
|
+
## 0.6.0 (2021-03-23)
|
24
|
+
|
25
|
+
- New cli parameter `seed`.
|
26
|
+
The seed is passed to the RSpec command.
|
6
27
|
|
7
28
|
## 0.5.0 (2021-02-05)
|
8
29
|
|
data/README.md
CHANGED
@@ -64,6 +64,7 @@ USAGE:
|
|
64
64
|
OPTIONS:
|
65
65
|
-b, --build ID A unique identifier for the build. Should be common among workers participating in the same build.
|
66
66
|
-w, --worker ID An identifier for the worker. Workers participating in the same build should have distinct IDs.
|
67
|
+
--seed SEED The RSpec seed. Passing the seed can be helpful in many ways i.e reproduction and testing.
|
67
68
|
-r, --redis HOST --redis is deprecated. Use --redis-host or --redis-url instead. Redis host to connect to (default: 127.0.0.1).
|
68
69
|
--redis-host HOST Redis host to connect to (default: 127.0.0.1).
|
69
70
|
--redis-url URL Redis URL to connect to (e.g.: redis://127.0.0.1:6379/0).
|
@@ -75,10 +76,36 @@ OPTIONS:
|
|
75
76
|
--max-requeues N Retry failed examples up to N times before considering them legit failures (default: 3).
|
76
77
|
--queue-wait-timeout N Time to wait for a queue to be ready before considering it failed (default: 30).
|
77
78
|
--fail-fast N Abort build with a non-zero status code after N failed examples.
|
79
|
+
--reproduction Enable reproduction mode: Publish files and examples in the exact order given in the command. Incompatible with --timings.
|
80
|
+
--tag TAG Run examples with the specified tag, or exclude examples by adding ~ before the tag. - e.g. ~slow - TAG is always converted to a symbol.
|
78
81
|
-h, --help Show this message.
|
79
82
|
-v, --version Print the version and exit.
|
80
83
|
```
|
81
84
|
|
85
|
+
You can set most options using ENV variables:
|
86
|
+
|
87
|
+
```shell
|
88
|
+
$ RSPECQ_BUILD=123 RSPECQ_WORKER=foo1 rspecq spec/
|
89
|
+
```
|
90
|
+
|
91
|
+
### Supported ENV variables
|
92
|
+
|
93
|
+
| Name | Desc |
|
94
|
+
| --- | --- |
|
95
|
+
| `RSPECQ_BUILD` | Build ID |
|
96
|
+
| `RSPECQ_WORKER` | Worker ID |
|
97
|
+
| `RSPECQ_SEED` | RSpec seed |
|
98
|
+
| `RSPECQ_REDIS` | Redis HOST |
|
99
|
+
| `RSPECQ_UPDATE_TIMINGS` | Timings |
|
100
|
+
| `RSPECQ_FILE_SPLIT_THRESHOLD` | File split threshold |
|
101
|
+
| `RSPECQ_REPORT` | Report |
|
102
|
+
| `RSPECQ_REPORT_TIMEOUT` | Report Timeout |
|
103
|
+
| `RSPECQ_MAX_REQUEUES` | Max requests |
|
104
|
+
| `RSPECQ_QUEUE_WAIT_TIMEOUT` | Queue wait timeout |
|
105
|
+
| `RSPECQ_REDIS_URL` | Redis URL |
|
106
|
+
| `RSPECQ_FAIL_FAST` | Fail fast |
|
107
|
+
| `RSPECQ_REPORTER_RERUN_COMMAND_SKIP` | Do not report flaky test's rerun command |
|
108
|
+
|
82
109
|
### Sentry integration
|
83
110
|
|
84
111
|
RSpecQ can optionally emit build events to a
|
@@ -90,7 +117,6 @@ This is convenient for monitoring important warnings/errors that may impact
|
|
90
117
|
build times, such as the fact that no previous timings were found and
|
91
118
|
therefore job scheduling was effectively random for a particular build.
|
92
119
|
|
93
|
-
|
94
120
|
## How it works
|
95
121
|
|
96
122
|
The core design is almost identical to ci-queue so please refer to its
|
@@ -117,7 +143,7 @@ For example, a single file may need 10 minutes to run while all other
|
|
117
143
|
files finish after 8 minutes. This would cause all but one workers to be
|
118
144
|
sitting idle for 2 minutes.
|
119
145
|
|
120
|
-
To overcome this issue, RSpecQ can
|
146
|
+
To overcome this issue, RSpecQ can split files which their execution time is
|
121
147
|
above a certain threshold (set with the `--file-split-threshold` option)
|
122
148
|
and instead schedule them as individual examples.
|
123
149
|
|
@@ -216,6 +242,13 @@ To enable verbose output in the tests:
|
|
216
242
|
$ RSPECQ_DEBUG=1 bundle exec rake
|
217
243
|
```
|
218
244
|
|
245
|
+
## Redis
|
246
|
+
|
247
|
+
RSpecQ by design doesn't expire its keys from Redis. It is left to the user
|
248
|
+
to configure the Redis server to do so; see
|
249
|
+
[Using Redis as an LRU cache](https://redis.io/topics/lru-cache) for more info.
|
250
|
+
|
251
|
+
You can do this from a configuration file or with `redis-cli`.
|
219
252
|
|
220
253
|
## License
|
221
254
|
|
data/bin/rspecq
CHANGED
@@ -12,7 +12,9 @@ def env_set?(var)
|
|
12
12
|
["1", "true"].include?(ENV[var])
|
13
13
|
end
|
14
14
|
|
15
|
-
opts = {
|
15
|
+
opts = {
|
16
|
+
tags: []
|
17
|
+
}
|
16
18
|
|
17
19
|
OptionParser.new do |o|
|
18
20
|
name = File.basename($PROGRAM_NAME)
|
@@ -38,9 +40,14 @@ OptionParser.new do |o|
|
|
38
40
|
opts[:worker] = v
|
39
41
|
end
|
40
42
|
|
43
|
+
o.on("--seed SEED", "The RSpec seed. Passing the seed can be helpful in " \
|
44
|
+
"many ways i.e reproduction and testing.") do |v|
|
45
|
+
opts[:seed] = v
|
46
|
+
end
|
47
|
+
|
41
48
|
o.on("-r", "--redis HOST", "Redis host to connect to " \
|
42
49
|
"(default: #{DEFAULT_REDIS_HOST}).") do |v|
|
43
|
-
puts "--redis is deprecated. Use --redis-host or --redis-url instead"
|
50
|
+
puts "DEPRECATION: --redis is deprecated. Use --redis-host or --redis-url instead"
|
44
51
|
opts[:redis_host] = v
|
45
52
|
end
|
46
53
|
|
@@ -96,11 +103,24 @@ OptionParser.new do |o|
|
|
96
103
|
opts[:fail_fast] = v
|
97
104
|
end
|
98
105
|
|
106
|
+
o.on("--reproduction", "Enable reproduction mode: run rspec on the given files " \
|
107
|
+
"and examples in the exact order they are given. Incompatible with " \
|
108
|
+
"--timings.") do |v|
|
109
|
+
opts[:reproduction] = v
|
110
|
+
end
|
111
|
+
|
99
112
|
o.on_tail("-h", "--help", "Show this message.") do
|
100
113
|
puts o
|
101
114
|
exit
|
102
115
|
end
|
103
116
|
|
117
|
+
o.on("--tag TAG", "Run examples with the specified tag, or exclude examples " \
|
118
|
+
"by adding ~ before the tag." \
|
119
|
+
" - e.g. ~slow" \
|
120
|
+
" - TAG is always converted to a symbol.") do |tag|
|
121
|
+
opts[:tags] << tag
|
122
|
+
end
|
123
|
+
|
104
124
|
o.on_tail("-v", "--version", "Print the version and exit.") do
|
105
125
|
puts "#{name} #{RSpecQ::VERSION}"
|
106
126
|
exit
|
@@ -109,6 +129,7 @@ end.parse!
|
|
109
129
|
|
110
130
|
opts[:build] ||= ENV["RSPECQ_BUILD"]
|
111
131
|
opts[:worker] ||= ENV["RSPECQ_WORKER"]
|
132
|
+
opts[:seed] ||= ENV["RSPECQ_SEED"]
|
112
133
|
opts[:redis_host] ||= ENV["RSPECQ_REDIS"] || DEFAULT_REDIS_HOST
|
113
134
|
opts[:timings] ||= env_set?("RSPECQ_UPDATE_TIMINGS")
|
114
135
|
opts[:file_split_threshold] ||= Integer(ENV["RSPECQ_FILE_SPLIT_THRESHOLD"] || 9_999_999)
|
@@ -118,6 +139,7 @@ opts[:max_requeues] ||= Integer(ENV["RSPECQ_MAX_REQUEUES"] || DEFAULT_MAX_REQUEU
|
|
118
139
|
opts[:queue_wait_timeout] ||= Integer(ENV["RSPECQ_QUEUE_WAIT_TIMEOUT"] || DEFAULT_QUEUE_WAIT_TIMEOUT)
|
119
140
|
opts[:redis_url] ||= ENV["RSPECQ_REDIS_URL"]
|
120
141
|
opts[:fail_fast] ||= Integer(ENV["RSPECQ_FAIL_FAST"] || DEFAULT_FAIL_FAST)
|
142
|
+
opts[:reproduction] ||= env_set?("RSPECQ_REPRODUCTION")
|
121
143
|
|
122
144
|
# rubocop:disable Style/RaiseArgs, Layout/EmptyLineAfterGuardClause
|
123
145
|
raise OptionParser::MissingArgument.new(:build) if opts[:build].nil?
|
@@ -148,11 +170,14 @@ else
|
|
148
170
|
redis_opts: redis_opts
|
149
171
|
)
|
150
172
|
|
151
|
-
worker.files_or_dirs_to_run = ARGV
|
173
|
+
worker.files_or_dirs_to_run = ARGV if ARGV.any?
|
152
174
|
worker.populate_timings = opts[:timings]
|
153
175
|
worker.file_split_threshold = opts[:file_split_threshold]
|
154
176
|
worker.max_requeues = opts[:max_requeues]
|
155
177
|
worker.queue_wait_timeout = opts[:queue_wait_timeout]
|
156
178
|
worker.fail_fast = opts[:fail_fast]
|
179
|
+
worker.seed = Integer(opts[:seed]) if opts[:seed]
|
180
|
+
worker.reproduction = opts[:reproduction]
|
181
|
+
worker.tags = opts[:tags]
|
157
182
|
worker.work
|
158
183
|
end
|
@@ -6,12 +6,13 @@ module RSpecQ
|
|
6
6
|
# Also persists non-example error information (e.g. a syntax error that
|
7
7
|
# in a spec file).
|
8
8
|
class FailureRecorder
|
9
|
-
def initialize(queue, job, max_requeues)
|
9
|
+
def initialize(queue, job, max_requeues, worker_id)
|
10
10
|
@queue = queue
|
11
11
|
@job = job
|
12
12
|
@colorizer = RSpec::Core::Formatters::ConsoleCodes
|
13
13
|
@non_example_error_recorded = false
|
14
14
|
@max_requeues = max_requeues
|
15
|
+
@worker_id = worker_id
|
15
16
|
end
|
16
17
|
|
17
18
|
# Here we're notified about errors occuring outside of examples.
|
@@ -30,7 +31,7 @@ module RSpecQ
|
|
30
31
|
def example_failed(notification)
|
31
32
|
example = notification.example
|
32
33
|
|
33
|
-
if @queue.requeue_job(example
|
34
|
+
if @queue.requeue_job(example, @max_requeues, @worker_id)
|
34
35
|
# HACK: try to avoid picking the job we just requeued; we want it
|
35
36
|
# to be picked up by a different worker
|
36
37
|
sleep 0.5
|
@@ -44,7 +45,7 @@ module RSpecQ
|
|
44
45
|
msg = presenter.fully_formatted(nil, @colorizer)
|
45
46
|
msg << "\n"
|
46
47
|
msg << @colorizer.wrap(
|
47
|
-
"bin/rspec #{example.location_rerun_argument}",
|
48
|
+
"bin/rspec --seed #{RSpec.configuration.seed} #{example.location_rerun_argument}",
|
48
49
|
RSpec.configuration.failure_color
|
49
50
|
)
|
50
51
|
|
data/lib/rspecq/queue.rb
CHANGED
@@ -51,8 +51,12 @@ module RSpecQ
|
|
51
51
|
REQUEUE_JOB = <<~LUA.freeze
|
52
52
|
local key_queue_unprocessed = KEYS[1]
|
53
53
|
local key_requeues = KEYS[2]
|
54
|
+
local key_requeued_job_original_worker = KEYS[3]
|
55
|
+
local key_job_location = KEYS[4]
|
54
56
|
local job = ARGV[1]
|
55
57
|
local max_requeues = ARGV[2]
|
58
|
+
local original_worker = ARGV[3]
|
59
|
+
local location = ARGV[4]
|
56
60
|
|
57
61
|
local requeued_times = redis.call('hget', key_requeues, job)
|
58
62
|
if requeued_times and requeued_times >= max_requeues then
|
@@ -60,7 +64,9 @@ module RSpecQ
|
|
60
64
|
end
|
61
65
|
|
62
66
|
redis.call('lpush', key_queue_unprocessed, job)
|
67
|
+
redis.call('hset', key_requeued_job_original_worker, job, original_worker)
|
63
68
|
redis.call('hincrby', key_requeues, job, 1)
|
69
|
+
redis.call('hset', key_job_location, job, location)
|
64
70
|
|
65
71
|
return true
|
66
72
|
LUA
|
@@ -117,6 +123,7 @@ module RSpecQ
|
|
117
123
|
@redis.multi do
|
118
124
|
@redis.hdel(key_queue_running, @worker_id)
|
119
125
|
@redis.sadd(key_queue_processed, job)
|
126
|
+
@redis.rpush(key("queue", "jobs_per_worker", @worker_id), job)
|
120
127
|
end
|
121
128
|
end
|
122
129
|
|
@@ -125,16 +132,41 @@ module RSpecQ
|
|
125
132
|
#
|
126
133
|
# Returns nil if the job hit the requeue limit and therefore was not
|
127
134
|
# requeued and should be considered a failure.
|
128
|
-
def requeue_job(
|
135
|
+
def requeue_job(example, max_requeues, original_worker_id)
|
129
136
|
return false if max_requeues.zero?
|
130
137
|
|
138
|
+
job = example.id
|
139
|
+
location = example.location_rerun_argument
|
140
|
+
|
131
141
|
@redis.eval(
|
132
142
|
REQUEUE_JOB,
|
133
|
-
keys: [key_queue_unprocessed, key_requeues],
|
134
|
-
argv: [job, max_requeues]
|
143
|
+
keys: [key_queue_unprocessed, key_requeues, key("requeued_job_original_worker"), key("job_location")],
|
144
|
+
argv: [job, max_requeues, original_worker_id, location]
|
135
145
|
)
|
136
146
|
end
|
137
147
|
|
148
|
+
def save_worker_seed(worker, seed)
|
149
|
+
@redis.hset(key("worker_seed"), worker, seed)
|
150
|
+
end
|
151
|
+
|
152
|
+
def job_location(job)
|
153
|
+
@redis.hget(key("job_location"), job)
|
154
|
+
end
|
155
|
+
|
156
|
+
def failed_job_worker(job)
|
157
|
+
redis.hget(key("requeued_job_original_worker"), job)
|
158
|
+
end
|
159
|
+
|
160
|
+
def job_rerun_command(job)
|
161
|
+
worker = failed_job_worker(job)
|
162
|
+
jobs = redis.lrange(key("queue", "jobs_per_worker", worker), 0, -1)
|
163
|
+
seed = redis.hget(key("worker_seed"), worker)
|
164
|
+
|
165
|
+
"DISABLE_SPRING=1 DISABLE_BOOTSNAP=1 bin/rspecq --build 1 " \
|
166
|
+
"--worker foo --seed #{seed} --max-requeues 0 --fail-fast 1 " \
|
167
|
+
"--reproduction #{jobs.join(' ')}"
|
168
|
+
end
|
169
|
+
|
138
170
|
def record_example_failure(example_id, message)
|
139
171
|
@redis.hset(key_failures, example_id, message)
|
140
172
|
end
|
data/lib/rspecq/reporter.rb
CHANGED
@@ -107,7 +107,16 @@ module RSpecQ
|
|
107
107
|
if !flaky_jobs.empty?
|
108
108
|
summary << "\n\n"
|
109
109
|
summary << "Flaky jobs detected (count=#{flaky_jobs.count}):\n"
|
110
|
-
flaky_jobs.each
|
110
|
+
flaky_jobs.each do |j|
|
111
|
+
summary << RSpec::Core::Formatters::ConsoleCodes.wrap(
|
112
|
+
"#{@queue.job_location(j)} @ #{@queue.failed_job_worker(j)}\n",
|
113
|
+
RSpec.configuration.pending_color
|
114
|
+
)
|
115
|
+
|
116
|
+
next if ENV["RSPECQ_REPORTER_RERUN_COMMAND_SKIP"]
|
117
|
+
|
118
|
+
summary << "#{@queue.job_rerun_command(j)}\n\n\n"
|
119
|
+
end
|
111
120
|
end
|
112
121
|
|
113
122
|
summary
|
@@ -125,16 +134,15 @@ module RSpecQ
|
|
125
134
|
return if jobs.empty?
|
126
135
|
|
127
136
|
jobs.each do |job|
|
128
|
-
filename = job.sub(/\[.+\]/, "")
|
137
|
+
filename = job.sub(/\[.+\]/, "")[%r{spec/.+}].split(":")[0]
|
129
138
|
|
130
139
|
extra = {
|
131
140
|
build: @build_id,
|
132
141
|
build_timeout: @timeout,
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
build_duration: build_duration
|
142
|
+
build_duration: build_duration,
|
143
|
+
location: @queue.job_location(job),
|
144
|
+
rerun_command: @queue.job_rerun_command(job),
|
145
|
+
worker: @queue.failed_job_worker(job)
|
138
146
|
}
|
139
147
|
|
140
148
|
tags = {
|
data/lib/rspecq/version.rb
CHANGED
data/lib/rspecq/worker.rb
CHANGED
@@ -51,6 +51,16 @@ module RSpecQ
|
|
51
51
|
# Defaults to 30
|
52
52
|
attr_accessor :queue_wait_timeout
|
53
53
|
|
54
|
+
# The RSpec seed
|
55
|
+
attr_accessor :seed
|
56
|
+
|
57
|
+
# Rspec tags
|
58
|
+
attr_accessor :tags
|
59
|
+
|
60
|
+
# Reproduction flag. If true, worker will publish files in the exact order
|
61
|
+
# given in the command.
|
62
|
+
attr_accessor :reproduction
|
63
|
+
|
54
64
|
attr_reader :queue
|
55
65
|
|
56
66
|
def initialize(build_id:, worker_id:, redis_opts:)
|
@@ -64,6 +74,9 @@ module RSpecQ
|
|
64
74
|
@heartbeat_updated_at = nil
|
65
75
|
@max_requeues = 3
|
66
76
|
@queue_wait_timeout = 30
|
77
|
+
@seed = srand && srand % 0xFFFF
|
78
|
+
@tags = []
|
79
|
+
@reproduction = false
|
67
80
|
|
68
81
|
RSpec::Core::Formatters.register(Formatters::JobTimingRecorder, :dump_summary)
|
69
82
|
RSpec::Core::Formatters.register(Formatters::ExampleCountRecorder, :dump_summary)
|
@@ -76,6 +89,7 @@ module RSpecQ
|
|
76
89
|
|
77
90
|
try_publish_queue!(queue)
|
78
91
|
queue.wait_until_published(queue_wait_timeout)
|
92
|
+
queue.save_worker_seed(@worker_id, seed)
|
79
93
|
|
80
94
|
loop do
|
81
95
|
# we have to bootstrap this so that it can be used in the first call
|
@@ -103,17 +117,19 @@ module RSpecQ
|
|
103
117
|
|
104
118
|
# reconfigure rspec
|
105
119
|
RSpec.configuration.detail_color = :magenta
|
106
|
-
RSpec.configuration.seed =
|
120
|
+
RSpec.configuration.seed = seed
|
107
121
|
RSpec.configuration.backtrace_formatter.filter_gem("rspecq")
|
108
|
-
RSpec.configuration.add_formatter(Formatters::FailureRecorder.new(queue, job, max_requeues))
|
122
|
+
RSpec.configuration.add_formatter(Formatters::FailureRecorder.new(queue, job, max_requeues, @worker_id))
|
109
123
|
RSpec.configuration.add_formatter(Formatters::ExampleCountRecorder.new(queue))
|
110
124
|
RSpec.configuration.add_formatter(Formatters::WorkerHeartbeatRecorder.new(self))
|
111
125
|
|
112
126
|
if populate_timings
|
113
127
|
RSpec.configuration.add_formatter(Formatters::JobTimingRecorder.new(queue, job))
|
114
128
|
end
|
115
|
-
|
116
|
-
|
129
|
+
|
130
|
+
options = ["--format", "progress", job]
|
131
|
+
tags.each { |tag| options.push(*["--tag", tag]) }
|
132
|
+
opts = RSpec::Core::ConfigurationOptions.new(options)
|
117
133
|
_result = RSpec::Core::Runner.new(opts).run($stderr, $stdout)
|
118
134
|
|
119
135
|
queue.acknowledge_job(job)
|
@@ -131,6 +147,14 @@ module RSpecQ
|
|
131
147
|
def try_publish_queue!(queue)
|
132
148
|
return if !queue.become_master
|
133
149
|
|
150
|
+
if reproduction
|
151
|
+
q_size = queue.publish(files_or_dirs_to_run, fail_fast)
|
152
|
+
log_event(
|
153
|
+
"Reproduction mode. Published queue as given (size=#{q_size})",
|
154
|
+
"info"
|
155
|
+
)
|
156
|
+
return
|
157
|
+
end
|
134
158
|
RSpec.configuration.files_or_directories_to_run = files_or_dirs_to_run
|
135
159
|
files_to_run = RSpec.configuration.files_to_run.map { |j| relative_path(j) }
|
136
160
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspecq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Agis Anastasopoulos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|