activerabbit-ai 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/.rspec +3 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +49 -0
- data/IMPLEMENTATION_SUMMARY.md +220 -0
- data/README.md +317 -0
- data/Rakefile +10 -0
- data/TESTING_GUIDE.md +585 -0
- data/examples/rails_app_testing.rb +437 -0
- data/examples/rails_integration.rb +243 -0
- data/examples/standalone_usage.rb +309 -0
- data/lib/active_rabbit/client/configuration.rb +162 -0
- data/lib/active_rabbit/client/event_processor.rb +131 -0
- data/lib/active_rabbit/client/exception_tracker.rb +157 -0
- data/lib/active_rabbit/client/http_client.rb +137 -0
- data/lib/active_rabbit/client/n_plus_one_detector.rb +188 -0
- data/lib/active_rabbit/client/performance_monitor.rb +150 -0
- data/lib/active_rabbit/client/pii_scrubber.rb +169 -0
- data/lib/active_rabbit/client/railtie.rb +328 -0
- data/lib/active_rabbit/client/sidekiq_middleware.rb +130 -0
- data/lib/active_rabbit/client/version.rb +7 -0
- data/lib/active_rabbit/client.rb +119 -0
- data/lib/active_rabbit.rb +3 -0
- data/script/test_production_readiness.rb +403 -0
- data/sig/active_rabbit/client.rbs +6 -0
- metadata +155 -0
data/TESTING_GUIDE.md
ADDED
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
# Testing ActiveRabbit Client with Rails Applications
|
|
2
|
+
|
|
3
|
+
This guide covers comprehensive testing strategies for the ActiveRabbit client gem in Rails applications before production deployment.
|
|
4
|
+
|
|
5
|
+
## ๐งช Testing Strategy Overview
|
|
6
|
+
|
|
7
|
+
### 1. **Unit Tests** - Test gem components in isolation
|
|
8
|
+
### 2. **Integration Tests** - Test gem integration with Rails
|
|
9
|
+
### 3. **End-to-End Tests** - Test complete error tracking flow
|
|
10
|
+
### 4. **Performance Tests** - Ensure minimal performance impact
|
|
11
|
+
### 5. **Production Simulation** - Test with realistic data volumes
|
|
12
|
+
|
|
13
|
+
## ๐ง Test Environment Setup
|
|
14
|
+
|
|
15
|
+
### Gemfile for Testing
|
|
16
|
+
```ruby
|
|
17
|
+
group :test do
|
|
18
|
+
gem 'rspec-rails'
|
|
19
|
+
gem 'webmock'
|
|
20
|
+
gem 'vcr'
|
|
21
|
+
gem 'factory_bot_rails'
|
|
22
|
+
gem 'database_cleaner-active_record'
|
|
23
|
+
gem 'timecop'
|
|
24
|
+
gem 'rails-controller-testing'
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Test Configuration
|
|
29
|
+
```ruby
|
|
30
|
+
# spec/rails_helper.rb
|
|
31
|
+
require 'spec_helper'
|
|
32
|
+
require 'rspec/rails'
|
|
33
|
+
require 'webmock/rspec'
|
|
34
|
+
require 'vcr'
|
|
35
|
+
|
|
36
|
+
# Configure WebMock to stub HTTP requests
|
|
37
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
|
38
|
+
|
|
39
|
+
# Configure VCR for recording real API interactions
|
|
40
|
+
VCR.configure do |config|
|
|
41
|
+
config.cassette_library_dir = "spec/vcr_cassettes"
|
|
42
|
+
config.hook_into :webmock
|
|
43
|
+
config.configure_rspec_metadata!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
RSpec.configure do |config|
|
|
47
|
+
config.use_transactional_fixtures = true
|
|
48
|
+
config.infer_spec_type_from_file_location!
|
|
49
|
+
config.filter_rails_from_backtrace!
|
|
50
|
+
|
|
51
|
+
# Reset ActiveRabbit configuration before each test
|
|
52
|
+
config.before(:each) do
|
|
53
|
+
ActiveRabbit::Client.configuration = nil
|
|
54
|
+
Thread.current[:active_rabbit_request_context] = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
config.after(:each) do
|
|
58
|
+
ActiveRabbit::Client.configuration = nil
|
|
59
|
+
Thread.current[:active_rabbit_request_context] = nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## ๐ Unit Tests for Gem Components
|
|
65
|
+
|
|
66
|
+
### Test Configuration
|
|
67
|
+
```ruby
|
|
68
|
+
# spec/active_rabbit/configuration_spec.rb
|
|
69
|
+
RSpec.describe ActiveRabbit::Client::Configuration do
|
|
70
|
+
describe "environment variable loading" do
|
|
71
|
+
it "loads API key from environment" do
|
|
72
|
+
allow(ENV).to receive(:[]).with("active_rabbit_API_KEY").and_return("test-key")
|
|
73
|
+
config = described_class.new
|
|
74
|
+
expect(config.api_key).to eq("test-key")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "validation" do
|
|
79
|
+
it "validates required configuration" do
|
|
80
|
+
config = described_class.new
|
|
81
|
+
config.api_key = "test-key"
|
|
82
|
+
config.api_url = "https://api.test.com"
|
|
83
|
+
expect(config.valid?).to be true
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Test Exception Tracking
|
|
90
|
+
```ruby
|
|
91
|
+
# spec/active_rabbit/exception_tracker_spec.rb
|
|
92
|
+
RSpec.describe ActiveRabbit::Client::ExceptionTracker do
|
|
93
|
+
let(:configuration) { ActiveRabbit::Client::Configuration.new }
|
|
94
|
+
let(:http_client) { instance_double(ActiveRabbit::Client::HttpClient) }
|
|
95
|
+
let(:tracker) { described_class.new(configuration, http_client) }
|
|
96
|
+
let(:exception) { StandardError.new("Test error") }
|
|
97
|
+
|
|
98
|
+
before do
|
|
99
|
+
configuration.api_key = "test-key"
|
|
100
|
+
configuration.project_id = "test-project"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "#track_exception" do
|
|
104
|
+
it "sends exception data to API" do
|
|
105
|
+
expect(http_client).to receive(:post_exception).with(hash_including(
|
|
106
|
+
type: "StandardError",
|
|
107
|
+
message: "Test error"
|
|
108
|
+
))
|
|
109
|
+
|
|
110
|
+
tracker.track_exception(
|
|
111
|
+
exception: exception,
|
|
112
|
+
context: { user_id: "123" }
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "ignores filtered exceptions" do
|
|
117
|
+
configuration.ignored_exceptions = ["StandardError"]
|
|
118
|
+
|
|
119
|
+
expect(http_client).not_to receive(:post_exception)
|
|
120
|
+
|
|
121
|
+
tracker.track_exception(exception: exception)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "applies before_send callback" do
|
|
125
|
+
configuration.before_send_exception = proc do |data|
|
|
126
|
+
data[:custom_field] = "test_value"
|
|
127
|
+
data
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
expect(http_client).to receive(:post_exception).with(
|
|
131
|
+
hash_including(custom_field: "test_value")
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
tracker.track_exception(exception: exception)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Test PII Scrubbing
|
|
141
|
+
```ruby
|
|
142
|
+
# spec/active_rabbit/pii_scrubber_spec.rb
|
|
143
|
+
RSpec.describe ActiveRabbit::Client::PiiScrubber do
|
|
144
|
+
let(:configuration) { ActiveRabbit::Client::Configuration.new }
|
|
145
|
+
let(:scrubber) { described_class.new(configuration) }
|
|
146
|
+
|
|
147
|
+
describe "#scrub" do
|
|
148
|
+
it "scrubs sensitive data" do
|
|
149
|
+
data = {
|
|
150
|
+
email: "user@example.com",
|
|
151
|
+
password: "secret123",
|
|
152
|
+
safe_field: "safe_value"
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
result = scrubber.scrub(data)
|
|
156
|
+
|
|
157
|
+
expect(result[:email]).to eq("[FILTERED]")
|
|
158
|
+
expect(result[:password]).to eq("[FILTERED]")
|
|
159
|
+
expect(result[:safe_field]).to eq("safe_value")
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## ๐ Integration Tests with Rails
|
|
166
|
+
|
|
167
|
+
### Test Rails Middleware Integration
|
|
168
|
+
```ruby
|
|
169
|
+
# spec/integration/rails_integration_spec.rb
|
|
170
|
+
RSpec.describe "Rails Integration", type: :request do
|
|
171
|
+
before do
|
|
172
|
+
ActiveRabbit::Client.configure do |config|
|
|
173
|
+
config.api_key = "test-api-key"
|
|
174
|
+
config.project_id = "test-project"
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe "exception middleware" do
|
|
179
|
+
it "captures unhandled exceptions" do
|
|
180
|
+
# Stub the API call
|
|
181
|
+
stub_request(:post, "https://api.activerabbit.com/api/v1/exceptions")
|
|
182
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
183
|
+
|
|
184
|
+
# Create a route that raises an exception
|
|
185
|
+
Rails.application.routes.draw do
|
|
186
|
+
get '/test_error', to: proc { raise StandardError, "Test error" }
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
expect {
|
|
190
|
+
get '/test_error'
|
|
191
|
+
}.to raise_error(StandardError, "Test error")
|
|
192
|
+
|
|
193
|
+
# Verify the API was called
|
|
194
|
+
expect(WebMock).to have_requested(:post, "https://api.activerabbit.com/api/v1/exceptions")
|
|
195
|
+
.with(body: hash_including(
|
|
196
|
+
type: "StandardError",
|
|
197
|
+
message: "Test error"
|
|
198
|
+
))
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
describe "performance monitoring" do
|
|
203
|
+
it "tracks controller performance" do
|
|
204
|
+
stub_request(:post, "https://api.activerabbit.com/api/v1/performance")
|
|
205
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
206
|
+
|
|
207
|
+
get '/some_endpoint'
|
|
208
|
+
|
|
209
|
+
expect(WebMock).to have_requested(:post, "https://api.activerabbit.com/api/v1/performance")
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Test Controller Integration
|
|
216
|
+
```ruby
|
|
217
|
+
# spec/controllers/application_controller_spec.rb
|
|
218
|
+
RSpec.describe ApplicationController, type: :controller do
|
|
219
|
+
controller do
|
|
220
|
+
def index
|
|
221
|
+
raise StandardError, "Controller error"
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
before do
|
|
226
|
+
ActiveRabbit::Client.configure do |config|
|
|
227
|
+
config.api_key = "test-key"
|
|
228
|
+
config.project_id = "test-project"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
232
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "tracks exceptions with request context" do
|
|
236
|
+
expect {
|
|
237
|
+
get :index
|
|
238
|
+
}.to raise_error(StandardError)
|
|
239
|
+
|
|
240
|
+
expect(WebMock).to have_requested(:post, "https://api.activerabbit.com/api/v1/exceptions")
|
|
241
|
+
.with { |req|
|
|
242
|
+
body = JSON.parse(req.body)
|
|
243
|
+
body["context"]["request"]["method"] == "GET"
|
|
244
|
+
}
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## ๐ญ End-to-End Testing
|
|
250
|
+
|
|
251
|
+
### Test Complete Error Flow
|
|
252
|
+
```ruby
|
|
253
|
+
# spec/features/error_tracking_spec.rb
|
|
254
|
+
RSpec.describe "Error Tracking Flow", type: :feature do
|
|
255
|
+
before do
|
|
256
|
+
ActiveRabbit::Client.configure do |config|
|
|
257
|
+
config.api_key = "test-key"
|
|
258
|
+
config.project_id = "test-project"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
scenario "user triggers an error and it gets tracked" do
|
|
263
|
+
# Stub API calls
|
|
264
|
+
exception_stub = stub_request(:post, "https://api.activerabbit.com/api/v1/exceptions")
|
|
265
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
266
|
+
|
|
267
|
+
# Create a user and simulate an error condition
|
|
268
|
+
user = create(:user)
|
|
269
|
+
|
|
270
|
+
# Visit a page that will cause an error
|
|
271
|
+
visit "/users/999999" # Non-existent user
|
|
272
|
+
|
|
273
|
+
# Verify the exception was tracked
|
|
274
|
+
expect(exception_stub).to have_been_requested.with { |req|
|
|
275
|
+
body = JSON.parse(req.body)
|
|
276
|
+
body["type"] == "ActiveRecord::RecordNotFound" &&
|
|
277
|
+
body["context"]["request"]["path"] == "/users/999999"
|
|
278
|
+
}
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Test N+1 Query Detection
|
|
284
|
+
```ruby
|
|
285
|
+
# spec/features/n_plus_one_detection_spec.rb
|
|
286
|
+
RSpec.describe "N+1 Query Detection", type: :feature do
|
|
287
|
+
before do
|
|
288
|
+
ActiveRabbit::Client.configure do |config|
|
|
289
|
+
config.api_key = "test-key"
|
|
290
|
+
config.enable_n_plus_one_detection = true
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
scenario "detects N+1 queries" do
|
|
295
|
+
event_stub = stub_request(:post, "https://api.activerabbit.com/api/v1/events")
|
|
296
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
297
|
+
|
|
298
|
+
# Create test data that will cause N+1
|
|
299
|
+
users = create_list(:user, 5)
|
|
300
|
+
users.each { |user| create(:post, user: user) }
|
|
301
|
+
|
|
302
|
+
# Visit page that triggers N+1 (without includes)
|
|
303
|
+
visit "/users" # Assuming this lists users and their post counts
|
|
304
|
+
|
|
305
|
+
# Verify N+1 detection was triggered
|
|
306
|
+
expect(event_stub).to have_been_requested.with { |req|
|
|
307
|
+
body = JSON.parse(req.body)
|
|
308
|
+
body["name"] == "n_plus_one_detected"
|
|
309
|
+
}
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## โก Performance Testing
|
|
315
|
+
|
|
316
|
+
### Test Performance Impact
|
|
317
|
+
```ruby
|
|
318
|
+
# spec/performance/activerabbit_performance_spec.rb
|
|
319
|
+
RSpec.describe "ActiveRabbit Performance Impact" do
|
|
320
|
+
let(:iterations) { 100 }
|
|
321
|
+
|
|
322
|
+
it "has minimal impact on request processing time" do
|
|
323
|
+
# Baseline without ActiveRabbit
|
|
324
|
+
baseline_time = Benchmark.measure do
|
|
325
|
+
iterations.times { make_test_request }
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Configure ActiveRabbit
|
|
329
|
+
ActiveRabbit::Client.configure do |config|
|
|
330
|
+
config.api_key = "test-key"
|
|
331
|
+
config.project_id = "test-project"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
335
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
336
|
+
|
|
337
|
+
# Time with ActiveRabbit
|
|
338
|
+
activerabbit_time = Benchmark.measure do
|
|
339
|
+
iterations.times { make_test_request }
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Performance impact should be minimal (< 5%)
|
|
343
|
+
impact_percentage = ((activerabbit_time.real - baseline_time.real) / baseline_time.real) * 100
|
|
344
|
+
expect(impact_percentage).to be < 5
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
private
|
|
348
|
+
|
|
349
|
+
def make_test_request
|
|
350
|
+
get "/test_endpoint"
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Test Memory Usage
|
|
356
|
+
```ruby
|
|
357
|
+
# spec/performance/memory_usage_spec.rb
|
|
358
|
+
RSpec.describe "Memory Usage" do
|
|
359
|
+
it "doesn't cause memory leaks" do
|
|
360
|
+
ActiveRabbit::Client.configure do |config|
|
|
361
|
+
config.api_key = "test-key"
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
365
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
366
|
+
|
|
367
|
+
# Measure initial memory
|
|
368
|
+
GC.start
|
|
369
|
+
initial_memory = `ps -o rss= -p #{Process.pid}`.to_i
|
|
370
|
+
|
|
371
|
+
# Generate many errors
|
|
372
|
+
1000.times do |i|
|
|
373
|
+
begin
|
|
374
|
+
raise StandardError, "Test error #{i}"
|
|
375
|
+
rescue => e
|
|
376
|
+
ActiveRabbit::Client.track_exception(e)
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# Force cleanup
|
|
381
|
+
ActiveRabbit::Client.flush
|
|
382
|
+
GC.start
|
|
383
|
+
|
|
384
|
+
# Measure final memory
|
|
385
|
+
final_memory = `ps -o rss= -p #{Process.pid}`.to_i
|
|
386
|
+
memory_increase = final_memory - initial_memory
|
|
387
|
+
|
|
388
|
+
# Memory increase should be reasonable (< 50MB)
|
|
389
|
+
expect(memory_increase).to be < 50_000 # KB
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## ๐ฏ Production Simulation Tests
|
|
395
|
+
|
|
396
|
+
### Test with High Volume
|
|
397
|
+
```ruby
|
|
398
|
+
# spec/load/high_volume_spec.rb
|
|
399
|
+
RSpec.describe "High Volume Testing" do
|
|
400
|
+
before do
|
|
401
|
+
ActiveRabbit::Client.configure do |config|
|
|
402
|
+
config.api_key = "test-key"
|
|
403
|
+
config.batch_size = 10
|
|
404
|
+
config.flush_interval = 1
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
408
|
+
.to_return(status: 200, body: '{"status":"ok"}')
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
it "handles high volume of exceptions" do
|
|
412
|
+
# Simulate high error volume
|
|
413
|
+
threads = []
|
|
414
|
+
|
|
415
|
+
10.times do
|
|
416
|
+
threads << Thread.new do
|
|
417
|
+
100.times do |i|
|
|
418
|
+
begin
|
|
419
|
+
raise StandardError, "High volume error #{i}"
|
|
420
|
+
rescue => e
|
|
421
|
+
ActiveRabbit::Client.track_exception(e)
|
|
422
|
+
end
|
|
423
|
+
sleep(0.01) # Small delay to simulate real usage
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
threads.each(&:join)
|
|
429
|
+
ActiveRabbit::Client.flush
|
|
430
|
+
|
|
431
|
+
# Verify all requests were batched and sent
|
|
432
|
+
expect(WebMock).to have_requested(:post, /api\.activerabbit\.com/).at_least_times(100)
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Test API Failures
|
|
438
|
+
```ruby
|
|
439
|
+
# spec/resilience/api_failure_spec.rb
|
|
440
|
+
RSpec.describe "API Failure Resilience" do
|
|
441
|
+
before do
|
|
442
|
+
ActiveRabbit::Client.configure do |config|
|
|
443
|
+
config.api_key = "test-key"
|
|
444
|
+
config.retry_count = 2
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
it "handles API failures gracefully" do
|
|
449
|
+
# Stub API to fail initially, then succeed
|
|
450
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
451
|
+
.to_return(status: 500).times(2)
|
|
452
|
+
.then.to_return(status: 200, body: '{"status":"ok"}')
|
|
453
|
+
|
|
454
|
+
# This should not raise an error
|
|
455
|
+
expect {
|
|
456
|
+
ActiveRabbit::Client.track_exception(StandardError.new("Test"))
|
|
457
|
+
}.not_to raise_error
|
|
458
|
+
|
|
459
|
+
# Verify retries were attempted
|
|
460
|
+
expect(WebMock).to have_requested(:post, /api\.activerabbit\.com/).times(3)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "doesn't crash app when API is completely down" do
|
|
464
|
+
stub_request(:post, /api\.activerabbit\.com/)
|
|
465
|
+
.to_return(status: 500)
|
|
466
|
+
|
|
467
|
+
# App should continue working even if ActiveRabbit API is down
|
|
468
|
+
expect {
|
|
469
|
+
100.times do
|
|
470
|
+
ActiveRabbit::Client.track_exception(StandardError.new("Test"))
|
|
471
|
+
end
|
|
472
|
+
}.not_to raise_error
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## ๐ Pre-Production Checklist
|
|
478
|
+
|
|
479
|
+
### Test Script for Manual Verification
|
|
480
|
+
```ruby
|
|
481
|
+
# script/test_activerabbit.rb
|
|
482
|
+
#!/usr/bin/env ruby
|
|
483
|
+
|
|
484
|
+
puts "๐งช Testing ActiveRabbit Integration..."
|
|
485
|
+
|
|
486
|
+
# Test 1: Configuration
|
|
487
|
+
puts "\n1. Testing Configuration..."
|
|
488
|
+
ActiveRabbit::Client.configure do |config|
|
|
489
|
+
config.api_key = ENV['active_rabbit_API_KEY'] || 'test-key'
|
|
490
|
+
config.project_id = ENV['active_rabbit_PROJECT_ID'] || 'test-project'
|
|
491
|
+
config.environment = 'test'
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
if ActiveRabbit::Client.configured?
|
|
495
|
+
puts "โ
Configuration successful"
|
|
496
|
+
else
|
|
497
|
+
puts "โ Configuration failed"
|
|
498
|
+
exit 1
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
# Test 2: Exception Tracking
|
|
502
|
+
puts "\n2. Testing Exception Tracking..."
|
|
503
|
+
begin
|
|
504
|
+
raise StandardError, "Test exception for ActiveRabbit"
|
|
505
|
+
rescue => e
|
|
506
|
+
ActiveRabbit::Client.track_exception(e, context: { test: true })
|
|
507
|
+
puts "โ
Exception tracked"
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
# Test 3: Event Tracking
|
|
511
|
+
puts "\n3. Testing Event Tracking..."
|
|
512
|
+
ActiveRabbit::Client.track_event(
|
|
513
|
+
'test_event',
|
|
514
|
+
{ component: 'test_script', timestamp: Time.current },
|
|
515
|
+
user_id: 'test-user'
|
|
516
|
+
)
|
|
517
|
+
puts "โ
Event tracked"
|
|
518
|
+
|
|
519
|
+
# Test 4: Performance Tracking
|
|
520
|
+
puts "\n4. Testing Performance Tracking..."
|
|
521
|
+
ActiveRabbit::Client.track_performance(
|
|
522
|
+
'test_operation',
|
|
523
|
+
150.5,
|
|
524
|
+
metadata: { test: true }
|
|
525
|
+
)
|
|
526
|
+
puts "โ
Performance tracked"
|
|
527
|
+
|
|
528
|
+
# Test 5: Flush and Shutdown
|
|
529
|
+
puts "\n5. Testing Flush and Shutdown..."
|
|
530
|
+
ActiveRabbit::Client.flush
|
|
531
|
+
ActiveRabbit::Client.shutdown
|
|
532
|
+
puts "โ
Flush and shutdown successful"
|
|
533
|
+
|
|
534
|
+
puts "\n๐ All tests passed! ActiveRabbit is ready for production."
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
## ๐ Running the Tests
|
|
538
|
+
|
|
539
|
+
### Complete Test Suite
|
|
540
|
+
```bash
|
|
541
|
+
# Run all tests
|
|
542
|
+
bundle exec rspec
|
|
543
|
+
|
|
544
|
+
# Run specific test types
|
|
545
|
+
bundle exec rspec spec/active_rabbit/ # Unit tests
|
|
546
|
+
bundle exec rspec spec/integration/ # Integration tests
|
|
547
|
+
bundle exec rspec spec/features/ # End-to-end tests
|
|
548
|
+
bundle exec rspec spec/performance/ # Performance tests
|
|
549
|
+
|
|
550
|
+
# Run with coverage
|
|
551
|
+
COVERAGE=true bundle exec rspec
|
|
552
|
+
|
|
553
|
+
# Run manual test script
|
|
554
|
+
ruby script/test_activerabbit.rb
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### CI/CD Integration
|
|
558
|
+
```yaml
|
|
559
|
+
# .github/workflows/test.yml
|
|
560
|
+
name: Test ActiveRabbit Integration
|
|
561
|
+
|
|
562
|
+
on: [push, pull_request]
|
|
563
|
+
|
|
564
|
+
jobs:
|
|
565
|
+
test:
|
|
566
|
+
runs-on: ubuntu-latest
|
|
567
|
+
|
|
568
|
+
steps:
|
|
569
|
+
- uses: actions/checkout@v2
|
|
570
|
+
- name: Setup Ruby
|
|
571
|
+
uses: ruby/setup-ruby@v1
|
|
572
|
+
with:
|
|
573
|
+
ruby-version: 3.2.0
|
|
574
|
+
bundler-cache: true
|
|
575
|
+
|
|
576
|
+
- name: Run tests
|
|
577
|
+
run: |
|
|
578
|
+
bundle exec rspec
|
|
579
|
+
ruby script/test_activerabbit.rb
|
|
580
|
+
env:
|
|
581
|
+
active_rabbit_API_KEY: ${{ secrets.active_rabbit_API_KEY }}
|
|
582
|
+
active_rabbit_PROJECT_ID: ${{ secrets.active_rabbit_PROJECT_ID }}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
This comprehensive testing approach ensures your Rails application and ActiveRabbit gem integration is thoroughly tested before production deployment, covering functionality, performance, and resilience scenarios.
|