infinity_test 2.0.0.rc1 → 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +84 -0
  3. data/README.md +249 -9
  4. data/TODO.markdown +36 -27
  5. data/lib/infinity_test/core/auto_discover.rb +3 -3
  6. data/lib/infinity_test/core/command_runner.rb +16 -40
  7. data/lib/infinity_test/core/continuous_test_server.rb +18 -0
  8. data/lib/infinity_test/core/version.rb +1 -1
  9. data/lib/infinity_test/framework/base.rb +36 -0
  10. data/lib/infinity_test/framework/django.rb +109 -0
  11. data/lib/infinity_test/framework/elixir_mix.rb +47 -0
  12. data/lib/infinity_test/framework/fast_api.rb +104 -0
  13. data/lib/infinity_test/framework/padrino.rb +5 -8
  14. data/lib/infinity_test/framework/phoenix.rb +72 -0
  15. data/lib/infinity_test/framework/python_package.rb +97 -0
  16. data/lib/infinity_test/framework/rails.rb +5 -14
  17. data/lib/infinity_test/framework/rocket.rb +70 -0
  18. data/lib/infinity_test/framework/rust_cargo.rb +69 -0
  19. data/lib/infinity_test/strategy/base.rb +17 -1
  20. data/lib/infinity_test/strategy/elixir_default.rb +20 -0
  21. data/lib/infinity_test/strategy/python_default.rb +22 -0
  22. data/lib/infinity_test/strategy/rbenv.rb +3 -1
  23. data/lib/infinity_test/strategy/ruby_default.rb +2 -1
  24. data/lib/infinity_test/strategy/rust_default.rb +21 -0
  25. data/lib/infinity_test/strategy/rvm.rb +3 -1
  26. data/lib/infinity_test/test_framework/cargo_test.rb +49 -0
  27. data/lib/infinity_test/test_framework/ex_unit.rb +53 -0
  28. data/lib/infinity_test/test_framework/pytest.rb +65 -0
  29. data/lib/infinity_test.rb +13 -0
  30. data/spec/infinity_test/core/auto_discover_spec.rb +29 -3
  31. data/spec/infinity_test/framework/django_spec.rb +95 -0
  32. data/spec/infinity_test/framework/elixir_mix_spec.rb +44 -0
  33. data/spec/infinity_test/framework/fast_api_spec.rb +96 -0
  34. data/spec/infinity_test/framework/padrino_spec.rb +28 -6
  35. data/spec/infinity_test/framework/phoenix_spec.rb +85 -0
  36. data/spec/infinity_test/framework/python_package_spec.rb +95 -0
  37. data/spec/infinity_test/framework/rails_spec.rb +28 -6
  38. data/spec/infinity_test/framework/rocket_spec.rb +69 -0
  39. data/spec/infinity_test/framework/rust_cargo_spec.rb +94 -0
  40. data/spec/infinity_test/strategy/elixir_default_spec.rb +46 -0
  41. data/spec/infinity_test/strategy/python_default_spec.rb +56 -0
  42. data/spec/infinity_test/strategy/rbenv_spec.rb +19 -2
  43. data/spec/infinity_test/strategy/ruby_default_spec.rb +19 -2
  44. data/spec/infinity_test/strategy/rust_default_spec.rb +56 -0
  45. data/spec/infinity_test/strategy/rvm_spec.rb +23 -6
  46. data/spec/infinity_test/test_framework/cargo_test_spec.rb +145 -0
  47. data/spec/infinity_test/test_framework/ex_unit_spec.rb +153 -0
  48. data/spec/infinity_test/test_framework/pytest_spec.rb +182 -0
  49. metadata +47 -5
@@ -0,0 +1,109 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class Django < 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 all Django app directories
18
+ # * Watch test dir (.py files) and run the changed file
19
+ # * Watch conftest.py and run all tests
20
+ #
21
+ def heuristics
22
+ watch_django_apps
23
+ watch_dir(test_dir, :py) { |file| run_file(file) } if File.directory?(test_dir.to_s)
24
+ watch(test_helper_file) { run_all } if File.exist?(test_helper_file.to_s)
25
+ end
26
+
27
+ # Auto-discover and watch Django app directories.
28
+ # Django apps have models.py, views.py, or apps.py
29
+ #
30
+ def watch_django_apps
31
+ django_apps = detect_django_apps
32
+
33
+ django_apps.each do |app_dir|
34
+ next unless File.directory?(app_dir)
35
+
36
+ watch_dir(app_dir, :py) { |file| run_app_test(file, app_dir) }
37
+ end
38
+ end
39
+
40
+ # Run test for a Django app file.
41
+ # Maps myapp/models.py -> myapp/tests/test_models.py or myapp/tests.py
42
+ #
43
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
44
+ # @param app_dir [String] The Django app directory
45
+ #
46
+ def run_app_test(changed_file, app_dir)
47
+ basename = File.basename(changed_file.path, '.py')
48
+ app_name = File.basename(app_dir)
49
+
50
+ # Try app/tests/test_*.py pattern
51
+ test_file = File.join(app_dir, 'tests', "test_#{basename}.py")
52
+ if File.exist?(test_file)
53
+ continuous_test_server.rerun_strategy(test_file)
54
+ return
55
+ end
56
+
57
+ # Try app/tests.py (single test file)
58
+ test_file = File.join(app_dir, 'tests.py')
59
+ if File.exist?(test_file)
60
+ continuous_test_server.rerun_strategy(test_file)
61
+ return
62
+ end
63
+
64
+ # Fallback: run all app tests
65
+ test_dir = File.join(app_dir, 'tests')
66
+ if File.directory?(test_dir)
67
+ continuous_test_server.rerun_strategy(test_dir)
68
+ end
69
+ end
70
+
71
+ # ==== Returns
72
+ # TrueClass: Find a Django project (manage.py exists)
73
+ # FalseClass: Not a Django project
74
+ #
75
+ def self.run?
76
+ File.exist?('manage.py') && django_project?
77
+ end
78
+
79
+ def self.django_project?
80
+ return false unless File.exist?('manage.py')
81
+ content = File.read('manage.py')
82
+ content.include?('django') || content.include?('DJANGO')
83
+ rescue
84
+ false
85
+ end
86
+
87
+ private
88
+
89
+ def detect_django_apps
90
+ apps = []
91
+
92
+ # Find directories with Django app markers
93
+ Dir.glob('*').each do |dir|
94
+ next unless File.directory?(dir)
95
+ next if %w[tests test static templates media venv .venv node_modules].include?(dir)
96
+
97
+ # Check for Django app markers
98
+ has_models = File.exist?(File.join(dir, 'models.py'))
99
+ has_views = File.exist?(File.join(dir, 'views.py'))
100
+ has_apps = File.exist?(File.join(dir, 'apps.py'))
101
+
102
+ apps << dir if has_models || has_views || has_apps
103
+ end
104
+
105
+ apps
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,47 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class ElixirMix < 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
+ # * Observe lib dir (.ex files) and run corresponding test.
18
+ # * Observe the test dir (.exs files) and run the same changed file.
19
+ # * Observe the test helper file and run all tests.
20
+ #
21
+ def heuristics
22
+ watch_dir(:lib, :ex) { |file| run_test(file) }
23
+ watch_dir(test_dir, :exs) { |file| run_file(file) }
24
+ watch(test_helper_file) { run_all }
25
+ end
26
+
27
+ # Run test based on the changed file.
28
+ # Maps lib/my_app/user.ex -> test/my_app/user_test.exs
29
+ #
30
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
31
+ #
32
+ def run_test(changed_file)
33
+ file_name = "#{changed_file.path}_test.exs"
34
+ file = hike.find(file_name)
35
+ continuous_test_server.rerun_strategy(file) if file.present?
36
+ end
37
+
38
+ # ==== Returns
39
+ # TrueClass: Find a mix.exs in the user current dir
40
+ # FalseClass: Don't Find a mix.exs in the user current dir
41
+ #
42
+ def self.run?
43
+ File.exist?('mix.exs')
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,104 @@
1
+ module InfinityTest
2
+ module Framework
3
+ class FastApi < 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 app dir (.py files) for FastAPI applications
18
+ # * Watch src dir (.py files) if exists
19
+ # * Watch routers/endpoints directories
20
+ # * Watch test dir (.py files) and run the changed file
21
+ # * Watch conftest.py and run all tests
22
+ #
23
+ def heuristics
24
+ watch_fastapi_dirs
25
+ watch_dir(test_dir, :py) { |file| run_file(file) }
26
+ watch(test_helper_file) { run_all } if File.exist?(test_helper_file.to_s)
27
+ end
28
+
29
+ # Auto-discover and watch FastAPI source directories.
30
+ # Common patterns: app/, src/, routers/, api/
31
+ #
32
+ def watch_fastapi_dirs
33
+ fastapi_dirs = detect_fastapi_source_dirs
34
+
35
+ fastapi_dirs.each do |dir|
36
+ next unless File.directory?(dir)
37
+ next unless Dir.glob("#{dir}/**/*.py").any?
38
+
39
+ watch_dir(dir, :py) { |file| run_test(file) }
40
+ end
41
+ end
42
+
43
+ # Run test based on the changed file.
44
+ #
45
+ # @param changed_file [<InfinityTest::Core::ChangedFile>]
46
+ #
47
+ def run_test(changed_file)
48
+ test_file = find_test_file(changed_file.path)
49
+ continuous_test_server.rerun_strategy(test_file) if test_file.present?
50
+ end
51
+
52
+ # ==== Returns
53
+ # TrueClass: Find a FastAPI project (app/main.py or main.py with FastAPI)
54
+ # FalseClass: Not a FastAPI project
55
+ #
56
+ def self.run?
57
+ return true if File.exist?('app/main.py') && fastapi_in_file?('app/main.py')
58
+ return true if File.exist?('main.py') && fastapi_in_file?('main.py')
59
+ return true if File.exist?('src/main.py') && fastapi_in_file?('src/main.py')
60
+ false
61
+ end
62
+
63
+ def self.fastapi_in_file?(file)
64
+ return false unless File.exist?(file)
65
+ content = File.read(file)
66
+ content.include?('fastapi') || content.include?('FastAPI')
67
+ rescue
68
+ false
69
+ end
70
+
71
+ private
72
+
73
+ def detect_fastapi_source_dirs
74
+ dirs = []
75
+ dirs << 'app' if File.directory?('app')
76
+ dirs << 'src' if File.directory?('src')
77
+ dirs << 'routers' if File.directory?('routers')
78
+ dirs << 'api' if File.directory?('api')
79
+ dirs << 'endpoints' if File.directory?('endpoints')
80
+
81
+ # Also watch root .py files for simple FastAPI apps
82
+ dirs << '.' if Dir.glob('*.py').any? { |f| !f.start_with?('test_') }
83
+
84
+ dirs.uniq
85
+ end
86
+
87
+ def find_test_file(source_path)
88
+ basename = File.basename(source_path, '.py')
89
+
90
+ patterns = [
91
+ "test_#{basename}.py",
92
+ "#{basename}_test.py"
93
+ ]
94
+
95
+ patterns.each do |pattern|
96
+ file = hike.find(pattern)
97
+ return file if file.present?
98
+ end
99
+
100
+ nil
101
+ end
102
+ end
103
+ end
104
+ end
@@ -6,19 +6,16 @@ module InfinityTest
6
6
  # Add Heuristics to the observer run on pattern changes!
7
7
  #
8
8
  # ==== Heuristics
9
- # * Watch app folder (models, controllers, helpers, mailers) and run corresponding tests/specs
9
+ # * Watch all app/* directories and run corresponding tests/specs
10
10
  # * Watch lib dir and run corresponding tests
11
11
  # * Watch test/spec dir and run the changed file
12
12
  # * Watch test/spec helper and run all
13
13
  #
14
14
  def heuristics
15
- watch_dir('app/models') { |file| run_test(file) }
16
- watch_dir('app/controllers') { |file| run_test(file) }
17
- watch_dir('app/helpers') { |file| run_test(file) }
18
- watch_dir('app/mailers') { |file| run_test(file) }
19
- watch_dir(:lib) { |file| run_test(file) }
20
- watch_dir(test_dir) { |file| run_file(file) }
21
- watch(test_helper_file) { run_all }
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 }
22
19
  end
23
20
 
24
21
  # ==== Returns
@@ -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
@@ -6,25 +6,16 @@ module InfinityTest
6
6
  # Add Heuristics to the observer run on pattern changes!
7
7
  #
8
8
  # ==== Heuristics
9
- # * Watch app/models and run corresponding tests/specs
10
- # * Watch app/controllers and run corresponding tests/specs
11
- # * Watch app/helpers and run corresponding tests/specs
12
- # * Watch app/mailers and run corresponding tests/specs
13
- # * Watch app/jobs and run corresponding tests/specs
9
+ # * Watch all app/* directories and run corresponding tests/specs
14
10
  # * Watch lib dir and run corresponding tests
15
11
  # * Watch test/spec dir and run the changed file
16
12
  # * Watch test/spec helper and run all
17
- # * Watch config/routes.rb and run routing specs
18
13
  #
19
14
  def heuristics
20
- watch_dir('app/models') { |file| run_test(file) }
21
- watch_dir('app/controllers') { |file| run_test(file) }
22
- watch_dir('app/helpers') { |file| run_test(file) }
23
- watch_dir('app/mailers') { |file| run_test(file) }
24
- watch_dir('app/jobs') { |file| run_test(file) }
25
- watch_dir(:lib) { |file| run_test(file) }
26
- watch_dir(test_dir) { |file| run_file(file) }
27
- watch(test_helper_file) { run_all }
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 }
28
19
  end
29
20
 
30
21
  def self.run?
@@ -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,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
@@ -13,9 +13,25 @@ module InfinityTest
13
13
  end
14
14
 
15
15
  # Run the strategy and parse the results storing in the strategy.
16
+ # Prints the command before executing if verbose mode is enabled.
16
17
  #
17
18
  def run
18
- Core::CommandRunner.new(run!)
19
+ command = run!
20
+ puts "\n\e[96m[InfinityTest]\e[0m - Command: '\e[32m#{command}\e[0m'\n\n" if Core::Base.verbose?
21
+ Core::CommandRunner.new(command)
22
+ end
23
+
24
+ # Check if bundler should be used.
25
+ # Returns true if bundler is enabled and Gemfile exists.
26
+ #
27
+ def use_bundler?
28
+ Core::Base.using_bundler? && File.exist?('Gemfile')
29
+ end
30
+
31
+ # Wrap command with bundle exec if bundler should be used.
32
+ #
33
+ def with_bundler(command)
34
+ use_bundler? ? "bundle exec #{command}" : command
19
35
  end
20
36
 
21
37
  # Implement #run! method returning a string command to be run.
@@ -0,0 +1,20 @@
1
+ module InfinityTest
2
+ module Strategy
3
+ class ElixirDefault < Base
4
+ attr_reader :continuous_test_server
5
+ delegate :binary, :test_files, to: :continuous_test_server
6
+
7
+ def run!
8
+ command = "#{binary} test #{test_files}"
9
+ command = "#{command} #{Core::Base.specific_options}" if Core::Base.specific_options.present?
10
+ command
11
+ end
12
+
13
+ # Run when the project has mix.exs (Elixir project)
14
+ #
15
+ def self.run?
16
+ File.exist?('mix.exs')
17
+ end
18
+ end
19
+ end
20
+ end