infinity_test 1.0.3 → 2.0.0.rc2

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.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +31 -0
  3. data/.gitignore +3 -0
  4. data/.rspec +2 -2
  5. data/AI_INTEGRATION_IDEAS.md +203 -0
  6. data/Gemfile +3 -15
  7. data/HISTORY.md +84 -0
  8. data/History.markdown +82 -0
  9. data/{.infinity_test → INFINITY_TEST} +18 -15
  10. data/LICENSE.txt +2 -2
  11. data/README.md +867 -0
  12. data/Rakefile +1 -65
  13. data/TODO.markdown +38 -24
  14. data/bin/infinity_test +1 -4
  15. data/images/fuuu/pending.png +0 -0
  16. data/images/fuuu/success.png +0 -0
  17. data/infinity_test.gemspec +41 -189
  18. data/lib/infinity_test/core/auto_discover.rb +67 -0
  19. data/lib/infinity_test/core/base.rb +369 -0
  20. data/lib/infinity_test/core/callback.rb +59 -0
  21. data/lib/infinity_test/core/changed_file.rb +13 -0
  22. data/lib/infinity_test/core/command_builder.rb +48 -0
  23. data/lib/infinity_test/core/command_runner.rb +38 -0
  24. data/lib/infinity_test/core/configuration_merge.rb +37 -0
  25. data/lib/infinity_test/core/continuous_test_server.rb +124 -0
  26. data/lib/infinity_test/core/load_configuration.rb +48 -0
  27. data/lib/infinity_test/core/notifier.rb +59 -0
  28. data/lib/infinity_test/core/options.rb +134 -0
  29. data/lib/infinity_test/core/runner.rb +18 -0
  30. data/lib/infinity_test/core/version.rb +5 -0
  31. data/lib/infinity_test/framework/base.rb +93 -0
  32. data/lib/infinity_test/framework/django.rb +109 -0
  33. data/lib/infinity_test/framework/elixir_mix.rb +47 -0
  34. data/lib/infinity_test/framework/fast_api.rb +104 -0
  35. data/lib/infinity_test/framework/padrino.rb +30 -0
  36. data/lib/infinity_test/framework/phoenix.rb +72 -0
  37. data/lib/infinity_test/framework/python_package.rb +97 -0
  38. data/lib/infinity_test/framework/rails.rb +26 -0
  39. data/lib/infinity_test/framework/rocket.rb +70 -0
  40. data/lib/infinity_test/framework/rubygems.rb +29 -0
  41. data/lib/infinity_test/framework/rust_cargo.rb +69 -0
  42. data/lib/infinity_test/framework/shared_example.rb +47 -0
  43. data/lib/infinity_test/observer/base.rb +40 -0
  44. data/lib/infinity_test/observer/filewatcher.rb +72 -0
  45. data/lib/infinity_test/observer/listen.rb +74 -0
  46. data/lib/infinity_test/observer/shared_example.rb +35 -0
  47. data/lib/infinity_test/old_dsl/configuration.rb +26 -0
  48. data/lib/infinity_test/strategy/base.rb +50 -0
  49. data/lib/infinity_test/strategy/elixir_default.rb +20 -0
  50. data/lib/infinity_test/strategy/python_default.rb +22 -0
  51. data/lib/infinity_test/strategy/rbenv.rb +34 -0
  52. data/lib/infinity_test/strategy/ruby_default.rb +21 -0
  53. data/lib/infinity_test/strategy/rust_default.rb +21 -0
  54. data/lib/infinity_test/strategy/rvm.rb +52 -0
  55. data/lib/infinity_test/strategy/shared_example.rb +32 -0
  56. data/lib/infinity_test/test_framework/base.rb +64 -0
  57. data/lib/infinity_test/test_framework/cargo_test.rb +49 -0
  58. data/lib/infinity_test/test_framework/ex_unit.rb +53 -0
  59. data/lib/infinity_test/test_framework/pytest.rb +65 -0
  60. data/lib/infinity_test/test_framework/rspec.rb +48 -0
  61. data/lib/infinity_test/test_framework/shared_example.rb +56 -0
  62. data/lib/infinity_test/test_framework/test_unit.rb +57 -0
  63. data/lib/infinity_test.rb +66 -35
  64. data/spec/infinity_test/core/auto_discover_spec.rb +175 -0
  65. data/spec/infinity_test/core/base_spec.rb +240 -0
  66. data/spec/infinity_test/core/callback_spec.rb +89 -0
  67. data/spec/infinity_test/core/changed_file_spec.rb +26 -0
  68. data/spec/infinity_test/core/command_builder_spec.rb +38 -0
  69. data/spec/infinity_test/core/configuration_merge_spec.rb +124 -0
  70. data/spec/infinity_test/core/continuous_test_server_spec.rb +116 -0
  71. data/spec/infinity_test/core/load_configuration_spec.rb +43 -0
  72. data/spec/infinity_test/core/notifier_spec.rb +151 -0
  73. data/spec/infinity_test/core/options_spec.rb +168 -0
  74. data/spec/infinity_test/core/runner_spec.rb +17 -0
  75. data/spec/infinity_test/framework/base_spec.rb +55 -0
  76. data/spec/infinity_test/framework/django_spec.rb +95 -0
  77. data/spec/infinity_test/framework/elixir_mix_spec.rb +44 -0
  78. data/spec/infinity_test/framework/fast_api_spec.rb +96 -0
  79. data/spec/infinity_test/framework/padrino_spec.rb +58 -0
  80. data/spec/infinity_test/framework/phoenix_spec.rb +85 -0
  81. data/spec/infinity_test/framework/python_package_spec.rb +95 -0
  82. data/spec/infinity_test/framework/rails_spec.rb +58 -0
  83. data/spec/infinity_test/framework/rocket_spec.rb +69 -0
  84. data/spec/infinity_test/framework/rubygems_spec.rb +34 -0
  85. data/spec/infinity_test/framework/rust_cargo_spec.rb +94 -0
  86. data/spec/infinity_test/observer/base_spec.rb +78 -0
  87. data/spec/infinity_test/observer/filewatcher_spec.rb +51 -0
  88. data/spec/infinity_test/observer/listen_spec.rb +50 -0
  89. data/spec/infinity_test/{builder_spec.rb → strategy/base_spec.rb} +1 -2
  90. data/spec/infinity_test/strategy/elixir_default_spec.rb +46 -0
  91. data/spec/infinity_test/strategy/python_default_spec.rb +56 -0
  92. data/spec/infinity_test/strategy/rbenv_spec.rb +70 -0
  93. data/spec/infinity_test/strategy/ruby_default_spec.rb +49 -0
  94. data/spec/infinity_test/strategy/rust_default_spec.rb +56 -0
  95. data/spec/infinity_test/strategy/rvm_spec.rb +86 -0
  96. data/spec/infinity_test/test_framework/cargo_test_spec.rb +145 -0
  97. data/spec/infinity_test/test_framework/ex_unit_spec.rb +153 -0
  98. data/spec/infinity_test/test_framework/pytest_spec.rb +182 -0
  99. data/spec/infinity_test/test_framework/rspec_spec.rb +119 -0
  100. data/spec/infinity_test/test_framework/test_unit_spec.rb +193 -0
  101. data/spec/spec_helper.rb +34 -119
  102. metadata +315 -177
  103. data/.rvmrc +0 -1
  104. data/Gemfile.lock +0 -62
  105. data/Readme.markdown +0 -147
  106. data/Tasks +0 -4
  107. data/VERSION.yml +0 -5
  108. data/buzz_images/buzz_lightyear.jpg +0 -0
  109. data/buzz_images/buzz_lightyear_continencia.gif +0 -0
  110. data/buzz_images/to_infinity_and_beyond.png +0 -0
  111. data/features/heuristics.feature +0 -23
  112. data/features/support/env.rb +0 -2
  113. data/images/fuuu/sucess.png +0 -0
  114. data/lib/infinity_test/application.rb +0 -362
  115. data/lib/infinity_test/application_library/rails.rb +0 -94
  116. data/lib/infinity_test/application_library/rubygems.rb +0 -43
  117. data/lib/infinity_test/binary_path.rb +0 -43
  118. data/lib/infinity_test/builder.rb +0 -66
  119. data/lib/infinity_test/command.rb +0 -58
  120. data/lib/infinity_test/configuration.rb +0 -277
  121. data/lib/infinity_test/continuous_testing.rb +0 -40
  122. data/lib/infinity_test/dependencies.rb +0 -80
  123. data/lib/infinity_test/environment.rb +0 -15
  124. data/lib/infinity_test/heuristics.rb +0 -36
  125. data/lib/infinity_test/heuristics_helper.rb +0 -9
  126. data/lib/infinity_test/options.rb +0 -96
  127. data/lib/infinity_test/runner.rb +0 -38
  128. data/lib/infinity_test/test_framework.rb +0 -110
  129. data/lib/infinity_test/test_library/bacon.rb +0 -55
  130. data/lib/infinity_test/test_library/cucumber.rb +0 -22
  131. data/lib/infinity_test/test_library/rspec.rb +0 -60
  132. data/lib/infinity_test/test_library/test_unit.rb +0 -52
  133. data/lib/infinity_test/test_unit_loader.rb +0 -5
  134. data/spec/factories/buzz/lib/buzz.rb +0 -0
  135. data/spec/factories/buzz/spec/buzz_spec.rb +0 -0
  136. data/spec/factories/company/Gemfile +0 -0
  137. data/spec/factories/company/lib/company.rb +0 -0
  138. data/spec/factories/company/test/company_test.rb +0 -0
  139. data/spec/factories/images/failure.png +0 -0
  140. data/spec/factories/images/pending.png +0 -0
  141. data/spec/factories/images/sucess.png +0 -0
  142. data/spec/factories/infinity_test +0 -5
  143. data/spec/factories/infinity_test_example +0 -7
  144. data/spec/factories/slinky/spec/slinky/slinky_spec.rb +0 -0
  145. data/spec/factories/travel/lib/travel.rb +0 -0
  146. data/spec/factories/travel/test/partner_test.rb +0 -0
  147. data/spec/factories/travel/test/travel_test.rb +0 -0
  148. data/spec/factories/wood/lib/wood.rb +0 -0
  149. data/spec/factories/wood/spec/wood_spec.rb +0 -0
  150. data/spec/infinity_test/application_library/rails_spec.rb +0 -140
  151. data/spec/infinity_test/application_library/rubygems_spec.rb +0 -52
  152. data/spec/infinity_test/application_spec.rb +0 -434
  153. data/spec/infinity_test/binary_path_spec.rb +0 -72
  154. data/spec/infinity_test/command_spec.rb +0 -53
  155. data/spec/infinity_test/configuration_spec.rb +0 -382
  156. data/spec/infinity_test/continuous_testing_spec.rb +0 -25
  157. data/spec/infinity_test/environment_spec.rb +0 -23
  158. data/spec/infinity_test/heuristics_helper_spec.rb +0 -15
  159. data/spec/infinity_test/heuristics_spec.rb +0 -127
  160. data/spec/infinity_test/options_spec.rb +0 -111
  161. data/spec/infinity_test/runner_spec.rb +0 -42
  162. data/spec/infinity_test/test_framework_spec.rb +0 -127
  163. data/spec/infinity_test/test_library/bacon_spec.rb +0 -150
  164. data/spec/infinity_test/test_library/cucumber_spec.rb +0 -8
  165. data/spec/infinity_test/test_library/rspec_spec.rb +0 -189
  166. data/spec/infinity_test/test_library/test_unit_spec.rb +0 -184
  167. data/spec/infinity_test_spec.rb +0 -40
  168. /data/images/faces/{sucess.png → success.png} +0 -0
  169. /data/images/hands/{sucess.png → success.png} +0 -0
  170. /data/images/mario_bros/{sucess.jpg → success.jpg} +0 -0
  171. /data/images/rails/{sucess.png → success.png} +0 -0
  172. /data/images/rubies/{sucess.png → success.png} +0 -0
  173. /data/images/simpson/{sucess.jpg → success.jpg} +0 -0
  174. /data/images/street_fighter/{sucess.jpg → success.jpg} +0 -0
  175. /data/images/toy_story/{sucess.png → success.png} +0 -0
data/README.md ADDED
@@ -0,0 +1,867 @@
1
+ # Infinity Test
2
+
3
+ **To Infinity and Beyond!**
4
+
5
+ Infinity Test is a continuous testing library and a flexible alternative to Autotest and Guard. It watches your files for changes and automatically runs your tests, providing instant feedback with desktop notifications.
6
+
7
+ Version 2.0.0 brings a complete rewrite with modern dependencies, multi-Ruby support via RVM/RbEnv, a powerful callbacks system, and experimental support for Elixir (Phoenix, ExUnit), Python (Django, FastAPI, Pytest), and Rust (Rocket, Cargo).
8
+
9
+ ## Table of Contents
10
+
11
+ - [Installation](#installation)
12
+ - [Quick Start](#quick-start)
13
+ - [Command Line Options](#command-line-options)
14
+ - [Configuration File (INFINITY_TEST)](#configuration-file-infinity_test)
15
+ - [Ruby Version Managers](#ruby-version-managers)
16
+ - [Test Frameworks](#test-frameworks)
17
+ - [Application Frameworks](#application-frameworks)
18
+ - [Experimental: Elixir Support](#experimental-elixir-support)
19
+ - [Experimental: Python Support](#experimental-python-support)
20
+ - [Experimental: Rust Support](#experimental-rust-support)
21
+ - [Notifications](#notifications)
22
+ - [Image Themes](#image-themes)
23
+ - [Callbacks](#callbacks)
24
+ - [File Watching](#file-watching)
25
+ - [Advanced Usage](#advanced-usage)
26
+
27
+ ---
28
+
29
+ ## Installation
30
+
31
+ Since this is a release candidate (rc1), you need to explicitly request the pre-release version:
32
+
33
+ ```bash
34
+ gem install infinity_test --pre
35
+ ```
36
+
37
+ Or add to your Gemfile:
38
+
39
+ ```ruby
40
+ gem 'infinity_test', '~> 2.0.0.rc2', group: :development
41
+ ```
42
+
43
+ Then run:
44
+
45
+ ```bash
46
+ bundle install
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Quick Start
52
+
53
+ ### Step 1: Navigate to your project
54
+
55
+ ```bash
56
+ cd /path/to/your/project
57
+ ```
58
+
59
+ ### Step 2: Run Infinity Test
60
+
61
+ ```bash
62
+ infinity_test
63
+ ```
64
+
65
+ That's it! Infinity Test will:
66
+
67
+ 1. Auto-detect your test framework (RSpec, Test::Unit, ExUnit, or Pytest)
68
+ 2. Auto-detect your application framework (Rails, Padrino, Rubygems, Phoenix, Django, FastAPI, etc.)
69
+ 3. Run all tests immediately
70
+ 4. Watch for file changes and re-run relevant tests
71
+ 5. Show desktop notifications with test results
72
+
73
+ ### Step 3: Start coding
74
+
75
+ Edit your files and watch the tests run automatically!
76
+
77
+ ---
78
+
79
+ ## Command Line Options
80
+
81
+ | Option | Short | Description |
82
+ |--------|-------|-------------|
83
+ | `--ruby strategy` | | Ruby manager strategy: `auto_discover`, `rvm`, `rbenv`, `ruby_default` |
84
+ | `--rubies=versions` | | Ruby versions to test against (comma-separated) |
85
+ | `--test library` | | Test framework: `auto_discover`, `rspec`, `test_unit`, `ex_unit`, `pytest`, `cargo_test` |
86
+ | `--framework library` | | Application framework: `auto_discover`, `rails`, `padrino`, `rubygems`, `phoenix`, `elixir_mix`, `django`, `fast_api`, `python_package`, `rocket`, `rust_cargo` |
87
+ | `--options=options` | | Additional options to pass to test command |
88
+ | `--notifications library` | | Notification system: `auto_discover`, `osascript`, `terminal_notifier`, `notify_send`, `dunstify` |
89
+ | `--mode theme` | | Image theme for notifications (see [Image Themes](#image-themes)) |
90
+ | `--no-infinity-and-beyond` | `-n` | Run tests once and exit (CI mode) |
91
+ | `--just-watch` | `-j` | Skip initial test run, only watch for changes |
92
+ | `--focus [FILE]` | `-f` | Focus on specific tests or `failures` for last failed tests |
93
+ | `--no-verbose` | | Don't print commands before executing |
94
+ | `--no-bundler` | | Bypass Bundler support |
95
+ | `--help` | | Show help message |
96
+
97
+ ### Examples
98
+
99
+ **Run with RSpec only:**
100
+ ```bash
101
+ infinity_test --test rspec
102
+ ```
103
+
104
+ **Run tests on multiple Ruby versions with RVM:**
105
+ ```bash
106
+ infinity_test --ruby rvm --rubies=3.0.0,3.1.0,3.2.0
107
+ ```
108
+
109
+ **Run tests once and exit (for CI):**
110
+ ```bash
111
+ infinity_test -n
112
+ ```
113
+
114
+ **Skip initial test run, just watch:**
115
+ ```bash
116
+ infinity_test --just-watch
117
+ ```
118
+
119
+ **Focus on failed tests:**
120
+ ```bash
121
+ infinity_test --focus failures
122
+ ```
123
+
124
+ **Focus on a specific file:**
125
+ ```bash
126
+ infinity_test --focus spec/models/user_spec.rb
127
+ ```
128
+
129
+ **Use a specific notification theme:**
130
+ ```bash
131
+ infinity_test --mode mario_bros
132
+ ```
133
+
134
+ **Pass additional options to the test runner:**
135
+ ```bash
136
+ infinity_test --options="-Ilib -Itest"
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Configuration File (INFINITY_TEST)
142
+
143
+ You can persist your settings in an `INFINITY_TEST` file. Infinity Test looks for configuration in two locations:
144
+
145
+ 1. **Project file**: `./INFINITY_TEST` (higher priority)
146
+ 2. **Global file**: `~/INFINITY_TEST` (lower priority)
147
+
148
+ ### Basic Configuration
149
+
150
+ ```ruby
151
+ InfinityTest.setup do |config|
152
+ config.test_framework = :rspec
153
+ config.framework = :rails
154
+ config.notifications = :terminal_notifier
155
+ config.mode = :mario_bros
156
+ config.verbose = true
157
+ end
158
+ ```
159
+
160
+ ### All Configuration Options
161
+
162
+ ```ruby
163
+ InfinityTest.setup do |config|
164
+ # Ruby Version Manager
165
+ # Options: :auto_discover, :rvm, :rbenv, :ruby_default
166
+ config.strategy = :auto_discover
167
+
168
+ # Ruby versions to test against (requires RVM or RbEnv)
169
+ config.rubies = ['3.0.0', '3.1.0', '3.2.0']
170
+
171
+ # Gemset to use with RVM
172
+ config.gemset = 'my_project'
173
+
174
+ # Test framework
175
+ # Options: :auto_discover, :rspec, :test_unit, :ex_unit, :pytest, :cargo_test
176
+ config.test_framework = :rspec
177
+
178
+ # Application framework
179
+ # Options: :auto_discover, :rails, :padrino, :rubygems, :phoenix, :elixir_mix, :django, :fast_api, :python_package, :rocket, :rust_cargo
180
+ config.framework = :rails
181
+
182
+ # File observer
183
+ # Options: :listen (event-driven), :filewatcher (polling)
184
+ config.observer = :listen
185
+
186
+ # Notification system
187
+ # Options: :auto_discover, :osascript, :terminal_notifier, :notify_send, :dunstify
188
+ config.notifications = :auto_discover
189
+
190
+ # Image theme for notifications
191
+ config.mode = :simpson
192
+
193
+ # Or use custom images
194
+ config.success_image = '/path/to/success.png'
195
+ config.failure_image = '/path/to/failure.png'
196
+ config.pending_image = '/path/to/pending.png'
197
+
198
+ # Bundler support (auto-detected if Gemfile exists)
199
+ config.bundler = true
200
+
201
+ # Print commands before executing
202
+ config.verbose = true
203
+
204
+ # File extension to watch
205
+ config.extension = :rb
206
+
207
+ # Skip initial test run
208
+ config.just_watch = false
209
+
210
+ # Run tests and exit (CI mode)
211
+ config.infinity_and_beyond = true
212
+
213
+ # Focus mode: nil, :failures, or file path
214
+ config.focus = nil
215
+
216
+ # Ignore specific test files
217
+ config.ignore_test_files = [
218
+ 'spec/slow/performance_spec.rb'
219
+ ]
220
+
221
+ # Ignore test folders
222
+ config.ignore_test_folders = [
223
+ 'spec/integration'
224
+ ]
225
+ end
226
+ ```
227
+
228
+ ### Configuration with Callbacks
229
+
230
+ ```ruby
231
+ InfinityTest.setup do |config|
232
+ config.test_framework = :rspec
233
+ config.mode = :faces
234
+ end
235
+
236
+ # Clear terminal before running tests
237
+ InfinityTest::Core::Base.before(:all) do
238
+ InfinityTest::Core::Base.clear_terminal
239
+ end
240
+
241
+ # Run after all tests complete
242
+ InfinityTest::Core::Base.after(:all) do
243
+ system('say "Tests finished"')
244
+ end
245
+
246
+ # Run before each Ruby version (when testing multiple rubies)
247
+ InfinityTest::Core::Base.before(:each_ruby) do |environment|
248
+ puts "Testing with Ruby #{environment[:ruby_version]}"
249
+ end
250
+
251
+ # Run after each Ruby version
252
+ InfinityTest::Core::Base.after(:each_ruby) do |environment|
253
+ puts "Finished testing Ruby #{environment[:ruby_version]}"
254
+ end
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Ruby Version Managers
260
+
261
+ Infinity Test supports testing across multiple Ruby versions using RVM or RbEnv.
262
+
263
+ ### Auto Discovery (Default)
264
+
265
+ ```ruby
266
+ config.strategy = :auto_discover
267
+ ```
268
+
269
+ Priority order: RVM > RbEnv > RubyDefault
270
+
271
+ ### RVM Strategy
272
+
273
+ Test against multiple Ruby versions with optional gemset support:
274
+
275
+ ```ruby
276
+ InfinityTest.setup do |config|
277
+ config.strategy = :rvm
278
+ config.rubies = ['3.0.0', '3.1.0', 'jruby-9.4.0.0']
279
+ config.gemset = 'infinity_test' # Optional
280
+ end
281
+ ```
282
+
283
+ **Command line:**
284
+ ```bash
285
+ infinity_test --ruby rvm --rubies=3.0.0,3.1.0,jruby-9.4.0.0
286
+ ```
287
+
288
+ ### RbEnv Strategy
289
+
290
+ Test against multiple Ruby versions using rbenv:
291
+
292
+ ```ruby
293
+ InfinityTest.setup do |config|
294
+ config.strategy = :rbenv
295
+ config.rubies = ['3.0.0', '3.1.0', '3.2.0']
296
+ end
297
+ ```
298
+
299
+ **Command line:**
300
+ ```bash
301
+ infinity_test --ruby rbenv --rubies=3.0.0,3.1.0
302
+ ```
303
+
304
+ ### Ruby Default Strategy
305
+
306
+ Use the current Ruby version only (no version manager):
307
+
308
+ ```ruby
309
+ config.strategy = :ruby_default
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Test Frameworks
315
+
316
+ ### RSpec
317
+
318
+ Auto-detected when `spec/` directory exists with `spec_helper.rb` or `*_spec.rb` files.
319
+
320
+ ```ruby
321
+ config.test_framework = :rspec
322
+ ```
323
+
324
+ ### Test::Unit / Minitest
325
+
326
+ Auto-detected when `test/` directory exists with `test_helper.rb` or `*_test.rb` files.
327
+
328
+ ```ruby
329
+ config.test_framework = :test_unit
330
+ ```
331
+
332
+ ### Other Test Frameworks (Experimental)
333
+
334
+ See [Elixir Support](#experimental-elixir-support) for ExUnit and [Python Support](#experimental-python-support) for Pytest.
335
+
336
+ ---
337
+
338
+ ## Application Frameworks
339
+
340
+ ### Rails
341
+
342
+ Auto-detected when `config/environment.rb` exists.
343
+
344
+ **Watched directories:**
345
+ - `app/models` → runs corresponding model specs/tests
346
+ - `app/controllers` → runs corresponding controller specs/tests
347
+ - `app/helpers` → runs corresponding helper specs/tests
348
+ - `app/mailers` → runs corresponding mailer specs/tests
349
+ - `app/jobs` → runs corresponding job specs/tests
350
+ - `lib/` → runs corresponding lib specs/tests
351
+ - `spec/` or `test/` → runs the changed spec/test file
352
+ - `spec_helper.rb` or `test_helper.rb` → runs all tests
353
+
354
+ ### Padrino
355
+
356
+ Auto-detected when `config/boot.rb` exists with Padrino reference.
357
+
358
+ Similar heuristics to Rails with Padrino-specific paths.
359
+
360
+ ### Rubygems (Default)
361
+
362
+ Used for gem development and simple Ruby projects.
363
+
364
+ **Watched directories:**
365
+ - `lib/` → runs corresponding specs/tests
366
+ - `spec/` or `test/` → runs the changed spec/test file
367
+
368
+ ---
369
+
370
+ ## Experimental: Elixir Support
371
+
372
+ > **Note:** Elixir support is experimental. Please report any issues.
373
+
374
+ Infinity Test can watch Elixir projects and run ExUnit tests automatically.
375
+
376
+ ### ExUnit Test Framework
377
+
378
+ Auto-detected when `test/` directory exists with `test_helper.exs` or `*_test.exs` files.
379
+
380
+ ```ruby
381
+ config.test_framework = :ex_unit
382
+ ```
383
+
384
+ ### Phoenix Framework
385
+
386
+ Auto-detected when `mix.exs` exists and `lib/*_web/` directory is present.
387
+
388
+ **Watched directories:**
389
+ - `lib/my_app/` → runs corresponding tests in `test/my_app/`
390
+ - `lib/my_app_web/controllers/` → runs corresponding controller tests
391
+ - `lib/my_app_web/live/` → runs corresponding LiveView tests
392
+ - `test/` → runs the changed test file
393
+ - `test/test_helper.exs` → runs all tests
394
+
395
+ ```ruby
396
+ config.framework = :phoenix
397
+ ```
398
+
399
+ ### ElixirMix Framework
400
+
401
+ For standard Elixir/Mix projects (non-Phoenix). Auto-detected when `mix.exs` exists.
402
+
403
+ **Watched directories:**
404
+ - `lib/` → runs corresponding tests
405
+ - `test/` → runs the changed test file
406
+
407
+ ```ruby
408
+ config.framework = :elixir_mix
409
+ ```
410
+
411
+ ### Elixir Configuration Example
412
+
413
+ ```ruby
414
+ InfinityTest.setup do |config|
415
+ config.test_framework = :ex_unit
416
+ config.framework = :phoenix # or :elixir_mix
417
+ config.strategy = :elixir_default
418
+ config.notifications = :terminal_notifier
419
+ end
420
+ ```
421
+
422
+ ---
423
+
424
+ ## Experimental: Python Support
425
+
426
+ > **Note:** Python support is experimental. Please report any issues.
427
+
428
+ Infinity Test can watch Python projects and run Pytest tests automatically.
429
+
430
+ ### Pytest Test Framework
431
+
432
+ Auto-detected when `tests/` or `test/` directory exists with `test_*.py` or `*_test.py` files.
433
+
434
+ ```ruby
435
+ config.test_framework = :pytest
436
+ ```
437
+
438
+ **Output parsing:**
439
+ - `5 passed` → success
440
+ - `1 failed, 4 passed` → failure
441
+ - `4 passed, 1 skipped` → pending
442
+
443
+ ### Django Framework
444
+
445
+ Auto-detected when `manage.py` exists with Django imports.
446
+
447
+ **Watched directories:**
448
+ - Django app directories (containing `models.py`, `views.py`, or `apps.py`)
449
+ - Each app's `tests/` directory or `tests.py` file
450
+ - `conftest.py` → runs all tests
451
+
452
+ ```ruby
453
+ config.framework = :django
454
+ ```
455
+
456
+ ### FastAPI Framework
457
+
458
+ Auto-detected when `main.py` (or `app/main.py`, `src/main.py`) contains FastAPI imports. Ideal for ML model serving APIs.
459
+
460
+ **Watched directories:**
461
+ - `app/` → API application code
462
+ - `routers/` → API route definitions
463
+ - `api/` → API endpoints
464
+ - `endpoints/` → endpoint handlers
465
+ - `tests/` → test files
466
+
467
+ ```ruby
468
+ config.framework = :fast_api
469
+ ```
470
+
471
+ ### PythonPackage Framework
472
+
473
+ For standard Python packages. Auto-detected when `pyproject.toml`, `setup.py`, or `setup.cfg` exists.
474
+
475
+ **Watched directories:**
476
+ - `src/` → source code
477
+ - `lib/` → library code
478
+ - Package directories (containing `__init__.py`)
479
+ - `tests/` or `test/` → test files
480
+
481
+ ```ruby
482
+ config.framework = :python_package
483
+ ```
484
+
485
+ ### Python Configuration Example
486
+
487
+ ```ruby
488
+ InfinityTest.setup do |config|
489
+ config.test_framework = :pytest
490
+ config.framework = :fast_api # or :django, :python_package
491
+ config.strategy = :python_default
492
+ config.notifications = :terminal_notifier
493
+ end
494
+ ```
495
+
496
+ ### Python Project Structure Examples
497
+
498
+ **FastAPI ML API:**
499
+ ```
500
+ my_ml_api/
501
+ ├── app/
502
+ │ ├── main.py # from fastapi import FastAPI
503
+ │ ├── models/ # ML models
504
+ │ └── routers/ # API endpoints
505
+ ├── tests/
506
+ │ ├── conftest.py
507
+ │ └── test_api.py
508
+ └── pyproject.toml
509
+ ```
510
+
511
+ **Django ML Dashboard:**
512
+ ```
513
+ my_dashboard/
514
+ ├── manage.py
515
+ ├── dashboard/ # Django app
516
+ │ ├── models.py
517
+ │ ├── views.py
518
+ │ └── tests/
519
+ ├── ml_pipeline/ # Django app
520
+ │ ├── models.py
521
+ │ └── tests.py
522
+ └── requirements.txt
523
+ ```
524
+
525
+ ---
526
+
527
+ ## Experimental: Rust Support
528
+
529
+ > **Note:** Rust support is experimental. Please report any issues.
530
+
531
+ Infinity Test can watch Rust projects and run `cargo test` automatically.
532
+
533
+ ### CargoTest Test Framework
534
+
535
+ Auto-detected when `Cargo.toml` exists.
536
+
537
+ ```ruby
538
+ config.test_framework = :cargo_test
539
+ ```
540
+
541
+ **Output parsing:**
542
+ - `5 passed; 0 failed; 0 ignored` → success
543
+ - `3 passed; 2 failed; 0 ignored` → failure
544
+ - `4 passed; 0 failed; 1 ignored` → pending
545
+
546
+ ### Rocket Framework
547
+
548
+ Auto-detected when `Cargo.toml` contains `rocket` dependency. For Rocket web applications.
549
+
550
+ **Watched directories:**
551
+ - `src/*.rs` → runs tests matching the module name (e.g., `src/routes.rs` → `cargo test routes`)
552
+ - `src/lib.rs` or `src/main.rs` → runs all tests
553
+ - `tests/*.rs` → runs the specific integration test
554
+ - `Cargo.toml` → runs all tests
555
+ - `Rocket.toml` → runs all tests (if exists)
556
+
557
+ ```ruby
558
+ config.framework = :rocket
559
+ ```
560
+
561
+ ### RustCargo Framework
562
+
563
+ For standard Rust libraries and applications. Auto-detected when `Cargo.toml` exists (and no Rocket dependency).
564
+
565
+ **Watched directories:**
566
+ - `src/*.rs` → runs tests matching the module name
567
+ - `tests/*.rs` → runs the specific integration test
568
+ - `Cargo.toml` → runs all tests
569
+
570
+ ```ruby
571
+ config.framework = :rust_cargo
572
+ ```
573
+
574
+ ### Rust Configuration Example
575
+
576
+ ```ruby
577
+ InfinityTest.setup do |config|
578
+ config.test_framework = :cargo_test
579
+ config.framework = :rust_cargo # or :rocket
580
+ config.strategy = :rust_default
581
+ config.notifications = :terminal_notifier
582
+ end
583
+ ```
584
+
585
+ ### Rust Project Structure Example
586
+
587
+ ```
588
+ my_rust_project/
589
+ ├── Cargo.toml
590
+ ├── src/
591
+ │ ├── lib.rs # Changes run all tests
592
+ │ ├── user.rs # Changes run `cargo test user`
593
+ │ └── utils.rs # Changes run `cargo test utils`
594
+ └── tests/
595
+ ├── integration.rs # Changes run `cargo test --test integration`
596
+ └── api_tests.rs # Changes run `cargo test --test api_tests`
597
+ ```
598
+
599
+ ---
600
+
601
+ ## Notifications
602
+
603
+ Desktop notifications show test results with themed images.
604
+
605
+ ### Notification Systems
606
+
607
+ | System | Platform | Description |
608
+ |--------|----------|-------------|
609
+ | `auto_discover` | All | Automatically detect available notifier |
610
+ | `terminal_notifier` | macOS | Modern macOS notifications |
611
+ | `osascript` | macOS | Built-in AppleScript notifications |
612
+ | `notify_send` | Linux | libnotify notifications |
613
+ | `dunstify` | Linux | Dunst notification daemon |
614
+
615
+ **Configuration:**
616
+ ```ruby
617
+ config.notifications = :terminal_notifier
618
+ ```
619
+
620
+ **Command line:**
621
+ ```bash
622
+ infinity_test --notifications terminal_notifier
623
+ ```
624
+
625
+ ---
626
+
627
+ ## Image Themes
628
+
629
+ Infinity Test includes fun image themes for notifications. Each theme has three images: `success`, `failure`, and `pending`.
630
+
631
+ ### Available Themes
632
+
633
+ | Theme | Description | Location |
634
+ |-------|-------------|----------|
635
+ | `simpson` | The Simpsons characters (default) | `images/simpson/` |
636
+ | `faces` | Expressive face icons | `images/faces/` |
637
+ | `fuuu` | Rage comic faces | `images/fuuu/` |
638
+ | `hands` | Hand gesture icons | `images/hands/` |
639
+ | `mario_bros` | Super Mario characters | `images/mario_bros/` |
640
+ | `rails` | Ruby on Rails themed | `images/rails/` |
641
+ | `rubies` | Ruby gemstone themed | `images/rubies/` |
642
+ | `street_fighter` | Street Fighter characters | `images/street_fighter/` |
643
+ | `toy_story` | Toy Story characters | `images/toy_story/` |
644
+
645
+ ### Using a Theme
646
+
647
+ **Configuration file:**
648
+ ```ruby
649
+ config.mode = :mario_bros
650
+ ```
651
+
652
+ **Command line:**
653
+ ```bash
654
+ infinity_test --mode mario_bros
655
+ ```
656
+
657
+ ### Custom Images
658
+
659
+ Use your own images by setting the image paths directly:
660
+
661
+ ```ruby
662
+ InfinityTest.setup do |config|
663
+ config.success_image = '/path/to/my_success.png'
664
+ config.failure_image = '/path/to/my_failure.png'
665
+ config.pending_image = '/path/to/my_pending.png'
666
+ end
667
+ ```
668
+
669
+ Or point to a custom directory containing `success.*`, `failure.*`, and `pending.*` images:
670
+
671
+ ```ruby
672
+ config.mode = '/path/to/my/images/directory'
673
+ ```
674
+
675
+ ---
676
+
677
+ ## Callbacks
678
+
679
+ Callbacks let you run custom code before or after tests.
680
+
681
+ ### Available Callbacks
682
+
683
+ | Callback | Scope | Description |
684
+ |----------|-------|-------------|
685
+ | `before(:all)` | All | Runs once before all tests |
686
+ | `after(:all)` | All | Runs once after all tests |
687
+ | `before(:each_ruby)` | Per Ruby | Runs before testing each Ruby version |
688
+ | `after(:each_ruby)` | Per Ruby | Runs after testing each Ruby version |
689
+
690
+ ### Examples
691
+
692
+ **Clear terminal before tests:**
693
+ ```ruby
694
+ InfinityTest::Core::Base.before(:all) do
695
+ InfinityTest::Core::Base.clear_terminal
696
+ end
697
+ ```
698
+
699
+ **Play a sound after tests:**
700
+ ```ruby
701
+ InfinityTest::Core::Base.after(:all) do
702
+ system('afplay /path/to/sound.mp3')
703
+ end
704
+ ```
705
+
706
+ **Log Ruby version being tested:**
707
+ ```ruby
708
+ InfinityTest::Core::Base.before(:each_ruby) do |env|
709
+ File.write('test.log', "Testing: #{env[:ruby_version]}\n", mode: 'a')
710
+ end
711
+ ```
712
+
713
+ **Compile extensions before each Ruby:**
714
+ ```ruby
715
+ InfinityTest::Core::Base.before(:each_ruby) do |env|
716
+ system('rake compile')
717
+ end
718
+ ```
719
+
720
+ ---
721
+
722
+ ## File Watching
723
+
724
+ ### Listen (Default)
725
+
726
+ Event-driven file watching using native OS notifications. Fast and efficient.
727
+
728
+ ```ruby
729
+ config.observer = :listen
730
+ ```
731
+
732
+ ### Filewatcher
733
+
734
+ Polling-based file watching. Works everywhere including VMs and NFS mounts.
735
+
736
+ ```ruby
737
+ config.observer = :filewatcher
738
+ ```
739
+
740
+ ---
741
+
742
+ ## Advanced Usage
743
+
744
+ ### Continuous Integration Mode
745
+
746
+ Run tests once and exit with proper exit code:
747
+
748
+ ```bash
749
+ infinity_test -n
750
+ ```
751
+
752
+ Or in configuration:
753
+ ```ruby
754
+ config.infinity_and_beyond = false
755
+ ```
756
+
757
+ ### Just Watch Mode
758
+
759
+ Skip the initial test run and only watch for changes. Useful for large projects:
760
+
761
+ ```bash
762
+ infinity_test --just-watch
763
+ ```
764
+
765
+ ### Focus Mode
766
+
767
+ Run only specific tests:
768
+
769
+ ```bash
770
+ # Run only previously failed tests
771
+ infinity_test --focus failures
772
+
773
+ # Run only a specific file
774
+ infinity_test --focus spec/models/user_spec.rb
775
+ ```
776
+
777
+ ### Ignoring Files
778
+
779
+ ```ruby
780
+ InfinityTest.setup do |config|
781
+ # Ignore specific test files
782
+ config.ignore_test_files = [
783
+ 'spec/slow/large_integration_spec.rb',
784
+ 'spec/external/api_spec.rb'
785
+ ]
786
+
787
+ # Ignore entire directories
788
+ config.ignore_test_folders = [
789
+ 'spec/integration',
790
+ 'spec/system'
791
+ ]
792
+ end
793
+ ```
794
+
795
+ ### Watching Non-Ruby Files
796
+
797
+ ```ruby
798
+ # Watch Python files
799
+ config.extension = :py
800
+
801
+ # Watch JavaScript files
802
+ config.extension = :js
803
+ ```
804
+
805
+ ### Sample Complete Configuration
806
+
807
+ ```ruby
808
+ # INFINITY_TEST
809
+
810
+ InfinityTest.setup do |config|
811
+ # Multi-Ruby testing with RVM
812
+ config.strategy = :rvm
813
+ config.rubies = ['3.1.0', '3.2.0', '3.3.0']
814
+ config.gemset = 'myapp'
815
+
816
+ # Test framework and app framework
817
+ config.test_framework = :rspec
818
+ config.framework = :rails
819
+
820
+ # Notifications with Mario theme
821
+ config.notifications = :terminal_notifier
822
+ config.mode = :mario_bros
823
+
824
+ # Performance settings
825
+ config.observer = :listen
826
+ config.just_watch = false
827
+ config.verbose = true
828
+
829
+ # Ignore slow tests during development
830
+ config.ignore_test_folders = ['spec/system']
831
+ end
832
+
833
+ # Clear screen before each run
834
+ InfinityTest::Core::Base.before(:all) do
835
+ InfinityTest::Core::Base.clear_terminal
836
+ end
837
+
838
+ # Notify via system sound when done
839
+ InfinityTest::Core::Base.after(:all) do
840
+ system('afplay /System/Library/Sounds/Glass.aiff')
841
+ end
842
+ ```
843
+
844
+ ---
845
+
846
+ ## Contributing
847
+
848
+ 1. Fork the repository
849
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
850
+ 3. Run the tests (`infinity_test`)
851
+ 4. Commit your changes (`git commit -am 'Add amazing feature'`)
852
+ 5. Push to the branch (`git push origin feature/amazing-feature`)
853
+ 6. Create a Pull Request
854
+
855
+ ---
856
+
857
+ ## License
858
+
859
+ MIT License - see [LICENSE.txt](LICENSE.txt) for details.
860
+
861
+ ---
862
+
863
+ ## Author
864
+
865
+ Tomas D'Stefano
866
+
867
+ **Happy Testing!**