ruby_llm-test 0.1.0 → 0.3.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 +4 -4
- data/README.md +51 -17
- data/lib/ruby_llm/test/complete_parameters.rb +58 -16
- data/lib/ruby_llm/test/harness.rb +65 -0
- data/lib/ruby_llm/test/resolve_with_test_provider.rb +1 -1
- data/lib/ruby_llm/test/test_provider.rb +11 -18
- data/lib/ruby_llm/test/version.rb +1 -1
- data/lib/ruby_llm/test.rb +92 -20
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef753ca266479d9530fb44f0660cb2292bc916c2c949376c65686488bd41f5d9
|
|
4
|
+
data.tar.gz: f96175266a8866d9038b529b37ae0f099f1b20cdf677f591ab36acc941e566bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e58becb7a4ae7b1d2248746f8aad685aa5a382307fe8c57887d0b6d2c170e35ffc4e97ae095cc0601ebf17e50de3374cab6060619c6ba57adfed4c85f5be576b
|
|
7
|
+
data.tar.gz: 76456e9ec3ed46ec76eafbae1bdebe6fd9598cce423f527c505028a43520dfa01c538341fd28c71fddfd70f36d7c47410b2cfb2fb8425fa6ba0abe6ccc6aac55
|
data/README.md
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/ruby_llm-test)
|
|
2
|
+
[](https://github.com/RockSolt/ruby_llm-test/actions/workflows/test.yml)
|
|
3
|
+
[](https://github.com/RockSolt/ruby_llm-test/actions/workflows/rubocop.yml)
|
|
4
|
+
|
|
1
5
|
# RubyLLM::Test
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
How do you test your business logic when it interacts with large language models (LLMs)? From a testing point of view, an LLM is just an external system. To keep tests fast and consistent, pick a boundary then stub or mock the external system.
|
|
8
|
+
|
|
9
|
+
Part of the appeal of the RubyLLM library is that code using it does not need to know the specifics of provider APIs. The RubyLLM::Test gem brings the same benefit to your tests. No API or provider-specific knowledge is required to stub calls.
|
|
10
|
+
|
|
11
|
+
Simple stubs make for simple tests. Keep your tests fast, consistent, and thorough with RubyLLM::Test!
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
RubyLLM::Test.stub_response("Outlook good")
|
|
15
|
+
|
|
16
|
+
chat = RubyLLM.chat
|
|
17
|
+
response = chat.ask "What are the odds this works?"
|
|
18
|
+
|
|
19
|
+
assert_equal "Outlook good", response.content
|
|
20
|
+
```
|
|
4
21
|
|
|
5
22
|
## Installation
|
|
6
23
|
|
|
7
|
-
Add this line to your application's Gemfile:
|
|
24
|
+
Add this line to your application's Gemfile in the test group:
|
|
8
25
|
|
|
9
26
|
```ruby
|
|
10
27
|
gem 'ruby_llm-test'
|
|
@@ -20,7 +37,7 @@ Or install it yourself as:
|
|
|
20
37
|
|
|
21
38
|
## Usage
|
|
22
39
|
|
|
23
|
-
Add the following lines to your `
|
|
40
|
+
Add the following lines to your `spec_helper.rb` or `test_helper.rb`:
|
|
24
41
|
|
|
25
42
|
```ruby
|
|
26
43
|
require 'ruby_llm/test'
|
|
@@ -34,21 +51,22 @@ Then, in your tests, you can use the `stub_response` method to stub responses fr
|
|
|
34
51
|
it 'returns a stubbed response' do
|
|
35
52
|
RubyLLM::Test.stub_response('Hello, world!')
|
|
36
53
|
|
|
37
|
-
response =
|
|
38
|
-
expect(response).to eq('Hello, world!')
|
|
54
|
+
response = RubyLLM.chat.ask 'Hello?'
|
|
55
|
+
expect(response.content).to eq('Hello, world!')
|
|
39
56
|
end
|
|
40
57
|
```
|
|
41
58
|
|
|
42
|
-
If you make multiple calls to the LLM, you can call `stub_response` more than once or use
|
|
59
|
+
If you make multiple calls to the LLM, you can call `stub_response` more than once or use the `stub_responses` method to stub multiple responses at once. For example:
|
|
43
60
|
|
|
44
61
|
```ruby
|
|
45
62
|
it 'returns multiple stubbed responses' do
|
|
46
|
-
RubyLLM::Test.stub_responses('
|
|
47
|
-
|
|
48
|
-
|
|
63
|
+
RubyLLM::Test.stub_responses('Blue.', 'No, yellow.')
|
|
64
|
+
chat = RubyLLM.chat
|
|
65
|
+
response1 = chat.ask 'What is your favorite color?'
|
|
66
|
+
response2 = chat.ask 'Are you sure?'
|
|
49
67
|
|
|
50
|
-
expect(response1).to eq('
|
|
51
|
-
expect(response2).to eq('
|
|
68
|
+
expect(response1.content).to eq('Blue.')
|
|
69
|
+
expect(response2.content).to eq('No, yellow.')
|
|
52
70
|
end
|
|
53
71
|
```
|
|
54
72
|
|
|
@@ -61,7 +79,7 @@ it 'returns a stubbed message' do
|
|
|
61
79
|
message = RubyLLM::Message.new(role: :assistant, content: 'Hello, world!')
|
|
62
80
|
RubyLLM::Test.stub_response(message)
|
|
63
81
|
|
|
64
|
-
response =
|
|
82
|
+
response = RubyLLM.chat.ask 'Hello?'
|
|
65
83
|
expect(response).to eq(message)
|
|
66
84
|
end
|
|
67
85
|
```
|
|
@@ -75,14 +93,14 @@ it 'returns a stubbed JSON message' do
|
|
|
75
93
|
hash = { key: 'value' }
|
|
76
94
|
RubyLLM::Test.stub_response(hash)
|
|
77
95
|
|
|
78
|
-
response =
|
|
96
|
+
response = RubyLLM.chat.ask 'Hello?'
|
|
79
97
|
expect(response.content).to eq(hash.to_json)
|
|
80
98
|
end
|
|
81
99
|
```
|
|
82
100
|
|
|
83
101
|
### Resetting Stubs
|
|
84
102
|
|
|
85
|
-
|
|
103
|
+
Reset stubs before each test to ensure a clean slate.
|
|
86
104
|
|
|
87
105
|
```ruby
|
|
88
106
|
RubyLLM::Test.reset
|
|
@@ -93,13 +111,29 @@ RubyLLM::Test.reset
|
|
|
93
111
|
You can also stub responses in a block, which handles the setup and teardown of stubs automatically. For example:
|
|
94
112
|
|
|
95
113
|
```ruby
|
|
96
|
-
|
|
97
114
|
RubyLLM::Test.with_responses('Hello, world!') do
|
|
98
|
-
response =
|
|
99
|
-
expect(response).to eq('Hello, world!')
|
|
115
|
+
response = RubyLLM.chat.ask 'Hello?'
|
|
116
|
+
expect(response.content).to eq('Hello, world!')
|
|
100
117
|
end
|
|
101
118
|
```
|
|
102
119
|
|
|
120
|
+
### Testing Arguments
|
|
121
|
+
|
|
122
|
+
You can verify arguments passed to the LLM by checking the requests received by the test provider with methods `requests` and `last_request`.
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
RubyLLM::Test.stub_response('Hello, world!')
|
|
126
|
+
chat = RubyLLM.chat(model: 'gpt-5-nano')
|
|
127
|
+
chat.with_tools(GreeterTool)
|
|
128
|
+
chat.ask('Hello?')
|
|
129
|
+
request = RubyLLM::Test.last_request
|
|
130
|
+
|
|
131
|
+
assert_equal 'gpt-5-nano', request.model
|
|
132
|
+
assert_includes request.tool_classes, GreeterTool
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Any parameters passed to the Provider's `complete` method are available on the request object. The `tool_classes` method is a helper that returns the classes of any tools included in the request.
|
|
136
|
+
|
|
103
137
|
## Development
|
|
104
138
|
|
|
105
139
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -2,27 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
module RubyLLM
|
|
4
4
|
module Test
|
|
5
|
-
# This class encapsulates all the parameters that are passed to the `complete` method of the
|
|
6
|
-
#
|
|
5
|
+
# This class encapsulates all the parameters that are passed to the `complete` method of the wrapped provider. It
|
|
6
|
+
# stores the raw arguments and uses the wrapped provider's actual method signature to expose named accessors for
|
|
7
|
+
# inspection in tests.
|
|
7
8
|
class CompleteParameters
|
|
8
|
-
attr_reader :
|
|
9
|
-
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@
|
|
17
|
-
@
|
|
18
|
-
@schema = schema
|
|
19
|
-
@thinking = thinking
|
|
20
|
-
@tool_prefs = tool_prefs
|
|
9
|
+
attr_reader :args, :kwargs, :block, :parameter_definitions
|
|
10
|
+
|
|
11
|
+
def self.capture_from(provider, *args, **kwargs, &block)
|
|
12
|
+
parameters = provider.method(:complete).parameters
|
|
13
|
+
new(args:, kwargs:, block:, parameter_definitions: parameters)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(args:, kwargs:, block:, parameter_definitions:)
|
|
17
|
+
@args = args
|
|
18
|
+
@kwargs = kwargs
|
|
21
19
|
@block = block
|
|
20
|
+
@parameter_definitions = parameter_definitions
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def block_received?
|
|
25
|
-
|
|
24
|
+
!block.nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def [](name)
|
|
28
|
+
name = name.to_sym
|
|
29
|
+
return block if name == :block
|
|
30
|
+
|
|
31
|
+
positional_name_to_value[name] || kwargs[name]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def key?(name)
|
|
35
|
+
name = name.to_sym
|
|
36
|
+
name == :block || positional_name_to_value.key?(name) || kwargs.key?(name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_h
|
|
40
|
+
positional_name_to_value.merge(kwargs).merge(block: block)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def method_missing(name, *call_args)
|
|
44
|
+
return super unless call_args.empty?
|
|
45
|
+
return self[name] if key?(name)
|
|
46
|
+
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def respond_to_missing?(name, include_private = false)
|
|
51
|
+
key?(name) || super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def tool_classes
|
|
55
|
+
(kwargs[:tools] || {}).values.map(&:class)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def positional_name_to_value
|
|
61
|
+
@positional_name_to_value ||= begin
|
|
62
|
+
positional_names = parameter_definitions
|
|
63
|
+
.select { |parameter| %i[req opt].include?(parameter.first) }
|
|
64
|
+
.map(&:last)
|
|
65
|
+
|
|
66
|
+
positional_names.each_with_index.to_h { |param_name, index| [ param_name, args[index] ] }
|
|
67
|
+
end
|
|
26
68
|
end
|
|
27
69
|
end
|
|
28
70
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyLLM
|
|
4
|
+
module Test
|
|
5
|
+
# This class serves as a test harness for stubbing responses and recording requests sent to the provider.
|
|
6
|
+
# It allows tests to set up expected responses and then verify that the provider received the correct
|
|
7
|
+
# parameters.
|
|
8
|
+
class Harness
|
|
9
|
+
attr_reader :requests
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
reset
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Pass in a RubyLLM::Message to have full control; strings and hashes will be wrapped in a message
|
|
16
|
+
def stub_response(body)
|
|
17
|
+
responses << body
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def stub_responses(*bodies)
|
|
21
|
+
responses.concat(bodies)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def with_responses(*bodies)
|
|
25
|
+
previous_responses = responses.dup
|
|
26
|
+
@responses = []
|
|
27
|
+
stub_responses(*bodies)
|
|
28
|
+
yield
|
|
29
|
+
ensure
|
|
30
|
+
@responses = previous_responses
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def next_response
|
|
34
|
+
responses.shift
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def responses_empty?
|
|
38
|
+
responses.empty?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def record_request(request)
|
|
42
|
+
requests << request
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def last_request
|
|
46
|
+
requests.last
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def clear_requests
|
|
50
|
+
requests.clear
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def reset
|
|
54
|
+
@responses = []
|
|
55
|
+
@requests = []
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def responses
|
|
61
|
+
@responses ||= []
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -12,7 +12,7 @@ module RubyLLM
|
|
|
12
12
|
module ResolveWithTestProvider
|
|
13
13
|
def resolve(...)
|
|
14
14
|
model, provider_instance = super
|
|
15
|
-
[ model, Test::TestProvider.new(provider_instance, RubyLLM::Test) ]
|
|
15
|
+
[ model, Test::TestProvider.new(provider_instance, RubyLLM::Test.send(:harness)) ]
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -6,24 +6,21 @@ module RubyLLM
|
|
|
6
6
|
# the `complete` method, allowing tests to assert that the correct parameters were passed and to simulate
|
|
7
7
|
# responses from the provider.
|
|
8
8
|
class TestProvider < SimpleDelegator
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
attr_reader :complete_calls
|
|
12
|
-
|
|
13
|
-
def_delegators :last_call, :messages, :tools, :temperature, :model, :params, :headers, :schema, :thinking,
|
|
14
|
-
:tool_prefs, :block_received?
|
|
15
|
-
|
|
16
|
-
def initialize(provider, test_harness = RubyLLM::Test)
|
|
9
|
+
def initialize(provider, test_harness)
|
|
17
10
|
super(provider)
|
|
18
11
|
@test_harness = test_harness
|
|
19
|
-
@complete_calls = []
|
|
20
12
|
end
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
# There are a number of cases that access `provider.class.display_name`, which avoids the delegation. Adding
|
|
15
|
+
# dummy stub for this. TBD if this needs to be more sophisticated in the future.
|
|
16
|
+
def self.display_name
|
|
17
|
+
"TestProvider"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def complete(...)
|
|
21
|
+
parameters = CompleteParameters.capture_from(__getobj__, ...)
|
|
22
|
+
@test_harness.record_request(parameters)
|
|
23
|
+
raise Errors::NoResponseProvidedError, parameters.messages if @test_harness.responses_empty?
|
|
27
24
|
|
|
28
25
|
response = @test_harness.next_response
|
|
29
26
|
return response if response.is_a?(Message)
|
|
@@ -33,10 +30,6 @@ module RubyLLM
|
|
|
33
30
|
content: response.is_a?(Hash) ? response.to_json : response
|
|
34
31
|
)
|
|
35
32
|
end
|
|
36
|
-
|
|
37
|
-
def last_call
|
|
38
|
-
@complete_calls.last
|
|
39
|
-
end
|
|
40
33
|
end
|
|
41
34
|
end
|
|
42
35
|
end
|
data/lib/ruby_llm/test.rb
CHANGED
|
@@ -7,43 +7,115 @@ loader = Zeitwerk::Loader.for_gem_extension(RubyLLM)
|
|
|
7
7
|
loader.setup
|
|
8
8
|
|
|
9
9
|
module RubyLLM
|
|
10
|
-
# The Test module provides a simple way to stub responses from an LLM for testing purposes.
|
|
11
|
-
#
|
|
12
|
-
#
|
|
10
|
+
# The Test module provides a simple way to stub responses from an LLM for testing purposes.
|
|
11
|
+
# You can use it to set up predetermined responses that your tests can rely on, allowing
|
|
12
|
+
# you to test your code's behavior without making actual calls to an LLM.
|
|
13
13
|
module Test
|
|
14
14
|
class << self
|
|
15
|
+
# Reset the test harness state.
|
|
16
|
+
#
|
|
17
|
+
# This clears all queued stubbed responses and all recorded requests.
|
|
18
|
+
#
|
|
19
|
+
# Use this at the start of a test, or whenever you want to ensure no state
|
|
20
|
+
# carries over from a previous example.
|
|
15
21
|
def reset
|
|
16
|
-
|
|
22
|
+
harness.reset
|
|
17
23
|
end
|
|
18
24
|
|
|
19
|
-
#
|
|
25
|
+
# Queue a single stubbed response.
|
|
26
|
+
#
|
|
27
|
+
# Parameters:
|
|
28
|
+
#
|
|
29
|
+
# - `body`: The response to queue. Pass a `RubyLLM::Message` to control the
|
|
30
|
+
# message directly. Strings and hashes are wrapped in a message
|
|
31
|
+
# automatically.
|
|
32
|
+
#
|
|
33
|
+
# This is useful when your test only needs one response from the model.
|
|
34
|
+
#
|
|
35
|
+
# Example:
|
|
36
|
+
#
|
|
37
|
+
# RubyLLM::Test.stub_response("Hello from the test harness!")
|
|
38
|
+
#
|
|
39
|
+
# chat = RubyLLM.chat
|
|
40
|
+
# response = chat.ask("Say hello")
|
|
41
|
+
# response.content
|
|
42
|
+
# # => "Hello from the test harness!"
|
|
20
43
|
def stub_response(body)
|
|
21
|
-
|
|
44
|
+
harness.stub_response(body)
|
|
22
45
|
end
|
|
23
46
|
|
|
47
|
+
# Queue multiple stubbed responses.
|
|
48
|
+
#
|
|
49
|
+
# Parameters:
|
|
50
|
+
#
|
|
51
|
+
# - `*bodies`: One or more responses to queue.
|
|
52
|
+
#
|
|
53
|
+
# Responses are returned in the same order they are provided, making this
|
|
54
|
+
# useful for tests that perform multiple LLM calls in sequence.
|
|
55
|
+
#
|
|
56
|
+
# Example:
|
|
57
|
+
#
|
|
58
|
+
# RubyLLM::Test.stub_responses("First reply", "Second reply")
|
|
59
|
+
#
|
|
60
|
+
# chat = RubyLLM.chat
|
|
61
|
+
# first_response = chat.ask("First question")
|
|
62
|
+
# second_response = chat.ask("Second question")
|
|
63
|
+
#
|
|
64
|
+
# first_response.content
|
|
65
|
+
# # => "First reply"
|
|
66
|
+
# second_response.content
|
|
67
|
+
# # => "Second reply"
|
|
24
68
|
def stub_responses(*bodies)
|
|
25
|
-
|
|
69
|
+
harness.stub_responses(*bodies)
|
|
26
70
|
end
|
|
27
71
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
72
|
+
# Run a block with a temporary set of stubbed responses.
|
|
73
|
+
#
|
|
74
|
+
# Parameters:
|
|
75
|
+
#
|
|
76
|
+
# - `*bodies`: The responses to make available inside the block.
|
|
77
|
+
# - `&block`: The code to run while those responses are active.
|
|
78
|
+
#
|
|
79
|
+
# The provided responses are available only for the duration of the block.
|
|
80
|
+
# This is useful when you want to scope stubbed responses to a single part
|
|
81
|
+
# of a test without affecting later assertions.
|
|
82
|
+
#
|
|
83
|
+
# Example:
|
|
84
|
+
#
|
|
85
|
+
# RubyLLM::Test.with_responses("Scoped reply") do
|
|
86
|
+
# chat = RubyLLM.chat
|
|
87
|
+
# chat.ask("Question")
|
|
88
|
+
# end
|
|
89
|
+
def with_responses(*bodies, &)
|
|
90
|
+
harness.with_responses(*bodies, &)
|
|
35
91
|
end
|
|
36
92
|
|
|
37
|
-
|
|
38
|
-
|
|
93
|
+
# Return all recorded requests.
|
|
94
|
+
#
|
|
95
|
+
# This is useful for assertions about prompts, parameters, or other request
|
|
96
|
+
# details captured by the harness.
|
|
97
|
+
def requests
|
|
98
|
+
harness.requests
|
|
39
99
|
end
|
|
40
100
|
|
|
41
|
-
|
|
42
|
-
|
|
101
|
+
# Return the most recent request.
|
|
102
|
+
#
|
|
103
|
+
# Use this when you only care about the latest request made during a test.
|
|
104
|
+
def last_request
|
|
105
|
+
harness.last_request
|
|
43
106
|
end
|
|
44
107
|
|
|
45
|
-
|
|
46
|
-
|
|
108
|
+
# Clear all recorded requests.
|
|
109
|
+
#
|
|
110
|
+
# This leaves queued responses unchanged.
|
|
111
|
+
def clear_requests
|
|
112
|
+
harness.clear_requests
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def harness
|
|
118
|
+
@harness ||= Harness.new
|
|
47
119
|
end
|
|
48
120
|
end
|
|
49
121
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-test
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Todd Kummer
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-09-08 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ruby_llm
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 1.
|
|
18
|
+
version: 1.5.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 1.
|
|
25
|
+
version: 1.5.0
|
|
26
26
|
description: Provides a RubyLLM::Provider that allows you to stub responses for testing
|
|
27
27
|
purposes. You can stub individual responses or a sequence of responses, and you
|
|
28
28
|
can also temporarily stub responses within a block.
|
|
@@ -37,13 +37,16 @@ files:
|
|
|
37
37
|
- lib/ruby_llm/test.rb
|
|
38
38
|
- lib/ruby_llm/test/complete_parameters.rb
|
|
39
39
|
- lib/ruby_llm/test/errors/no_response_provided_error.rb
|
|
40
|
+
- lib/ruby_llm/test/harness.rb
|
|
40
41
|
- lib/ruby_llm/test/resolve_with_test_provider.rb
|
|
41
42
|
- lib/ruby_llm/test/test_provider.rb
|
|
42
43
|
- lib/ruby_llm/test/version.rb
|
|
43
44
|
homepage: https://github.com/RockSolt/ruby_llm-test
|
|
44
45
|
licenses:
|
|
45
46
|
- MIT
|
|
46
|
-
metadata:
|
|
47
|
+
metadata:
|
|
48
|
+
rubygems_mfa_required: 'true'
|
|
49
|
+
homepage_uri: https://github.com/RockSolt/ruby_llm-test
|
|
47
50
|
rdoc_options: []
|
|
48
51
|
require_paths:
|
|
49
52
|
- lib
|