tconsole-rails4 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TConsole
3
+ class MinitestServer < Server
4
+
5
+ # Loads the files that match globs and then executes tests against them. Limit tests
6
+ # with class names, method names, and test ids using match_patterns.
7
+ def run_tests(globs, match_patterns, message = "Running tests...")
8
+ time = Benchmark.realtime do
9
+ reporter.info(message)
10
+ reporter.info
11
+
12
+ paths = []
13
+ globs.each do |glob|
14
+ paths.concat(Dir.glob(glob))
15
+ end
16
+
17
+ if paths.length == 0
18
+ reporter.warn("No test files match your requested test set: #{globs.join(",")}.")
19
+ reporter.warn("Skipping execution.")
20
+ return nil
21
+ end
22
+
23
+ self.last_result = run_in_fork do
24
+
25
+ paths.each do |path|
26
+ reporter.trace("Requested path `#{path}` doesn't exist.") unless File.exist?(path)
27
+ require File.expand_path(path)
28
+ end
29
+
30
+ reporter.trace("Running before_test_run callback")
31
+ config.before_test_run!
32
+ reporter.trace("Completed before_test_run callback")
33
+
34
+ result = nil
35
+ if defined?(::Minitest)
36
+ reporter.trace("Detected minitest.")
37
+ require File.join(File.dirname(__FILE__), "minitest_handler")
38
+ require File.join(File.dirname(__FILE__), "minitest_reporter")
39
+
40
+ reporter.trace("Running tests.")
41
+ runner = MiniTestHandler.new(config)
42
+
43
+ # TODO надо починить Ctrl+C
44
+ # Handle trapping interrupts
45
+ trap("SIGINT") do
46
+ reporter.warn
47
+ reporter.warn("Trapped interrupt. Halting tests.")
48
+
49
+ runner.interrupted = true
50
+ end
51
+
52
+
53
+ result, res_reporter = runner.match_and_run(match_patterns, config)
54
+
55
+ res_reporter.report
56
+ # Make sure minitest doesn't run automatically
57
+ MiniTestHandler.patch_minitest
58
+
59
+ reporter.trace("Finished running tests.")
60
+
61
+ if runner.interrupted
62
+ reporter.error("Test run was interrupted.")
63
+ end
64
+
65
+ elsif defined?(::Test::Unit)
66
+ reporter.error("Sorry, but #{config.app} doesn't support Test::Unit")
67
+ end
68
+
69
+ result
70
+ end
71
+
72
+ if self.last_result == nil
73
+ # Just in case anything crazy goes down with marshalling
74
+ self.last_result = TConsole::TestResult.new
75
+ end
76
+
77
+ config.cache_test_ids(self.last_result)
78
+
79
+ true
80
+ end
81
+
82
+ reporter.info
83
+ reporter.info("Tests ran in #{"%0.6f" % time}s. Finished at #{Time.now.strftime('%Y-%m-%d %l:%M:%S %p')}.")
84
+ reporter.info
85
+ end
86
+
87
+ # Preloads our autocomplete cache
88
+ def preload_test_ids
89
+ result = run_in_fork do
90
+ paths = []
91
+ config.file_sets["all"].each do |glob|
92
+ paths.concat(Dir.glob(glob))
93
+ end
94
+
95
+ paths.each { |path| require File.expand_path(path) }
96
+
97
+ require File.join(File.dirname(__FILE__), "minitest_handler")
98
+ MiniTestHandler.preload_elements
99
+ end
100
+
101
+ config.cache_test_ids(result) unless result.nil?
102
+ end
103
+
104
+ # Runs all tests against the match patterns given
105
+ def run_all_tests(match_patterns = nil)
106
+ run_tests(config.file_sets["all"], match_patterns)
107
+ end
108
+
109
+ # Runs a file set out of the config
110
+ def run_file_set(set)
111
+ run_tests(config.file_sets[set], nil)
112
+ end
113
+
114
+ def run_failed
115
+ if last_result.failures.empty?
116
+ reporter.info("No tests failed in your last run, or you haven't run any tests in this session yet.")
117
+ reporter.info
118
+ else
119
+ run_tests(config.file_sets["all"], last_result.failures)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,113 @@
1
+ # Manages all output for TConsole
2
+ module TConsole
3
+ class Reporter
4
+ attr_accessor :config
5
+
6
+ def initialize(config)
7
+ self.config = config
8
+ end
9
+
10
+ # Public: Ouptuts an informative message.
11
+ def info(message = "")
12
+ puts message
13
+ end
14
+
15
+ # Public: Outputs a positive informative message.
16
+ # Colors it green if the console supports it.
17
+ def exclaim(message = "")
18
+ puts ::Term::ANSIColor.green(message)
19
+ end
20
+
21
+ # Public: Outputs a warning message.
22
+ def warn(message = "")
23
+ puts ::Term::ANSIColor.yellow(message)
24
+ end
25
+
26
+ # Public: Outputs an error message.
27
+ def error(message = "")
28
+ puts ::Term::ANSIColor.red(message)
29
+ end
30
+
31
+
32
+ # Public: Outputs a trace message, when needed.
33
+ def trace(message = "")
34
+ puts "[tconsole trace] #{message}" if config.trace?
35
+ end
36
+
37
+ # Public: Prints a backtrace out.
38
+ def trace_backtrace(exception)
39
+ trace("===========")
40
+ trace(exception.backtrace.join("\n"))
41
+ trace("===========")
42
+ end
43
+
44
+ # Public: Outputs a timing for the timings command, using the proper
45
+ # color logic
46
+ def timing(timing, test_id)
47
+ output = "#{"%0.6f" % timing[:time]}s #{timing[:name]}"
48
+ if timing[:time] > 1
49
+ print ::Term::ANSIColor.red, output, ::Term::ANSIColor.reset
50
+ else
51
+ print ::Term::ANSIColor.green, output, ::Term::ANSIColor.reset
52
+ end
53
+
54
+ print ::Term::ANSIColor.magenta, " #{last_result}", ::Term::ANSIColor.reset, "\n"
55
+ end
56
+
57
+ # Public: Prints a list of available commands
58
+ def help_message
59
+ puts
60
+ puts "Available commands:"
61
+ puts
62
+ puts "reload # Reload your Rails environment"
63
+ puts "set [variable] [value] # Sets a runtime variable (see below for details)"
64
+ puts "exit # Exit the console"
65
+ puts "!failed # Runs the last set of failing tests"
66
+ puts "!timings [limit] # Lists the timings for the last test run, sorted."
67
+ puts "[filename] [test_pattern] # Run the tests contained in the given file"
68
+ puts ".[command] # Executes the given command in a subshell"
69
+ puts
70
+ puts "Running file sets"
71
+ puts
72
+ puts "File sets are sets of files that are typically run together. For example,"
73
+ puts "in Rails projects it's common to run `rake test:units` to run all of the"
74
+ puts "tests under the units directory."
75
+ puts
76
+ puts "Available file sets:"
77
+
78
+ config.file_sets.each do |set, paths|
79
+ puts set
80
+ end
81
+
82
+ puts
83
+ puts "Working with test patterns:"
84
+ puts
85
+ puts "All of the test execution commands include an optional test_pattern argument. A"
86
+ puts "test pattern can be given to filter the executed tests to only those tests whose"
87
+ puts "name matches the pattern given. This is especially useful when rerunning a failing"
88
+ puts "test."
89
+ puts
90
+ puts "Runtime Variables"
91
+ puts
92
+ puts "You can set runtime variables with the set command. This helps out with changing"
93
+ puts "features that you may want to change at runtime. At present, the following"
94
+ puts "runtime variables are available:"
95
+ puts
96
+ puts "fast # Turns on fail fast mode. Values: on, off"
97
+ puts
98
+
99
+ end
100
+
101
+ # Public: Outputs the tconsole welcome message
102
+ def welcome_message
103
+ info
104
+ info("Welcome to #{config.app} (v#{TConsole::VERSION}). Type 'help' for help or 'exit' to quit.")
105
+ end
106
+
107
+ # Public: Outputs the tconsole exit message
108
+ def exit_message
109
+ info
110
+ info("Exiting. Bye!")
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,108 @@
1
+ module TConsole
2
+ class RSpecServer < Server
3
+
4
+ # Loads the files that match globs and then executes tests against them. Limit tests
5
+ # with class names, method names, and test ids using match_patterns.
6
+ def run_tests(globs, match_patterns, message = "Running tests...")
7
+ time = Benchmark.realtime do
8
+ reporter.info(message)
9
+ reporter.info
10
+
11
+ paths = []
12
+ globs.each do |glob|
13
+ paths.concat(Dir.glob(glob))
14
+ end
15
+
16
+ if paths.length == 0
17
+ reporter.warn("No test files match your requested test set: #{globs.join(",")}.")
18
+ reporter.warn("Skipping execution.")
19
+ return nil
20
+ end
21
+
22
+ self.last_result = run_in_fork do
23
+
24
+ # Make sure rspec is loaded up
25
+ require 'rspec'
26
+
27
+ paths.each do |path|
28
+ reporter.trace("Requested path `#{path}` doesn't exist.") unless File.exist?(path)
29
+ require File.expand_path(path)
30
+ end
31
+
32
+ reporter.trace("Running before_test_run callback")
33
+ config.before_test_run!
34
+ reporter.trace("Completed before_test_run callback")
35
+
36
+ result = nil
37
+ if defined?(::RSpec)
38
+ reporter.trace("Detected rspec.")
39
+
40
+ reporter.trace("Running tests.")
41
+
42
+ # Handle trapping interrupts
43
+ trap("SIGINT") do
44
+ reporter.warn
45
+ reporter.warn("Trapped interrupt. Halting tests.")
46
+ end
47
+
48
+ # Actually run the tests!
49
+ configuration = RSpec::configuration
50
+ world = RSpec::world
51
+ options = RSpec::Core::ConfigurationOptions.new([])
52
+ options.parse_options
53
+
54
+ configuration.error_stream = STDERR
55
+ configuration.output_stream = STDOUT
56
+
57
+ options.configure(configuration)
58
+
59
+ configuration.files_to_run = paths
60
+
61
+ configuration.reporter.report(world.example_count, configuration.randomize? ? configuration.seed : nil) do |reporter|
62
+ begin
63
+ configuration.run_hook(:before, :suite)
64
+ world.example_groups.ordered.map {|g| g.run(reporter)}.all? ? 0 : configuration.failure_exit_code
65
+ ensure
66
+ configuration.run_hook(:after, :suite)
67
+ end
68
+ end
69
+
70
+ # Patch RSpec to disable autorun
71
+ ::RSpec::Core::Runner.class_eval do
72
+ def self.run(args = [], err=$stderr, out=$stdout)
73
+ # do nothing
74
+ end
75
+ end
76
+
77
+ reporter.trace("Finished running tests.")
78
+ end
79
+
80
+ nil
81
+ end
82
+
83
+ if self.last_result == nil
84
+ # Just in case anything crazy goes down with marshalling
85
+ self.last_result = TConsole::TestResult.new
86
+ end
87
+
88
+ config.cache_test_ids(self.last_result)
89
+
90
+ true
91
+ end
92
+
93
+ reporter.info
94
+ reporter.info("Tests ran in #{"%0.6f" % time}s. Finished at #{Time.now.strftime('%Y-%m-%d %l:%M:%S %p')}.")
95
+ reporter.info
96
+ end
97
+
98
+ # Runs all tests against the match patterns given
99
+ def run_all_tests(match_patterns = nil)
100
+ run_tests(config.file_sets["all"], match_patterns)
101
+ end
102
+
103
+ # Runs a file set out of the config
104
+ def run_file_set(set)
105
+ run_tests(config.file_sets[set], nil)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,139 @@
1
+ module TConsole
2
+ class Runner
3
+
4
+ attr_accessor :mode, :config, :reporter, :console, :stty_save
5
+
6
+ # Public: Sets up the new runner's config.
7
+ def initialize(mode, argv = [])
8
+ self.mode = mode
9
+
10
+ # try to load the default configs
11
+ Config.load_config(File.join(Dir.home, ".#{Config.app(mode)}"))
12
+ Config.load_config(File.join(Dir.pwd, ".#{Config.app(mode)}"))
13
+ self.config = Config.configure(mode, argv)
14
+ self.reporter = Reporter.new(config)
15
+ end
16
+
17
+ # Spawns a new environment. Looks at the results of the environment to determine
18
+ # whether to stop or keep running
19
+ def run
20
+ prepare_process
21
+ reporter.welcome_message
22
+ exit(1) if print_config_errors
23
+
24
+ # Set up our console input handling and history
25
+ console = Console.new(config, reporter)
26
+
27
+ # Start the server
28
+ while console_run_loop(console)
29
+ # just need to run the loop
30
+ end
31
+
32
+ console.store_history
33
+
34
+ cleanup_process
35
+ end
36
+
37
+ # Internal: Set up the process and console.
38
+ def prepare_process
39
+ self.stty_save = `stty -g`.chomp
40
+
41
+ trap("SIGINT", "IGNORE")
42
+ trap("SIGTSTP", "IGNORE")
43
+ end
44
+
45
+ # Internal: Cleans up the process at the end of execution.
46
+ def cleanup_process
47
+ reporter.exit_message
48
+ system("stty", self.stty_save);
49
+ end
50
+
51
+ # Internal: Prints config errors, if there are any.
52
+ #
53
+ # Returns true if there were errors, false otherwise.
54
+ def print_config_errors
55
+ config_errors = @config.validation_errors
56
+ if config_errors.length > 0
57
+ reporter.error
58
+ reporter.error(config_errors.first)
59
+ true
60
+ else
61
+ false
62
+ end
63
+ end
64
+
65
+ # Internal: Environment reload run loop.
66
+ #
67
+ # This run loop handles spawning a new tconsole environment - it's basically
68
+ # just there to handle reloads. Also calls out to the input loop for the
69
+ # console.
70
+ #
71
+ # Returns false if tconsole needs to stop, true otherwise.
72
+ def console_run_loop(console)
73
+ pipe_server = ChattyProc::PipeServer.new
74
+
75
+ reporter.trace("Forking test server.")
76
+ server_pid = fork do
77
+ server_run_loop(pipe_server)
78
+ end
79
+
80
+ pipe_server.caller!
81
+ unless load_environment(pipe_server)
82
+ pipe_server.write({:action => "exit"})
83
+ return false
84
+ end
85
+
86
+ continue = console.read_and_execute(pipe_server)
87
+ reporter.trace("Console read loop returned - continue: #{continue}")
88
+
89
+ Process.waitall
90
+
91
+ continue
92
+ end
93
+
94
+ # Internal: Asks the server to load the environment.
95
+ #
96
+ # Returns true if the environment was loaded, or false otherwise.
97
+ def load_environment(pipe_server)
98
+ reporter.trace("Attempting to load environment.")
99
+ pipe_server.write({:action => "load_environment"})
100
+
101
+ if pipe_server.read
102
+ reporter.trace("Environment loaded successfully.")
103
+ true
104
+ else
105
+ reporter.error("Couldn't load the test environment. Exiting.")
106
+ false
107
+ end
108
+ end
109
+
110
+ # Internal: Run loop for the server.
111
+ def server_run_loop(pipe_server)
112
+ pipe_server.callee!
113
+
114
+ if mode == :minitest
115
+ server = MinitestServer.new(config, reporter)
116
+ elsif mode == :rspec
117
+ server = RSpecServer.new(config, reporter)
118
+ else
119
+ reporter.error
120
+ reporter.error("The given test mode isn't supported.")
121
+ reporter.error
122
+ exit
123
+ end
124
+
125
+ while message = pipe_server.read
126
+ reporter.trace("Server Received Message: #{message[:action]}")
127
+ begin
128
+ result = server.handle(message)
129
+ pipe_server.write(result)
130
+ rescue => e
131
+ reporter.error
132
+ reporter.error("An error occured: #{e.message}")
133
+ reporter.trace_backtrace(e)
134
+ pipe_server.write(nil)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end