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.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +31 -0
- data/.gitignore +3 -0
- data/.rspec +2 -2
- data/AI_INTEGRATION_IDEAS.md +203 -0
- data/Gemfile +3 -15
- data/HISTORY.md +84 -0
- data/History.markdown +82 -0
- data/{.infinity_test → INFINITY_TEST} +18 -15
- data/LICENSE.txt +2 -2
- data/README.md +867 -0
- data/Rakefile +1 -65
- data/TODO.markdown +38 -24
- data/bin/infinity_test +1 -4
- data/images/fuuu/pending.png +0 -0
- data/images/fuuu/success.png +0 -0
- data/infinity_test.gemspec +41 -189
- data/lib/infinity_test/core/auto_discover.rb +67 -0
- data/lib/infinity_test/core/base.rb +369 -0
- data/lib/infinity_test/core/callback.rb +59 -0
- data/lib/infinity_test/core/changed_file.rb +13 -0
- data/lib/infinity_test/core/command_builder.rb +48 -0
- data/lib/infinity_test/core/command_runner.rb +38 -0
- data/lib/infinity_test/core/configuration_merge.rb +37 -0
- data/lib/infinity_test/core/continuous_test_server.rb +124 -0
- data/lib/infinity_test/core/load_configuration.rb +48 -0
- data/lib/infinity_test/core/notifier.rb +59 -0
- data/lib/infinity_test/core/options.rb +134 -0
- data/lib/infinity_test/core/runner.rb +18 -0
- data/lib/infinity_test/core/version.rb +5 -0
- data/lib/infinity_test/framework/base.rb +93 -0
- data/lib/infinity_test/framework/django.rb +109 -0
- data/lib/infinity_test/framework/elixir_mix.rb +47 -0
- data/lib/infinity_test/framework/fast_api.rb +104 -0
- data/lib/infinity_test/framework/padrino.rb +30 -0
- data/lib/infinity_test/framework/phoenix.rb +72 -0
- data/lib/infinity_test/framework/python_package.rb +97 -0
- data/lib/infinity_test/framework/rails.rb +26 -0
- data/lib/infinity_test/framework/rocket.rb +70 -0
- data/lib/infinity_test/framework/rubygems.rb +29 -0
- data/lib/infinity_test/framework/rust_cargo.rb +69 -0
- data/lib/infinity_test/framework/shared_example.rb +47 -0
- data/lib/infinity_test/observer/base.rb +40 -0
- data/lib/infinity_test/observer/filewatcher.rb +72 -0
- data/lib/infinity_test/observer/listen.rb +74 -0
- data/lib/infinity_test/observer/shared_example.rb +35 -0
- data/lib/infinity_test/old_dsl/configuration.rb +26 -0
- data/lib/infinity_test/strategy/base.rb +50 -0
- data/lib/infinity_test/strategy/elixir_default.rb +20 -0
- data/lib/infinity_test/strategy/python_default.rb +22 -0
- data/lib/infinity_test/strategy/rbenv.rb +34 -0
- data/lib/infinity_test/strategy/ruby_default.rb +21 -0
- data/lib/infinity_test/strategy/rust_default.rb +21 -0
- data/lib/infinity_test/strategy/rvm.rb +52 -0
- data/lib/infinity_test/strategy/shared_example.rb +32 -0
- data/lib/infinity_test/test_framework/base.rb +64 -0
- data/lib/infinity_test/test_framework/cargo_test.rb +49 -0
- data/lib/infinity_test/test_framework/ex_unit.rb +53 -0
- data/lib/infinity_test/test_framework/pytest.rb +65 -0
- data/lib/infinity_test/test_framework/rspec.rb +48 -0
- data/lib/infinity_test/test_framework/shared_example.rb +56 -0
- data/lib/infinity_test/test_framework/test_unit.rb +57 -0
- data/lib/infinity_test.rb +66 -35
- data/spec/infinity_test/core/auto_discover_spec.rb +175 -0
- data/spec/infinity_test/core/base_spec.rb +240 -0
- data/spec/infinity_test/core/callback_spec.rb +89 -0
- data/spec/infinity_test/core/changed_file_spec.rb +26 -0
- data/spec/infinity_test/core/command_builder_spec.rb +38 -0
- data/spec/infinity_test/core/configuration_merge_spec.rb +124 -0
- data/spec/infinity_test/core/continuous_test_server_spec.rb +116 -0
- data/spec/infinity_test/core/load_configuration_spec.rb +43 -0
- data/spec/infinity_test/core/notifier_spec.rb +151 -0
- data/spec/infinity_test/core/options_spec.rb +168 -0
- data/spec/infinity_test/core/runner_spec.rb +17 -0
- data/spec/infinity_test/framework/base_spec.rb +55 -0
- data/spec/infinity_test/framework/django_spec.rb +95 -0
- data/spec/infinity_test/framework/elixir_mix_spec.rb +44 -0
- data/spec/infinity_test/framework/fast_api_spec.rb +96 -0
- data/spec/infinity_test/framework/padrino_spec.rb +58 -0
- data/spec/infinity_test/framework/phoenix_spec.rb +85 -0
- data/spec/infinity_test/framework/python_package_spec.rb +95 -0
- data/spec/infinity_test/framework/rails_spec.rb +58 -0
- data/spec/infinity_test/framework/rocket_spec.rb +69 -0
- data/spec/infinity_test/framework/rubygems_spec.rb +34 -0
- data/spec/infinity_test/framework/rust_cargo_spec.rb +94 -0
- data/spec/infinity_test/observer/base_spec.rb +78 -0
- data/spec/infinity_test/observer/filewatcher_spec.rb +51 -0
- data/spec/infinity_test/observer/listen_spec.rb +50 -0
- data/spec/infinity_test/{builder_spec.rb → strategy/base_spec.rb} +1 -2
- data/spec/infinity_test/strategy/elixir_default_spec.rb +46 -0
- data/spec/infinity_test/strategy/python_default_spec.rb +56 -0
- data/spec/infinity_test/strategy/rbenv_spec.rb +70 -0
- data/spec/infinity_test/strategy/ruby_default_spec.rb +49 -0
- data/spec/infinity_test/strategy/rust_default_spec.rb +56 -0
- data/spec/infinity_test/strategy/rvm_spec.rb +86 -0
- data/spec/infinity_test/test_framework/cargo_test_spec.rb +145 -0
- data/spec/infinity_test/test_framework/ex_unit_spec.rb +153 -0
- data/spec/infinity_test/test_framework/pytest_spec.rb +182 -0
- data/spec/infinity_test/test_framework/rspec_spec.rb +119 -0
- data/spec/infinity_test/test_framework/test_unit_spec.rb +193 -0
- data/spec/spec_helper.rb +34 -119
- metadata +315 -177
- data/.rvmrc +0 -1
- data/Gemfile.lock +0 -62
- data/Readme.markdown +0 -147
- data/Tasks +0 -4
- data/VERSION.yml +0 -5
- data/buzz_images/buzz_lightyear.jpg +0 -0
- data/buzz_images/buzz_lightyear_continencia.gif +0 -0
- data/buzz_images/to_infinity_and_beyond.png +0 -0
- data/features/heuristics.feature +0 -23
- data/features/support/env.rb +0 -2
- data/images/fuuu/sucess.png +0 -0
- data/lib/infinity_test/application.rb +0 -362
- data/lib/infinity_test/application_library/rails.rb +0 -94
- data/lib/infinity_test/application_library/rubygems.rb +0 -43
- data/lib/infinity_test/binary_path.rb +0 -43
- data/lib/infinity_test/builder.rb +0 -66
- data/lib/infinity_test/command.rb +0 -58
- data/lib/infinity_test/configuration.rb +0 -277
- data/lib/infinity_test/continuous_testing.rb +0 -40
- data/lib/infinity_test/dependencies.rb +0 -80
- data/lib/infinity_test/environment.rb +0 -15
- data/lib/infinity_test/heuristics.rb +0 -36
- data/lib/infinity_test/heuristics_helper.rb +0 -9
- data/lib/infinity_test/options.rb +0 -96
- data/lib/infinity_test/runner.rb +0 -38
- data/lib/infinity_test/test_framework.rb +0 -110
- data/lib/infinity_test/test_library/bacon.rb +0 -55
- data/lib/infinity_test/test_library/cucumber.rb +0 -22
- data/lib/infinity_test/test_library/rspec.rb +0 -60
- data/lib/infinity_test/test_library/test_unit.rb +0 -52
- data/lib/infinity_test/test_unit_loader.rb +0 -5
- data/spec/factories/buzz/lib/buzz.rb +0 -0
- data/spec/factories/buzz/spec/buzz_spec.rb +0 -0
- data/spec/factories/company/Gemfile +0 -0
- data/spec/factories/company/lib/company.rb +0 -0
- data/spec/factories/company/test/company_test.rb +0 -0
- data/spec/factories/images/failure.png +0 -0
- data/spec/factories/images/pending.png +0 -0
- data/spec/factories/images/sucess.png +0 -0
- data/spec/factories/infinity_test +0 -5
- data/spec/factories/infinity_test_example +0 -7
- data/spec/factories/slinky/spec/slinky/slinky_spec.rb +0 -0
- data/spec/factories/travel/lib/travel.rb +0 -0
- data/spec/factories/travel/test/partner_test.rb +0 -0
- data/spec/factories/travel/test/travel_test.rb +0 -0
- data/spec/factories/wood/lib/wood.rb +0 -0
- data/spec/factories/wood/spec/wood_spec.rb +0 -0
- data/spec/infinity_test/application_library/rails_spec.rb +0 -140
- data/spec/infinity_test/application_library/rubygems_spec.rb +0 -52
- data/spec/infinity_test/application_spec.rb +0 -434
- data/spec/infinity_test/binary_path_spec.rb +0 -72
- data/spec/infinity_test/command_spec.rb +0 -53
- data/spec/infinity_test/configuration_spec.rb +0 -382
- data/spec/infinity_test/continuous_testing_spec.rb +0 -25
- data/spec/infinity_test/environment_spec.rb +0 -23
- data/spec/infinity_test/heuristics_helper_spec.rb +0 -15
- data/spec/infinity_test/heuristics_spec.rb +0 -127
- data/spec/infinity_test/options_spec.rb +0 -111
- data/spec/infinity_test/runner_spec.rb +0 -42
- data/spec/infinity_test/test_framework_spec.rb +0 -127
- data/spec/infinity_test/test_library/bacon_spec.rb +0 -150
- data/spec/infinity_test/test_library/cucumber_spec.rb +0 -8
- data/spec/infinity_test/test_library/rspec_spec.rb +0 -189
- data/spec/infinity_test/test_library/test_unit_spec.rb +0 -184
- data/spec/infinity_test_spec.rb +0 -40
- /data/images/faces/{sucess.png → success.png} +0 -0
- /data/images/hands/{sucess.png → success.png} +0 -0
- /data/images/mario_bros/{sucess.jpg → success.jpg} +0 -0
- /data/images/rails/{sucess.png → success.png} +0 -0
- /data/images/rubies/{sucess.png → success.png} +0 -0
- /data/images/simpson/{sucess.jpg → success.jpg} +0 -0
- /data/images/street_fighter/{sucess.jpg → success.jpg} +0 -0
- /data/images/toy_story/{sucess.png → success.png} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Core
|
|
3
|
+
class LoadConfiguration
|
|
4
|
+
attr_accessor :global_file, :project_file
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@global_file = File.expand_path('~/INFINITY_TEST')
|
|
8
|
+
@project_file = './INFINITY_TEST'
|
|
9
|
+
@old_configuration = InfinityTest::OldDSL::Configuration
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Load the Configuration file
|
|
13
|
+
#
|
|
14
|
+
# Command line options can be persisted in an INFINITY_TEST file in a project.
|
|
15
|
+
# You can also store an INFINITY_TEST file in your home directory (~/INFINITY_TEST)
|
|
16
|
+
#
|
|
17
|
+
# Precedence is:
|
|
18
|
+
# command line
|
|
19
|
+
# ./INFINITY_TEST
|
|
20
|
+
# ~/INFINITY_TEST
|
|
21
|
+
#
|
|
22
|
+
# Example:
|
|
23
|
+
#
|
|
24
|
+
# ~/INFINITY_TEST -> infinity_test { notifications :osascript }
|
|
25
|
+
#
|
|
26
|
+
# ./INFINITY_TEST -> infinity_test { notifications :terminal_notifier } # High Priority
|
|
27
|
+
#
|
|
28
|
+
# After the load the Notifications Framework will be Terminal Notifier
|
|
29
|
+
#
|
|
30
|
+
def load!
|
|
31
|
+
load_global_file!
|
|
32
|
+
load_project_file!
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def load_global_file!
|
|
36
|
+
load_file(@global_file)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def load_project_file!
|
|
40
|
+
load_file(@project_file)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def load_file(file)
|
|
44
|
+
load(file) if File.exist?(file)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Core
|
|
3
|
+
class Notifier
|
|
4
|
+
include ::Notifiers
|
|
5
|
+
|
|
6
|
+
attr_reader :test_framework, :library
|
|
7
|
+
|
|
8
|
+
IMAGES = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'images'))
|
|
9
|
+
|
|
10
|
+
delegate :test_message, to: :test_framework
|
|
11
|
+
|
|
12
|
+
def initialize(options)
|
|
13
|
+
@test_framework = options.fetch(:test_framework)
|
|
14
|
+
@library = options.fetch(:library)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def notify
|
|
18
|
+
send(library).title(RUBY_VERSION).message(test_message).image(image).notify
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def image
|
|
22
|
+
return success_image if test_framework.success?
|
|
23
|
+
|
|
24
|
+
if test_framework.failure?
|
|
25
|
+
failure_image
|
|
26
|
+
else
|
|
27
|
+
pending_image
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def success_image
|
|
32
|
+
Core::Base.success_image || find_image(:success)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def failure_image
|
|
36
|
+
Core::Base.failure_image || find_image(:failure)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def pending_image
|
|
40
|
+
Core::Base.pending_image || find_image(:pending)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def find_image(image_type)
|
|
44
|
+
Dir.glob(File.join(images_dir, "#{image_type.to_s}*")).first
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def images_dir
|
|
48
|
+
mode = Core::Base.mode
|
|
49
|
+
|
|
50
|
+
case mode
|
|
51
|
+
when Symbol
|
|
52
|
+
File.join(IMAGES, mode.to_s)
|
|
53
|
+
when String
|
|
54
|
+
File.expand_path(File.join(mode))
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Core
|
|
3
|
+
class Options
|
|
4
|
+
attr_accessor :arguments, :options_parser, :strategy, :bundler, :verbose
|
|
5
|
+
attr_accessor :rubies, :specific_options, :test_framework, :framework, :infinity_and_beyond
|
|
6
|
+
attr_accessor :notifications, :mode, :just_watch, :focus
|
|
7
|
+
|
|
8
|
+
def initialize(*arguments)
|
|
9
|
+
@arguments = arguments.flatten.clone
|
|
10
|
+
@options_parser = new_options_parser
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def new_options_parser
|
|
14
|
+
OptionParser.new do |option|
|
|
15
|
+
%w(
|
|
16
|
+
ruby_strategy
|
|
17
|
+
ruby_versions
|
|
18
|
+
options_to_added_in_the_command
|
|
19
|
+
test_framework_to_be_run
|
|
20
|
+
app_framework
|
|
21
|
+
notifications_library
|
|
22
|
+
image_mode
|
|
23
|
+
infinity_and_beyond_option
|
|
24
|
+
just_watch_option
|
|
25
|
+
focus_option
|
|
26
|
+
verbose_mode
|
|
27
|
+
skip_bundler
|
|
28
|
+
).each do |option_to_parse|
|
|
29
|
+
send(option_to_parse, option)
|
|
30
|
+
end
|
|
31
|
+
banner(option)
|
|
32
|
+
help(option)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def parse!
|
|
37
|
+
@options_parser.parse!(@arguments)
|
|
38
|
+
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def ruby_strategy(option)
|
|
43
|
+
option.on('--ruby strategy', 'Ruby Manager. Ex.: auto_discover, rvm, rbenv, ruby_default') do |strategy|
|
|
44
|
+
@strategy = strategy.to_sym
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def ruby_versions(option)
|
|
49
|
+
option.on('--rubies=rubies', 'Specify Ruby version(s) to test against') do |versions|
|
|
50
|
+
@rubies = versions.split(',')
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def options_to_added_in_the_command(option)
|
|
55
|
+
option.on('--options=options', 'Pass the options to be added. Ex. -Ilib-Itest-Iapp') do |options|
|
|
56
|
+
@specific_options = options.split('-').join(' -').strip
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_framework_to_be_run(option)
|
|
61
|
+
option.on('--test library', 'Test Framework to be run. Ex.: auto_discover, rspec, test_unit.') do |library|
|
|
62
|
+
@test_framework = library.to_sym
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def app_framework(option)
|
|
67
|
+
option.on('--framework library', 'Application Framework to be run and added the patterns to search changed files. Ex.: auto_discover, rails, rubygems, padrino.') do |library|
|
|
68
|
+
@framework = library.to_sym
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def notifications_library(option)
|
|
73
|
+
option.on('--notifications library', 'Notification library to use. Ex.: auto_discover, osascript, terminal_notifier, notify_send, dunstify.') do |library|
|
|
74
|
+
@notifications = library.to_sym
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def image_mode(option)
|
|
79
|
+
option.on('--mode theme', 'Image theme for notifications. Ex.: simpson, faces, fuuu, hands, mario_bros, rails, rubies, street_fighter, toy_story.') do |theme|
|
|
80
|
+
@mode = theme.to_sym
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def infinity_and_beyond_option(option)
|
|
85
|
+
option.on('-n', '--no-infinity-and-beyond', 'Run tests and exit. Useful in a Continuous Integration environment.') do
|
|
86
|
+
@infinity_and_beyond = false
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def just_watch_option(option)
|
|
91
|
+
option.on('-j', '--just-watch', 'Skip initial test run and only watch for file changes. Useful for large applications.') do
|
|
92
|
+
@just_watch = true
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def focus_option(option)
|
|
97
|
+
option.on('-f', '--focus [FILE]', 'Focus on specific tests. Use "failures" for failed tests, or provide a file path.') do |file|
|
|
98
|
+
@focus = file == 'failures' ? :failures : file
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def verbose_mode(option)
|
|
103
|
+
option.on('--no-verbose', "Don't print commands before executing them") do
|
|
104
|
+
@verbose = false
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def skip_bundler(option)
|
|
109
|
+
option.on('--no-bundler', "Bypass Infinity Test's Bundler support") do
|
|
110
|
+
@bundler = false
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def banner(option)
|
|
115
|
+
option.banner = [ "Usage: infinity_test [options]", "Run tests"].join("\n")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def help(option)
|
|
119
|
+
option.on_tail("--help", "You're looking at it.") do
|
|
120
|
+
print option.help
|
|
121
|
+
exit
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def verbose?
|
|
126
|
+
@verbose
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def bundler?
|
|
130
|
+
@bundler
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Core
|
|
3
|
+
class Runner
|
|
4
|
+
attr_accessor :options
|
|
5
|
+
|
|
6
|
+
def initialize(*arguments)
|
|
7
|
+
@options = Options.new(arguments).parse!
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def start
|
|
11
|
+
Core::LoadConfiguration.new.load!
|
|
12
|
+
Core::Base.merge!(options)
|
|
13
|
+
Core::AutoDiscover.new(Core::Base).discover_libraries
|
|
14
|
+
Core::Base.start_continuous_test_server
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Framework
|
|
3
|
+
class Base
|
|
4
|
+
attr_reader :continuous_test_server, :hike
|
|
5
|
+
delegate :observer, :test_framework, :extension, to: :continuous_test_server
|
|
6
|
+
delegate :watch, :watch_dir, to: :observer
|
|
7
|
+
|
|
8
|
+
def initialize(continuous_test_server)
|
|
9
|
+
@continuous_test_server = continuous_test_server
|
|
10
|
+
@hike = Hike::Trail.new(Dir.pwd)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def heuristics!
|
|
14
|
+
hike.append_extension(extension)
|
|
15
|
+
hike.append_path(test_framework.test_dir)
|
|
16
|
+
heuristics
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# This method is called for the InfinityTest before starting the observer
|
|
20
|
+
#
|
|
21
|
+
def heuristics
|
|
22
|
+
raise NotImplementedError, "not implemented in #{self}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Put all the requires to autodiscover use your framework instead of others.
|
|
26
|
+
#
|
|
27
|
+
def self.run?
|
|
28
|
+
raise NotImplementedError, "not implemented in #{self}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Run all the strategy again.
|
|
32
|
+
#
|
|
33
|
+
def run_all
|
|
34
|
+
continuous_test_server.run_strategy
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Run the same changed file.
|
|
38
|
+
# E.g: the user saves the test file, runs the test file.
|
|
39
|
+
#
|
|
40
|
+
# @param changed_file [<InfinityTest::Core::ChangedFile>]
|
|
41
|
+
#
|
|
42
|
+
def run_file(changed_file)
|
|
43
|
+
continuous_test_server.rerun_strategy(changed_file.name)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Run test based on the changed file.
|
|
47
|
+
#
|
|
48
|
+
# @param changed_file [<InfinityTest::Core::ChangedFile>]
|
|
49
|
+
#
|
|
50
|
+
def run_test(changed_file)
|
|
51
|
+
file_name = "#{changed_file.path}_#{test_framework.test_dir}.#{extension}"
|
|
52
|
+
file = hike.find(file_name)
|
|
53
|
+
continuous_test_server.rerun_strategy(file) if file.present?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Auto-discover and watch all directories under app/ that contain Ruby files.
|
|
57
|
+
# Maps app/components to spec/components, app/wizards to spec/wizards, etc.
|
|
58
|
+
# Skips directories without .rb files (e.g., app/views, app/assets).
|
|
59
|
+
#
|
|
60
|
+
def watch_app_dirs
|
|
61
|
+
return unless File.directory?('app')
|
|
62
|
+
|
|
63
|
+
Dir.glob('app/*').each do |app_dir|
|
|
64
|
+
next unless File.directory?(app_dir)
|
|
65
|
+
next unless Dir.glob("#{app_dir}/**/*.rb").any?
|
|
66
|
+
|
|
67
|
+
watch_dir(app_dir) { |file| run_test_in_subdir(file, app_dir) }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Run test preserving the subdirectory structure.
|
|
72
|
+
# E.g: app/components/wizard.rb -> spec/components/wizard_spec.rb
|
|
73
|
+
#
|
|
74
|
+
# @param changed_file [<InfinityTest::Core::ChangedFile>]
|
|
75
|
+
# @param app_dir [String] The app directory (e.g., 'app/components')
|
|
76
|
+
#
|
|
77
|
+
def run_test_in_subdir(changed_file, app_dir)
|
|
78
|
+
subdir = File.basename(app_dir)
|
|
79
|
+
test_file = File.join(test_framework.test_dir, subdir, "#{changed_file.path}_#{test_framework.test_dir}.#{extension}")
|
|
80
|
+
|
|
81
|
+
if File.exist?(test_file)
|
|
82
|
+
continuous_test_server.rerun_strategy(test_file)
|
|
83
|
+
else
|
|
84
|
+
# Fallback: try finding with hike in test_dir/subdir
|
|
85
|
+
hike.prepend_path(File.join(test_framework.test_dir, subdir))
|
|
86
|
+
file_name = "#{changed_file.path}_#{test_framework.test_dir}.#{extension}"
|
|
87
|
+
file = hike.find(file_name)
|
|
88
|
+
continuous_test_server.rerun_strategy(file) if file.present?
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -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
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module InfinityTest
|
|
2
|
+
module Framework
|
|
3
|
+
class Padrino < 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
|
+
# ==== Returns
|
|
22
|
+
# TrueClass: Find the config/apps.rb in the user current dir
|
|
23
|
+
# FalseClass: Don't Find the config/apps.rb in the user current dir
|
|
24
|
+
#
|
|
25
|
+
def self.run?
|
|
26
|
+
File.exist?(File.expand_path('./config/apps.rb'))
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|