riteway 0.1.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 +7 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE +21 -0
- data/README.md +275 -0
- data/lib/riteway/match.rb +22 -0
- data/lib/riteway/minitest.rb +49 -0
- data/lib/riteway/rspec.rb +48 -0
- data/lib/riteway/version.rb +5 -0
- data/lib/riteway.rb +34 -0
- metadata +121 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6761c022b9dd95c5940eb0d3b373306d29aec20ef8b1b952bbe56e13f148fdaf
|
|
4
|
+
data.tar.gz: 4583be719e30bfaaa0d2174e727b07c647125681c552e032eb26beffda272670
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: efc1d4c26e6c2bb6660543b6106bc6853db6e4508ade85ea1a9ff3eaa25eb79771e314dcbcacde64971caaf5a131c5d1d6d26f7bf83bf0a1a9b5827c32ad9341
|
|
7
|
+
data.tar.gz: 7ad168dea1489678eebbb73fdef53ae15a1777f8e835ac816100045fa6dacf10407aebf6e00eb96b1fbb795e876d85b8c547593d5ea3bcbd009a3961ac89ff28
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-03-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `Riteway.assert` with RSpec and Minitest adapters
|
|
15
|
+
- `Riteway.attempt` for testing error cases
|
|
16
|
+
- `Riteway.count_keys` convenience helper
|
|
17
|
+
- `Riteway.match` curried text search
|
|
18
|
+
|
|
19
|
+
[unreleased]: https://github.com/mycargus/riteway-ruby/compare/v0.1.0...HEAD
|
|
20
|
+
[0.1.0]: https://github.com/mycargus/riteway-ruby/releases/tag/v0.1.0
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michael Hargiss
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Riteway Ruby
|
|
2
|
+
|
|
3
|
+
[](https://github.com/mycargus/riteway-ruby/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
**The standard testing assertion style for AI Driven Development (AIDD) and software agents.**
|
|
6
|
+
|
|
7
|
+
This is the Ruby port of the [riteway JavaScript library](https://github.com/paralleldrive/riteway).
|
|
8
|
+
|
|
9
|
+
Riteway is a testing assertion style and philosophy which leads to simple, readable, helpful unit tests for humans and AI agents.
|
|
10
|
+
|
|
11
|
+
It lets you write better, more readable tests with a fraction of the code that traditional assertion frameworks would use.
|
|
12
|
+
|
|
13
|
+
Riteway is the AI-native way to build a modern test suite. It pairs well with RSpec, Claude Code, Cursor Agent, and more.
|
|
14
|
+
|
|
15
|
+
* **R**eadable
|
|
16
|
+
* **I**solated/**I**ntegrated
|
|
17
|
+
* **T**horough
|
|
18
|
+
* **E**xplicit
|
|
19
|
+
|
|
20
|
+
Riteway forces you to write **R**eadable, **I**solated, and **E**xplicit tests, because that's the only way you can use the API. It also makes it easier to be thorough by making test assertions so simple that you'll want to write more of them.
|
|
21
|
+
|
|
22
|
+
## Why Riteway for AI Driven Development?
|
|
23
|
+
|
|
24
|
+
Riteway's structured approach makes it ideal for AIDD:
|
|
25
|
+
|
|
26
|
+
**📖 Learn more:** [Better AI Driven Development with Test Driven Development](https://medium.com/effortless-programming/better-ai-driven-development-with-test-driven-development-d4849f67e339)
|
|
27
|
+
|
|
28
|
+
- **Clear requirements**: The given/should structure and 5-question framework help AI better understand exactly what to build
|
|
29
|
+
- **Readable by design**: Natural language descriptions make tests comprehensible to both humans and AI
|
|
30
|
+
- **Simple API**: Minimal surface area reduces AI confusion and hallucinations
|
|
31
|
+
- **Token efficient**: Concise syntax saves valuable context window space
|
|
32
|
+
|
|
33
|
+
## The 5 Questions Every Test Must Answer
|
|
34
|
+
|
|
35
|
+
There are [5 questions every unit test must answer](https://medium.com/javascript-scene/what-every-unit-test-needs-f6cd34d9836d). Riteway forces you to answer them.
|
|
36
|
+
|
|
37
|
+
1. What is the unit under test (module, function, class, whatever)?
|
|
38
|
+
2. What should it do? (Prose description)
|
|
39
|
+
3. What was the actual output?
|
|
40
|
+
4. What was the expected output?
|
|
41
|
+
5. How do you reproduce the failure?
|
|
42
|
+
|
|
43
|
+
## Installing
|
|
44
|
+
|
|
45
|
+
Add to your `Gemfile`:
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
gem "riteway"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or install directly:
|
|
52
|
+
|
|
53
|
+
```shell
|
|
54
|
+
gem install riteway
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Then require the adapter for your test framework. Use one or the other — not both.
|
|
58
|
+
|
|
59
|
+
**RSpec** — require in `spec/spec_helper.rb`:
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
require "riteway/rspec"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Optional: filter Riteway internals from RSpec backtraces so failures point directly to your test code:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
RSpec.configure do |config|
|
|
69
|
+
config.backtrace_exclusion_patterns << /lib\/riteway/
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Minitest** — require in `test/test_helper.rb`:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
require "minitest/autorun"
|
|
77
|
+
require "riteway/minitest"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Minitest ships with Ruby's standard library — no extra gem needed.
|
|
81
|
+
|
|
82
|
+
## Example Usage
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
require "riteway/rspec"
|
|
86
|
+
|
|
87
|
+
# A function to test
|
|
88
|
+
def sum(*args)
|
|
89
|
+
args.each { |n| raise TypeError, "Not a number: #{n.inspect}" unless n.is_a?(Numeric) }
|
|
90
|
+
args.reduce(0, :+)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
RSpec.describe "sum()" do
|
|
94
|
+
it "given no arguments, should return 0" do
|
|
95
|
+
Riteway.assert(
|
|
96
|
+
given: "no arguments",
|
|
97
|
+
should: "return 0",
|
|
98
|
+
actual: sum(),
|
|
99
|
+
expected: 0
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "given zero, should return the correct sum" do
|
|
104
|
+
Riteway.assert(
|
|
105
|
+
given: "zero",
|
|
106
|
+
should: "return the correct sum",
|
|
107
|
+
actual: sum(2, 0),
|
|
108
|
+
expected: 2
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "given negative numbers, should return the correct sum" do
|
|
113
|
+
Riteway.assert(
|
|
114
|
+
given: "negative numbers",
|
|
115
|
+
should: "return the correct sum",
|
|
116
|
+
actual: sum(1, -4),
|
|
117
|
+
expected: -3
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "given a non-numeric argument, should raise TypeError" do
|
|
122
|
+
error = Riteway.attempt(method(:sum), 1, "NaN")
|
|
123
|
+
|
|
124
|
+
Riteway.assert(
|
|
125
|
+
given: "a non-numeric argument",
|
|
126
|
+
should: "raise TypeError",
|
|
127
|
+
actual: error.class,
|
|
128
|
+
expected: TypeError
|
|
129
|
+
)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Output
|
|
135
|
+
|
|
136
|
+
Riteway uses your test framework's output. The failure message always includes the given/should context; the diff format varies slightly between RSpec (colorized diff) and Minitest (simple expected/got lines).
|
|
137
|
+
|
|
138
|
+
For RSpec, use `--format documentation` for full prose output:
|
|
139
|
+
|
|
140
|
+
```shell
|
|
141
|
+
bundle exec rspec --format documentation
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
sum()
|
|
146
|
+
given no arguments, should return 0
|
|
147
|
+
given zero, should return the correct sum
|
|
148
|
+
given negative numbers, should return the correct sum
|
|
149
|
+
given a non-numeric argument, should raise TypeError
|
|
150
|
+
|
|
151
|
+
Finished in 0.00112 seconds
|
|
152
|
+
4 examples, 0 failures
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
When a test fails, the given/should context is always included in the error:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
Given negative numbers: should return the correct sum
|
|
159
|
+
expected: -3
|
|
160
|
+
got: 0
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## API
|
|
164
|
+
|
|
165
|
+
### `Riteway.assert`
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
Riteway.assert(given:, should:, actual:, expected:) => void, raises
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The core assertion. Takes keyword arguments and compares `actual` to `expected` using deep equality (`eq`). All four arguments are required — missing any raises Ruby's native `ArgumentError`.
|
|
172
|
+
|
|
173
|
+
`assert` uses RSpec's `eq` matcher, which handles deep comparison of arrays, hashes, and nested structures.
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
Riteway.assert(
|
|
177
|
+
given: "an array of numbers",
|
|
178
|
+
should: "equal the expected array",
|
|
179
|
+
actual: [1, 2, 3].map { |n| n * 2 },
|
|
180
|
+
expected: [2, 4, 6]
|
|
181
|
+
)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### `Riteway.attempt`
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
Riteway.attempt(callable = nil, *args, **kwargs, &block) => Error | Any
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Execute a callable or block with the given arguments. Returns the error if one is raised, otherwise returns the result. Designed for testing error cases in your assertions. Supports positional args, keyword args, lambdas, procs, and blocks.
|
|
191
|
+
|
|
192
|
+
`attempt` catches `StandardError` and its subclasses only. Exceptions outside this hierarchy — `SystemExit`, `Interrupt`, `SignalException` — propagate normally. Note that RSpec's `ExpectationNotMetError` inherits from `Exception` (not `StandardError`), so it propagates through `attempt` rather than being caught and returned.
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
# Block form (most concise)
|
|
196
|
+
error = Riteway.attempt { Integer("not a number") }
|
|
197
|
+
|
|
198
|
+
# Lambda form
|
|
199
|
+
error = Riteway.attempt(-> { Integer("not a number") })
|
|
200
|
+
|
|
201
|
+
# Method reference with positional args
|
|
202
|
+
error = Riteway.attempt(method(:sum), 1, "NaN")
|
|
203
|
+
|
|
204
|
+
# Method reference with keyword args
|
|
205
|
+
result = Riteway.attempt(method(:create_user), name: "Alice", age: 30)
|
|
206
|
+
|
|
207
|
+
Riteway.assert(
|
|
208
|
+
given: "a non-numeric string",
|
|
209
|
+
should: "raise ArgumentError",
|
|
210
|
+
actual: error.class,
|
|
211
|
+
expected: ArgumentError
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### `Riteway.count_keys`
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
Riteway.count_keys(hash = {}) => Integer
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Given a hash, return a count of its keys. Defaults to `{}` (returns `0`) when called with no arguments. A convenience wrapper for `hash.keys.length` that reads naturally inside a `Riteway.assert` call. Handy when you're adding new state to a hash keyed by ID and want to ensure the correct number of keys were added.
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
Riteway.assert(
|
|
225
|
+
given: "a hash with 3 keys",
|
|
226
|
+
should: "return 3",
|
|
227
|
+
actual: Riteway.count_keys({ a: 1, b: 2, c: 3 }),
|
|
228
|
+
expected: 3
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### `Riteway.match`
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
Riteway.match(text) => ->(pattern) => String
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Take some text to search and return a lambda which takes a pattern and returns the matched text, or `nil` if no match — consistent with Ruby's own `String#match`. The pattern can be a String or Regexp. String patterns are auto-escaped so regex meta-characters are treated as literals.
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
contains = Riteway.match("<h1>Dialog Title</h1>")
|
|
242
|
+
|
|
243
|
+
Riteway.assert(
|
|
244
|
+
given: "some text and a string pattern",
|
|
245
|
+
should: "return the matched text",
|
|
246
|
+
actual: contains.call("Dialog Title"),
|
|
247
|
+
expected: "Dialog Title"
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
Riteway.assert(
|
|
251
|
+
given: "some text and a regex pattern",
|
|
252
|
+
should: "return the matched text",
|
|
253
|
+
actual: contains.call(/\w+/),
|
|
254
|
+
expected: "Dialog"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
Riteway.assert(
|
|
258
|
+
given: "a pattern that does not match",
|
|
259
|
+
should: "return nil",
|
|
260
|
+
actual: contains.call("not found"),
|
|
261
|
+
expected: nil
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
You can also use `contains.("pattern")` or `contains["pattern"]` as shorthand for `.call`.
|
|
266
|
+
|
|
267
|
+
## Publishing
|
|
268
|
+
|
|
269
|
+
See [RELEASING.md](RELEASING.md) for the full release process.
|
|
270
|
+
|
|
271
|
+
`rake release` is intentionally disabled to prevent automated publishing.
|
|
272
|
+
|
|
273
|
+
## License
|
|
274
|
+
|
|
275
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Riteway
|
|
4
|
+
# Returns a lambda that searches text for a pattern (String or Regexp).
|
|
5
|
+
# Returns the matched text on success, or nil if no match — consistent with
|
|
6
|
+
# Ruby's String#match which also returns nil on no match.
|
|
7
|
+
def self.match(text)
|
|
8
|
+
raise TypeError, "match expects a String, got #{text.class}" unless text.is_a?(String)
|
|
9
|
+
|
|
10
|
+
->(pattern) {
|
|
11
|
+
unless pattern.is_a?(String) || pattern.is_a?(Regexp)
|
|
12
|
+
raise TypeError,
|
|
13
|
+
"pattern must be a String or Regexp, got #{pattern.class}"
|
|
14
|
+
end
|
|
15
|
+
raise ArgumentError, "pattern must not be empty" if pattern.is_a?(String) && pattern.empty?
|
|
16
|
+
|
|
17
|
+
re = pattern.is_a?(String) ? Regexp.new(Regexp.escape(pattern)) : pattern
|
|
18
|
+
matched = text.match(re)
|
|
19
|
+
matched ? matched[0] : nil
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest"
|
|
4
|
+
require "riteway"
|
|
5
|
+
|
|
6
|
+
module Riteway
|
|
7
|
+
if defined?(ADAPTER)
|
|
8
|
+
raise LoadError,
|
|
9
|
+
"riteway: adapter conflict — #{ADAPTER} already loaded. " \
|
|
10
|
+
"Only require one adapter (riteway/rspec or riteway/minitest)."
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
ADAPTER = :minitest
|
|
14
|
+
|
|
15
|
+
module MinitestLifecycle
|
|
16
|
+
def before_setup
|
|
17
|
+
super
|
|
18
|
+
Thread.current[:riteway_minitest_context] = self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def after_teardown
|
|
22
|
+
Thread.current[:riteway_minitest_context] = nil
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.assert(given:, should:, actual:, expected:)
|
|
28
|
+
ctx = Thread.current[:riteway_minitest_context]
|
|
29
|
+
unless ctx
|
|
30
|
+
raise "Riteway.assert must be called inside an it/test block. " \
|
|
31
|
+
"Ensure `require \"riteway/minitest\"` is in your test_helper.rb " \
|
|
32
|
+
"and that assert is only called from within a test context."
|
|
33
|
+
end
|
|
34
|
+
unless given.is_a?(String) && !given.empty?
|
|
35
|
+
raise ArgumentError,
|
|
36
|
+
"given: must be a non-empty String, got #{given.inspect}"
|
|
37
|
+
end
|
|
38
|
+
unless should.is_a?(String) && !should.empty?
|
|
39
|
+
raise ArgumentError,
|
|
40
|
+
"should: must be a non-empty String, got #{should.inspect}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
message = "Given #{given}: should #{should}"
|
|
44
|
+
expected.nil? ? ctx.assert_nil(actual, message) : ctx.assert_equal(expected, actual, message)
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Minitest::Test.include Riteway::MinitestLifecycle
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require "rspec/expectations"
|
|
5
|
+
require "rspec/matchers"
|
|
6
|
+
rescue LoadError
|
|
7
|
+
raise LoadError,
|
|
8
|
+
"riteway/rspec requires the 'rspec' gem. Add `gem \"rspec\"` to your Gemfile, " \
|
|
9
|
+
"or use `require \"riteway/minitest\"` for Minitest."
|
|
10
|
+
end
|
|
11
|
+
require "riteway"
|
|
12
|
+
|
|
13
|
+
module Riteway
|
|
14
|
+
if defined?(ADAPTER)
|
|
15
|
+
raise LoadError,
|
|
16
|
+
"riteway: adapter conflict — #{ADAPTER} already loaded. " \
|
|
17
|
+
"Only require one adapter (riteway/rspec or riteway/minitest)."
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
ADAPTER = :rspec
|
|
21
|
+
|
|
22
|
+
# Internal — not part of the public API. Isolates RSpec matcher methods
|
|
23
|
+
# so they don't pollute Riteway's module namespace.
|
|
24
|
+
module RSpecBridge
|
|
25
|
+
extend RSpec::Matchers
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.assert(given:, should:, actual:, expected:)
|
|
29
|
+
unless RSpec.respond_to?(:current_example) && RSpec.current_example
|
|
30
|
+
raise "Riteway.assert must be called inside an it/specify block, not at describe-level. " \
|
|
31
|
+
"Move this assertion inside an `it` block."
|
|
32
|
+
end
|
|
33
|
+
unless given.is_a?(String) && !given.empty?
|
|
34
|
+
raise ArgumentError,
|
|
35
|
+
"given: must be a non-empty String, got #{given.inspect}"
|
|
36
|
+
end
|
|
37
|
+
unless should.is_a?(String) && !should.empty?
|
|
38
|
+
raise ArgumentError,
|
|
39
|
+
"should: must be a non-empty String, got #{should.inspect}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
matcher = RSpecBridge.eq(expected)
|
|
43
|
+
return if matcher.matches?(actual)
|
|
44
|
+
|
|
45
|
+
raise RSpec::Expectations::ExpectationNotMetError,
|
|
46
|
+
"Given #{given}: should #{should}\n#{matcher.failure_message}"
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/riteway.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "riteway/version"
|
|
4
|
+
require_relative "riteway/match"
|
|
5
|
+
|
|
6
|
+
module Riteway
|
|
7
|
+
def self.assert(**)
|
|
8
|
+
raise "Riteway.assert requires an adapter. " \
|
|
9
|
+
"Add `require \"riteway/rspec\"` or `require \"riteway/minitest\"` to your test helper."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Calls callable (or block) with given args. Returns the error if raised,
|
|
13
|
+
# otherwise returns the result. Catches StandardError and subclasses only —
|
|
14
|
+
# SystemExit, Interrupt, SignalException, etc. propagate normally.
|
|
15
|
+
def self.attempt(callable = nil, *args, **kwargs, &block)
|
|
16
|
+
raise ArgumentError, "attempt accepts a callable or a block, not both" if callable && block
|
|
17
|
+
|
|
18
|
+
fn = callable || block
|
|
19
|
+
raise ArgumentError, "attempt requires a callable or a block" unless fn
|
|
20
|
+
raise ArgumentError, "attempt expects a callable (responds to #call), got #{fn.class}" unless fn.respond_to?(:call)
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
kwargs.empty? ? fn.call(*args) : fn.call(*args, **kwargs)
|
|
24
|
+
rescue => error
|
|
25
|
+
error
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.count_keys(hash = {})
|
|
30
|
+
raise TypeError, "count_keys expects a Hash, got #{hash.class}" unless hash.is_a?(Hash)
|
|
31
|
+
|
|
32
|
+
hash.keys.length
|
|
33
|
+
end
|
|
34
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: riteway
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Michael Hargiss
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '13.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '13.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rubocop
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec-expectations
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: minitest
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '5.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '5.0'
|
|
82
|
+
description: Ruby port of the riteway JavaScript testing library.
|
|
83
|
+
executables: []
|
|
84
|
+
extensions: []
|
|
85
|
+
extra_rdoc_files: []
|
|
86
|
+
files:
|
|
87
|
+
- CHANGELOG.md
|
|
88
|
+
- LICENSE
|
|
89
|
+
- README.md
|
|
90
|
+
- lib/riteway.rb
|
|
91
|
+
- lib/riteway/match.rb
|
|
92
|
+
- lib/riteway/minitest.rb
|
|
93
|
+
- lib/riteway/rspec.rb
|
|
94
|
+
- lib/riteway/version.rb
|
|
95
|
+
homepage: https://github.com/mycargus/riteway-ruby
|
|
96
|
+
licenses:
|
|
97
|
+
- MIT
|
|
98
|
+
metadata:
|
|
99
|
+
allowed_push_host: https://rubygems.org
|
|
100
|
+
homepage_uri: https://github.com/mycargus/riteway-ruby
|
|
101
|
+
source_code_uri: https://github.com/mycargus/riteway-ruby
|
|
102
|
+
changelog_uri: https://github.com/mycargus/riteway-ruby/blob/main/CHANGELOG.md
|
|
103
|
+
bug_tracker_uri: https://github.com/mycargus/riteway-ruby/issues
|
|
104
|
+
rdoc_options: []
|
|
105
|
+
require_paths:
|
|
106
|
+
- lib
|
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '3.0'
|
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
requirements: []
|
|
118
|
+
rubygems_version: 3.6.9
|
|
119
|
+
specification_version: 4
|
|
120
|
+
summary: Unit tests that always supply a good bug report when they fail.
|
|
121
|
+
test_files: []
|