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
@@ -0,0 +1,72 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Phoenix < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Override to use .exs extension for Elixir test files.
7
+ #
8
+ def heuristics!
9
+ hike.append_extension('.exs')
10
+ hike.append_path(test_framework.test_dir)
11
+ heuristics
12
+ end
13
+
14
+ # Add Heuristics to the observer run on pattern changes!
15
+ #
16
+ # ==== Heuristics
17
+ # * Watch all lib/*_web directories (controllers, views, live, channels)
18
+ # * Watch lib dir (.ex files) and run corresponding test
19
+ # * Watch test dir (.exs files) and run the changed file
20
+ # * Watch test helper and run all tests
21
+ #
22
+ def heuristics
23
+ watch_lib_dirs
24
+ watch_dir(test_dir, :exs) { |file| run_file(file) }
25
+ watch(test_helper_file) { run_all }
26
+ end
27
+
28
+ # Auto-discover and watch all directories under lib/ that contain .ex files.
29
+ # Maps lib/my_app/accounts to test/my_app/accounts, etc.
30
+ #
31
+ def watch_lib_dirs
32
+ return unless File.directory?('lib')
33
+
34
+ Dir.glob('lib/*').each do |lib_dir|
35
+ next unless File.directory?(lib_dir)
36
+ next unless Dir.glob("#{lib_dir}/**/*.ex").any?
37
+
38
+ watch_dir(lib_dir, :ex) { |file| run_test_in_lib(file, lib_dir) }
39
+ end
40
+ end
41
+
42
+ # Run test preserving the directory structure.
43
+ # E.g: lib/my_app_web/controllers/user_controller.ex -> test/my_app_web/controllers/user_controller_test.exs
44
+ #
45
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
46
+ # @param lib_dir [String] The lib directory (e.g., 'lib/my_app_web')
47
+ #
48
+ def run_test_in_lib(changed_file, lib_dir)
49
+ subdir = File.basename(lib_dir)
50
+ test_file = File.join(test_framework.test_dir, subdir, "#{changed_file.path}_test.exs")
51
+
52
+ if File.exist?(test_file)
53
+ continuous_test_server.rerun_strategy(test_file)
54
+ else
55
+ # Fallback: try finding with hike in test_dir/subdir
56
+ hike.prepend_path(File.join(test_framework.test_dir, subdir))
57
+ file_name = "#{changed_file.path}_test.exs"
58
+ file = hike.find(file_name)
59
+ continuous_test_server.rerun_strategy(file) if file.present?
60
+ end
61
+ end
62
+
63
+ # ==== Returns
64
+ # TrueClass: Find a Phoenix project (has lib/*_web directory)
65
+ # FalseClass: Not a Phoenix project
66
+ #
67
+ def self.run?
68
+ File.exist?('mix.exs') && Dir.glob('lib/*_web').any?
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,97 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class PythonPackage < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Override to use .py extension for Python test files.
7
+ #
8
+ def heuristics!
9
+ hike.append_extension('.py')
10
+ hike.append_path(test_framework.test_dir)
11
+ heuristics
12
+ end
13
+
14
+ # Add Heuristics to the observer run on pattern changes!
15
+ #
16
+ # ==== Heuristics
17
+ # * Watch src dir (.py files) and run corresponding test
18
+ # * Watch package dirs (.py files) and run corresponding test
19
+ # * Watch test dir (.py files) and run the changed file
20
+ # * Watch conftest.py and run all tests
21
+ #
22
+ def heuristics
23
+ watch_python_dirs
24
+ watch_dir(test_dir, :py) { |file| run_file(file) }
25
+ watch(test_helper_file) { run_all } if File.exist?(test_helper_file.to_s)
26
+ end
27
+
28
+ # Auto-discover and watch Python source directories.
29
+ # Common patterns: src/, package_name/, lib/
30
+ #
31
+ def watch_python_dirs
32
+ python_dirs = detect_python_source_dirs
33
+
34
+ python_dirs.each do |dir|
35
+ next unless File.directory?(dir)
36
+ next unless Dir.glob("#{dir}/**/*.py").any?
37
+
38
+ watch_dir(dir, :py) { |file| run_test(file) }
39
+ end
40
+ end
41
+
42
+ # Run test based on the changed file.
43
+ # Maps src/mypackage/utils.py -> tests/test_utils.py or tests/mypackage/test_utils.py
44
+ #
45
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
46
+ #
47
+ def run_test(changed_file)
48
+ # Try test_filename.py pattern first
49
+ test_file = find_test_file(changed_file.path)
50
+ continuous_test_server.rerun_strategy(test_file) if test_file.present?
51
+ end
52
+
53
+ # ==== Returns
54
+ # TrueClass: Find a Python package (pyproject.toml, setup.py, or setup.cfg)
55
+ # FalseClass: Not a Python package
56
+ #
57
+ def self.run?
58
+ File.exist?('pyproject.toml') ||
59
+ File.exist?('setup.py') ||
60
+ File.exist?('setup.cfg')
61
+ end
62
+
63
+ private
64
+
65
+ def detect_python_source_dirs
66
+ dirs = []
67
+ dirs << 'src' if File.directory?('src')
68
+ dirs << 'lib' if File.directory?('lib') && Dir.glob('lib/**/*.py').any?
69
+
70
+ # Detect package directories (directories with __init__.py)
71
+ Dir.glob('*/__init__.py').each do |init_file|
72
+ dir = File.dirname(init_file)
73
+ dirs << dir unless %w[tests test].include?(dir)
74
+ end
75
+
76
+ dirs.uniq
77
+ end
78
+
79
+ def find_test_file(source_path)
80
+ basename = File.basename(source_path, '.py')
81
+
82
+ # Try various test file patterns
83
+ patterns = [
84
+ "test_#{basename}.py",
85
+ "#{basename}_test.py"
86
+ ]
87
+
88
+ patterns.each do |pattern|
89
+ file = hike.find(pattern)
90
+ return file if file.present?
91
+ end
92
+
93
+ nil
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,26 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Rails < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Add Heuristics to the observer run on pattern changes!
7
+ #
8
+ # ==== Heuristics
9
+ # * Watch all app/* directories and run corresponding tests/specs
10
+ # * Watch lib dir and run corresponding tests
11
+ # * Watch test/spec dir and run the changed file
12
+ # * Watch test/spec helper and run all
13
+ #
14
+ def heuristics
15
+ watch_app_dirs
16
+ watch_dir(:lib) { |file| run_test(file) }
17
+ watch_dir(test_dir) { |file| run_file(file) }
18
+ watch(test_helper_file) { run_all }
19
+ end
20
+
21
+ def self.run?
22
+ File.exist?(File.expand_path('./config/environment.rb'))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Rocket < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Override to use .rs extension for Rust files.
7
+ #
8
+ def heuristics!
9
+ hike.append_extension('.rs')
10
+ hike.append_path(test_framework.test_dir) if File.directory?(test_framework.test_dir.to_s)
11
+ heuristics
12
+ end
13
+
14
+ # Add Heuristics to the observer run on pattern changes!
15
+ #
16
+ # ==== Heuristics
17
+ # * Watch src dir (.rs files) and run tests matching the module name
18
+ # * Watch tests dir (.rs files) and run the changed integration test
19
+ # * Watch Cargo.toml and run all tests
20
+ # * Watch Rocket.toml if exists and run all tests
21
+ #
22
+ def heuristics
23
+ watch_dir(:src, :rs) { |file| run_module_tests(file) }
24
+ watch_dir(test_dir, :rs) { |file| run_integration_test(file) } if File.directory?(test_dir.to_s)
25
+ watch(test_helper_file) { run_all }
26
+ watch('Rocket.toml') { run_all } if File.exist?('Rocket.toml')
27
+ end
28
+
29
+ # Run tests matching the module name.
30
+ # E.g: src/routes.rs -> cargo test routes
31
+ #
32
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
33
+ #
34
+ def run_module_tests(changed_file)
35
+ module_name = File.basename(changed_file.name, '.rs')
36
+ # lib.rs and main.rs changes should run all tests
37
+ if %w[lib main].include?(module_name)
38
+ run_all
39
+ else
40
+ continuous_test_server.rerun_strategy(module_name)
41
+ end
42
+ end
43
+
44
+ # Run a specific integration test file.
45
+ #
46
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
47
+ #
48
+ def run_integration_test(changed_file)
49
+ test_name = File.basename(changed_file.name, '.rs')
50
+ continuous_test_server.rerun_strategy("--test #{test_name}")
51
+ end
52
+
53
+ # ==== Returns
54
+ # TrueClass: Find a Rocket project (Cargo.toml with rocket dependency)
55
+ # FalseClass: Not a Rocket project
56
+ #
57
+ def self.run?
58
+ File.exist?('Cargo.toml') && rocket_project?
59
+ end
60
+
61
+ def self.rocket_project?
62
+ return false unless File.exist?('Cargo.toml')
63
+ content = File.read('Cargo.toml')
64
+ content.include?('rocket')
65
+ rescue
66
+ false
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,29 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Rubygems < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Add Heuristics to the observer run on pattern changes!
7
+ #
8
+ # ==== Heuristics
9
+ # * Add Gemfile and Run bundle install and run all specs.
10
+ # * Observe lib dir and run test.
11
+ # * Observe the test dir and run the same changed file.
12
+ # * Observe the test helper file and run.
13
+ #
14
+ def heuristics
15
+ watch_dir(:lib) { |file| run_test(file) }
16
+ watch_dir(test_dir) { |file| run_file(file) }
17
+ watch(test_helper_file) { run_all }
18
+ end
19
+
20
+ # ==== Returns
21
+ # TrueClass: Find a gemspec in the user current dir
22
+ # FalseClass: Don't Find a gemspec in the user current dir
23
+ #
24
+ def self.run?
25
+ Dir["*.gemspec"].present?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class RustCargo < Base
4
+ delegate :test_dir, :test_helper_file, to: :test_framework
5
+
6
+ # Override to use .rs extension for Rust files.
7
+ #
8
+ def heuristics!
9
+ hike.append_extension('.rs')
10
+ hike.append_path(test_framework.test_dir) if File.directory?(test_framework.test_dir.to_s)
11
+ heuristics
12
+ end
13
+
14
+ # Add Heuristics to the observer run on pattern changes!
15
+ #
16
+ # ==== Heuristics
17
+ # * Watch src dir (.rs files) and run tests matching the module name
18
+ # * Watch tests dir (.rs files) and run the changed integration test
19
+ # * Watch Cargo.toml and run all tests
20
+ #
21
+ def heuristics
22
+ watch_dir(:src, :rs) { |file| run_module_tests(file) }
23
+ watch_dir(test_dir, :rs) { |file| run_integration_test(file) } if File.directory?(test_dir.to_s)
24
+ watch(test_helper_file) { run_all }
25
+ end
26
+
27
+ # Run tests matching the module name.
28
+ # E.g: src/user.rs -> cargo test user
29
+ #
30
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
31
+ #
32
+ def run_module_tests(changed_file)
33
+ module_name = File.basename(changed_file.name, '.rs')
34
+ # lib.rs and main.rs changes should run all tests
35
+ if %w[lib main].include?(module_name)
36
+ run_all
37
+ else
38
+ continuous_test_server.rerun_strategy(module_name)
39
+ end
40
+ end
41
+
42
+ # Run a specific integration test file.
43
+ # For tests in tests/, run cargo test --test <name>
44
+ #
45
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
46
+ #
47
+ def run_integration_test(changed_file)
48
+ test_name = File.basename(changed_file.name, '.rs')
49
+ continuous_test_server.rerun_strategy("--test #{test_name}")
50
+ end
51
+
52
+ # ==== Returns
53
+ # TrueClass: Find a Rust project (Cargo.toml exists)
54
+ # FalseClass: Not a Rust project
55
+ #
56
+ def self.run?
57
+ File.exist?('Cargo.toml') && !rocket_project?
58
+ end
59
+
60
+ def self.rocket_project?
61
+ return false unless File.exist?('Cargo.toml')
62
+ content = File.read('Cargo.toml')
63
+ content.include?('rocket')
64
+ rescue
65
+ false
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,47 @@
1
+ module InfinityTest
2
+ module Framework
3
+ module SharedExample
4
+ # Shared Examples to use in the RSpec specs when you want create your own observer.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # RSpec.configure do |config|
9
+ # config.include InfinityTest::Observer::SharedExample
10
+ # end
11
+ #
12
+ # describe BarObserver do
13
+ # it_should_behave_like 'an infinity test observer'
14
+ # end
15
+ #
16
+ shared_examples_for 'an infinity test framework' do
17
+ it 'responds to #heuristics' do
18
+ expect(subject).to respond_to(:heuristics)
19
+ end
20
+
21
+ it 'responds to #heuristics!' do
22
+ expect(subject).to respond_to(:heuristics!)
23
+ end
24
+
25
+ it 'responds to .run?' do
26
+ expect(subject.class).to respond_to(:run?)
27
+ end
28
+
29
+ it 'responds to #base' do
30
+ expect(subject).to respond_to(:base)
31
+ end
32
+
33
+ it 'responds to #test_framework' do
34
+ expect(subject).to respond_to(:test_framework)
35
+ end
36
+
37
+ it 'responds to #strategy' do
38
+ expect(subject).to respond_to(:strategy)
39
+ end
40
+
41
+ it 'responds to #observer' do
42
+ expect(subject).to respond_to(:observer)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ module InfinityTest
2
+ module Observer
3
+ class Base
4
+ attr_accessor :continuous_test_server
5
+
6
+ def initialize(continuous_test_server)
7
+ @continuous_test_server = continuous_test_server
8
+ end
9
+
10
+ def watch(pattern_or_file, &block)
11
+ raise NotImplementedError, "not implemented in #{self}"
12
+ end
13
+
14
+ def watch_dir(dir_name, extension, &block)
15
+ raise NotImplementedError, "not implemented in #{self}"
16
+ end
17
+
18
+ def start!
19
+ signal
20
+ start
21
+ end
22
+
23
+ def start
24
+ raise NotImplementedError, "not implemented in #{self}"
25
+ end
26
+
27
+ def signal
28
+ Signal.trap('INT') do
29
+ if @interrupt_at && (Time.now - @interrupt_at) < 2
30
+ puts " To Infinity and Beyond!"
31
+ exit
32
+ else
33
+ puts " Are you sure? :S ... Interrupt a second time to quit!"
34
+ @interrupt_at = Time.now
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,72 @@
1
+ require 'filewatcher'
2
+
3
+ module InfinityTest
4
+ module Observer
5
+ class Filewatcher < Base
6
+ attr_reader :observer, :watch_paths, :patterns
7
+
8
+ def initialize(continuous_test_server)
9
+ super
10
+ @watch_paths = []
11
+ @patterns = {}
12
+ end
13
+
14
+ # Watch a file or pattern for changes.
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # watch('lib/(.*)\.rb') { |file| puts [file.name, file.path, file.match_data] }
19
+ # watch('test/test_helper.rb') { run_all() }
20
+ #
21
+ def watch(pattern_or_file, &block)
22
+ pattern = Regexp.new(pattern_or_file.to_s)
23
+ @patterns[pattern] = block
24
+ end
25
+
26
+ # Watch a directory for changes.
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # watch_dir(:lib) { |file| run_test(file) }
31
+ # watch_dir(:test) { |file| run_file(file) }
32
+ #
33
+ # watch_dir(:test, :py) { |file| puts [file.name, file.path, file.match_data] }
34
+ # watch_dir(:test, :js) { |file| puts [file.name, file.path, file.match_data] }
35
+ #
36
+ def watch_dir(dir_name, extension = :rb, &block)
37
+ watch("^#{dir_name}/*/(.*).#{extension}", &block)
38
+ path = "#{dir_name}/**/*.#{extension}"
39
+ @watch_paths << path unless @watch_paths.include?(path)
40
+ end
41
+
42
+ # Start the continuous test server.
43
+ #
44
+ def start
45
+ paths = @watch_paths.empty? ? ['**/*.rb'] : @watch_paths
46
+
47
+ @observer = ::Filewatcher.new(paths)
48
+
49
+ @observer.watch do |changes|
50
+ changes.each do |file_path, _event|
51
+ relative_path = file_path.sub("#{Dir.pwd}/", '')
52
+ handle_file_change(relative_path)
53
+ end
54
+ end
55
+ rescue Interrupt
56
+ @observer.stop if @observer
57
+ end
58
+
59
+ private
60
+
61
+ def handle_file_change(file_path)
62
+ @patterns.each do |pattern, block|
63
+ if match_data = pattern.match(file_path)
64
+ changed_file = InfinityTest::Core::ChangedFile.new(match_data)
65
+ block.call(changed_file)
66
+ break
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,74 @@
1
+ require 'listen'
2
+
3
+ module InfinityTest
4
+ module Observer
5
+ class Listen < Base
6
+ attr_reader :observer, :directories, :patterns
7
+
8
+ def initialize(continuous_test_server)
9
+ super
10
+ @directories = []
11
+ @patterns = {}
12
+ end
13
+
14
+ # Watch a file or pattern for changes.
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # watch('lib/(.*)\.rb') { |file| puts [file.name, file.path, file.match_data] }
19
+ # watch('test/test_helper.rb') { run_all() }
20
+ #
21
+ def watch(pattern_or_file, &block)
22
+ pattern = Regexp.new(pattern_or_file.to_s)
23
+ @patterns[pattern] = block
24
+ end
25
+
26
+ # Watch a directory for changes.
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # watch_dir(:lib) { |file| run_test(file) }
31
+ # watch_dir(:test) { |file| run_file(file) }
32
+ #
33
+ # watch_dir(:test, :py) { |file| puts [file.name, file.path, file.match_data] }
34
+ # watch_dir(:test, :js) { |file| puts [file.name, file.path, file.match_data] }
35
+ #
36
+ def watch_dir(dir_name, extension = :rb, &block)
37
+ watch("^#{dir_name}/*/(.*).#{extension}", &block)
38
+ @directories << dir_name.to_s unless @directories.include?(dir_name.to_s)
39
+ end
40
+
41
+ # Start the continuous test server.
42
+ #
43
+ def start
44
+ dirs = @directories.empty? ? ['.'] : @directories
45
+ dirs = dirs.select { |d| File.directory?(d) }
46
+ dirs = ['.'] if dirs.empty?
47
+
48
+ @observer = ::Listen.to(*dirs) do |modified, added, _removed|
49
+ (modified + added).each do |file|
50
+ relative_path = file.sub("#{Dir.pwd}/", '')
51
+ handle_file_change(relative_path)
52
+ end
53
+ end
54
+
55
+ @observer.start
56
+ sleep
57
+ rescue Interrupt
58
+ @observer.stop if @observer
59
+ end
60
+
61
+ private
62
+
63
+ def handle_file_change(file_path)
64
+ @patterns.each do |pattern, block|
65
+ if match_data = pattern.match(file_path)
66
+ changed_file = InfinityTest::Core::ChangedFile.new(match_data)
67
+ block.call(changed_file)
68
+ break
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ module InfinityTest
2
+ module Observer
3
+ module SharedExample
4
+ # Shared Examples to use in the RSpec specs when you want create your own observer.
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # RSpec.configure do |config|
9
+ # config.include InfinityTest::Observer::SharedExample
10
+ # end
11
+ #
12
+ # describe BarObserver do
13
+ # it_should_behave_like 'an infinity test observer'
14
+ # end
15
+ #
16
+ shared_examples_for 'an infinity test observer' do
17
+ it 'responds to #observer' do
18
+ expect(subject).to respond_to(:observer)
19
+ end
20
+
21
+ it 'responds to #watch_dir' do
22
+ expect(subject).to respond_to(:watch_dir)
23
+ end
24
+
25
+ it 'responds to #watch' do
26
+ expect(subject).to respond_to(:watch)
27
+ end
28
+
29
+ it 'responds to #start' do
30
+ expect(subject).to respond_to(:start)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ module InfinityTest
2
+ module OldDSL
3
+ class Configuration
4
+ # Pass the responsability to InfinityTest::Base class.
5
+ #
6
+ # <b>Don't need #super or #respond_to here.</b>
7
+ # <b>This class will be removed in infinity_test 2.0.1</b>
8
+ #
9
+ def method_missing(method_name, *arguments, &block)
10
+ InfinityTest::Base.send(method_name, *arguments, &block)
11
+ end
12
+ end
13
+
14
+ module InfinityTestMethod
15
+ # <b>DEPRECATED:</b> Please use <tt>InfinityTest::Base.setup</tt> instead.
16
+ #
17
+ def infinity_test(&block)
18
+ message = "infinity_test method is deprecated. Use InfinityTest.setup { |config| ... } instead."
19
+ ActiveSupport::Deprecation.warn(message)
20
+ ::InfinityTest::OldDSL::Configuration.new.instance_eval(&block)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ include InfinityTest::OldDSL::InfinityTestMethod