tconsole 1.2.7 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .rvmrc
6
+ .rspec
data/Gemfile CHANGED
@@ -4,4 +4,4 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "rake"
7
- gem "nutrasuite"
7
+ gem "rspec"
data/Rakefile CHANGED
@@ -1,10 +1 @@
1
1
  require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- task :default => [:test]
5
-
6
- Rake::TestTask.new do |t|
7
- t.libs << "test"
8
- t.test_files = FileList['test/unit/**/*_test.rb']
9
- t.verbose = true
10
- end
@@ -2,4 +2,4 @@
2
2
 
3
3
  require File.join(File.dirname(__FILE__), "..", "lib", "tconsole")
4
4
 
5
- TConsole::Runner.run(ARGV)
5
+ TConsole::Runner.new(ARGV).run
@@ -1,104 +1,19 @@
1
1
  require "tconsole/version"
2
- require "tconsole/config"
3
- require "tconsole/console"
4
- require "tconsole/server"
5
- require "tconsole/pipe_server"
6
- require "tconsole/test_result"
7
- require "tconsole/util"
8
2
 
3
+ require "chattyproc"
9
4
  require "optparse"
10
5
  require "readline"
11
6
  require "benchmark"
12
- require "drb/drb"
13
7
  require "term/ansicolor"
14
8
  require "shellwords"
15
9
 
16
- module TConsole
17
- class Runner
18
-
19
- # Spawns a new environment. Looks at the results of the environment to determine whether to stop or
20
- # keep running
21
- def self.run(argv)
22
- stty_save = `stty -g`.chomp
23
-
24
- running = true
25
- trap("SIGINT", "IGNORE")
26
- trap("SIGTSTP", "IGNORE")
27
-
28
- # A little welcome
29
- puts
30
- puts "Welcome to tconsole (v#{TConsole::VERSION}). Type 'help' for help or 'exit' to quit."
31
-
32
- # set up the config
33
- Config.load_config(File.join(Dir.home, ".tconsole"))
34
- Config.load_config(File.join(Dir.pwd, ".tconsole"))
35
- config = Config.configure(argv)
36
-
37
- config_errors = config.validation_errors
38
- if config_errors.length > 0
39
- puts
40
- puts config_errors.first
41
- exit(1)
42
- end
43
-
44
- # Set up our console input handling and history
45
- console = Console.new(config)
46
-
47
- # Start the server
48
- while running
49
- # ignore ctrl-c during load, since things can get kind of messy if we don't
50
-
51
- pipe_server = PipeServer.new
52
-
53
- config.trace("Forking test server.")
54
- server_pid = fork do
55
- pipe_server.callee!
56
-
57
- server = Server.new(config)
58
-
59
- while message = pipe_server.read
60
- config.trace("Server Received Message: #{message[:action]}")
61
- begin
62
- result = server.handle(message)
63
- pipe_server.write(result)
64
- rescue => e
65
- puts
66
- puts "An error occured: #{e.message}"
67
- config.trace("===========")
68
- config.trace(e.backtrace.join("\n"))
69
- config.trace("===========")
70
- pipe_server.write(nil)
71
- end
72
- end
73
- end
74
-
75
- pipe_server.caller!
76
-
77
- wait_until = Time.now + 10
78
-
79
- config.trace("Attempting to load environment.")
80
- pipe_server.write({:action => "load_environment"})
81
-
82
- unless pipe_server.read
83
- puts "Couldn't load the test environment. Exiting."
84
- exit(1)
85
- end
86
- config.trace("Environment loaded successfully.")
87
-
88
- console.pipe_server = pipe_server
89
- running = console.read_and_execute
90
- console.pipe_server = nil
91
-
92
- Process.waitall
93
- end
94
-
95
- console.store_history
10
+ require "tconsole/config"
11
+ require "tconsole/reporter"
12
+ require "tconsole/console"
13
+ require "tconsole/server"
14
+ require "tconsole/test_result"
15
+ require "tconsole/util"
16
+ require "tconsole/runner"
96
17
 
97
- puts
98
- puts "Exiting. Bye!"
99
- system("stty", stty_save);
100
- end
101
- end
102
- end
103
18
 
104
19
 
@@ -37,9 +37,9 @@ module TConsole
37
37
  # Only runs the command passed on the command line, and then exits
38
38
  attr_accessor :once
39
39
 
40
- def initialize(argv)
40
+ def initialize(argv = [])
41
41
  self.trace_execution = false
42
- self.test_dir = "./test"
42
+ self.test_dir = "test"
43
43
  self.include_paths = ["./test", "./lib"]
44
44
  self.preload_paths = []
45
45
  self.fail_fast = false
@@ -172,7 +172,6 @@ module TConsole
172
172
  "integration" => ["#{config.test_dir}/integration/**/*_test.rb"]
173
173
  }
174
174
 
175
-
176
175
  config.before_load do
177
176
  ENV["RAILS_ENV"] ||= "test"
178
177
  end
@@ -205,10 +204,5 @@ module TConsole
205
204
  def self.is_rails?
206
205
  @rails ||= !!File.exist?("./config/application.rb")
207
206
  end
208
-
209
- # Outputs trace message if our config allows it
210
- def trace(message)
211
- puts "[tconsole trace] #{message}" if trace?
212
- end
213
207
  end
214
208
  end
@@ -2,16 +2,15 @@ module TConsole
2
2
  class Console
3
3
  KNOWN_COMMANDS = ["exit", "reload", "help", "info", "!failed", "!timings", "set"]
4
4
 
5
- attr_accessor :pipe_server
5
+ attr_accessor :config, :reporter
6
6
 
7
- def initialize(config)
8
- @config = config
7
+ def initialize(config, reporter)
8
+ self.config = config
9
+ self.reporter = reporter
9
10
  read_history
10
-
11
- define_autocomplete
12
11
  end
13
12
 
14
- def define_autocomplete
13
+ def define_autocomplete(pipe_server)
15
14
  Readline.completion_append_character = ""
16
15
 
17
16
  # Proc for helping us figure out autocompletes
@@ -21,7 +20,7 @@ module TConsole
21
20
 
22
21
  known_elements = []
23
22
  unless pipe_server.nil?
24
- known_elements = send_message(:autocomplete, str)
23
+ known_elements = send_message(pipe_server, :autocomplete, str)
25
24
  end
26
25
 
27
26
  known_commands.concat(known_elements)
@@ -29,12 +28,7 @@ module TConsole
29
28
  end
30
29
 
31
30
  # Returns true if the app should keep running, false otherwise
32
- def read_and_execute
33
- if pipe_server.nil?
34
- puts "No connection to test environment. Exiting."
35
- return false
36
- end
37
-
31
+ def read_and_execute(pipe_server)
38
32
  prompt = "tconsole> "
39
33
 
40
34
  trap("SIGTSTP", "SYSTEM_DEFAULT")
@@ -43,7 +37,7 @@ module TConsole
43
37
  end
44
38
 
45
39
  # Run any commands that have been passed
46
- result = process_command(@config.run_command)
40
+ result = process_command(pipe_server, @config.run_command)
47
41
  @config.run_command = ""
48
42
  if result == :exit || @config.once
49
43
  return false
@@ -51,10 +45,12 @@ module TConsole
51
45
  return true
52
46
  end
53
47
 
48
+ define_autocomplete(pipe_server)
49
+
54
50
  # The command entry loop
55
51
  while command = Readline.readline(prompt, false)
56
52
  command.strip!
57
- result = process_command(command)
53
+ result = process_command(pipe_server, command)
58
54
 
59
55
  if result == :exit
60
56
  return false
@@ -69,8 +65,9 @@ module TConsole
69
65
 
70
66
  # Public: Process a command however it needs to be handled.
71
67
  #
68
+ # pipe_server - The pipe server we're working with
72
69
  # command - The command we need to parse and handle
73
- def process_command(command)
70
+ def process_command(pipe_server, command)
74
71
  args = Shellwords.shellwords(command)
75
72
 
76
73
  # save the command unless we're exiting or repeating the last command
@@ -81,80 +78,49 @@ module TConsole
81
78
  if command == ""
82
79
  # do nothing
83
80
  elsif args[0] == "exit"
84
- send_message(:stop)
85
- self.pipe_server = nil
81
+ send_message(pipe_server, :stop)
86
82
  return :exit
87
83
  elsif args[0] == "reload"
88
- send_message(:stop)
84
+ send_message(pipe_server, :stop)
89
85
  return :reload
90
86
  elsif args[0] == "help"
91
- print_help
87
+ reporter.help_message
92
88
  elsif args[0] == "!failed"
93
- send_message(:run_failed)
89
+ send_message(pipe_server, :run_failed)
94
90
  elsif args[0] == "!timings"
95
- send_message(:show_performance, args[1])
91
+ send_message(pipe_server, :show_performance, args[1])
96
92
  elsif args[0] == "info"
97
- send_message(:run_info)
93
+ send_message(pipe_server, :run_info)
98
94
  elsif args[0] == "set"
99
- send_message(:set, args[1], args[2])
95
+ send_message(pipe_server, :set, args[1], args[2])
100
96
  elsif args[0].start_with?(".")
101
- send_message(:shell, command[1, command.length - 1])
97
+ shell_command(command[1, command.length - 1])
102
98
  elsif @config.file_sets.has_key?(args[0])
103
- send_message(:run_file_set, args[0])
99
+ send_message(pipe_server, :run_file_set, args[0])
104
100
  else
105
- send_message(:run_all_tests, args)
101
+ send_message(pipe_server, :run_all_tests, args)
106
102
  end
107
103
 
108
104
  nil
109
105
  end
110
106
 
111
- def send_message(message, *args)
107
+ def send_message(pipe_server, message, *args)
112
108
  pipe_server.write({:action => message.to_sym, :args => args})
113
109
  pipe_server.read
114
110
  end
115
111
 
116
- # Prints a list of available commands
117
- def print_help
118
- puts
119
- puts "Available commands:"
120
- puts
121
- puts "reload # Reload your Rails environment"
122
- puts "set [variable] [value] # Sets a runtime variable (see below for details)"
123
- puts "exit # Exit the console"
124
- puts "!failed # Runs the last set of failing tests"
125
- puts "!timings [limit] # Lists the timings for the last test run, sorted."
126
- puts "[filename] [test_pattern] # Run the tests contained in the given file"
127
- puts ".[command] # Executes the given command in a subshell"
128
- puts
129
- puts "Running file sets"
130
- puts
131
- puts "File sets are sets of files that are typically run together. For example,"
132
- puts "in Rails projects it's common to run `rake test:units` to run all of the"
133
- puts "tests under the units directory."
134
- puts
135
- puts "Available file sets:"
136
-
137
- @config.file_sets.each do |set, paths|
138
- puts set
139
- end
112
+ # Internal: Runs a shell command on the console and outputs the results.
113
+ def shell_command(command)
114
+ system(command)
140
115
 
141
- puts
142
- puts "Working with test patterns:"
143
- puts
144
- puts "All of the test execution commands include an optional test_pattern argument. A"
145
- puts "test pattern can be given to filter the executed tests to only those tests whose"
146
- puts "name matches the pattern given. This is especially useful when rerunning a failing"
147
- puts "test."
148
- puts
149
- puts "Runtime Variables"
150
- puts
151
- puts "You can set runtime variables with the set command. This helps out with changing"
152
- puts "features of TConsole that you may want to change at runtime. At present, the"
153
- puts "following runtime variables are available:"
154
- puts
155
- puts "fast # Turns on fail fast mode. Values: on, off"
156
- puts
116
+ result = $?
157
117
 
118
+ reporter.info
119
+ if result.exitstatus == 0
120
+ reporter.exclaim("Command exited with status code: 0")
121
+ else
122
+ reporter.error("Command exited with status code: #{result.exitstatus}")
123
+ end
158
124
  end
159
125
 
160
126
  def history_file
@@ -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 of TConsole that you may want to change at runtime. At present, the"
94
+ puts "following 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 tconsole (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,127 @@
1
+ module TConsole
2
+ class Runner
3
+
4
+ attr_accessor :config, :reporter, :console, :stty_save
5
+
6
+ # Public: Sets up the new runner's config.
7
+ def initialize(argv = [])
8
+ # try to load the default configs
9
+ Config.load_config(File.join(Dir.home, ".tconsole"))
10
+ Config.load_config(File.join(Dir.pwd, ".tconsole"))
11
+ self.config = Config.configure(argv)
12
+ self.reporter = Reporter.new(config)
13
+ end
14
+
15
+ # Spawns a new environment. Looks at the results of the environment to determine whether to stop or
16
+ # keep running
17
+ def run
18
+ prepare_process
19
+ reporter.welcome_message
20
+ exit(1) if print_config_errors
21
+
22
+ # Set up our console input handling and history
23
+ console = Console.new(config, reporter)
24
+
25
+ # Start the server
26
+ while console_run_loop(console)
27
+ # just need to run the loop
28
+ end
29
+
30
+ console.store_history
31
+
32
+ cleanup_process
33
+ end
34
+
35
+ # Internal: Set up the process and console.
36
+ def prepare_process
37
+ self.stty_save = `stty -g`.chomp
38
+
39
+ trap("SIGINT", "IGNORE")
40
+ trap("SIGTSTP", "IGNORE")
41
+ end
42
+
43
+ # Internal: Cleans up the process at the end of execution.
44
+ def cleanup_process
45
+ reporter.exit_message
46
+ system("stty", self.stty_save);
47
+ end
48
+
49
+ # Internal: Prints config errors, if there are any.
50
+ #
51
+ # Returns true if there were errors, false otherwise.
52
+ def print_config_errors
53
+ config_errors = @config.validation_errors
54
+ if config_errors.length > 0
55
+ reporter.error
56
+ reporter.error(config_errors.first)
57
+ true
58
+ else
59
+ false
60
+ end
61
+ end
62
+
63
+ # Internal: Environment reload run loop.
64
+ #
65
+ # This run loop handles spawning a new tconsole environment - it's basically
66
+ # just there to handle reloads. Also calls out to the input loop for the
67
+ # console.
68
+ #
69
+ # Returns false if tconsole needs to stop, true otherwise.
70
+ def console_run_loop(console)
71
+ pipe_server = ChattyProc::PipeServer.new
72
+
73
+ reporter.trace("Forking test server.")
74
+ server_pid = fork do
75
+ server_run_loop(pipe_server)
76
+ end
77
+
78
+ pipe_server.caller!
79
+ unless load_environment(pipe_server)
80
+ pipe_server.write({:action => "exit"})
81
+ return false
82
+ end
83
+
84
+ continue = console.read_and_execute(pipe_server)
85
+ reporter.trace("Console read loop returned - continue: #{continue}")
86
+
87
+ Process.waitall
88
+
89
+ continue
90
+ end
91
+
92
+ # Internal: Asks the server to load the environment.
93
+ #
94
+ # Returns true if the environment was loaded, or false otherwise.
95
+ def load_environment(pipe_server)
96
+ reporter.trace("Attempting to load environment.")
97
+ pipe_server.write({:action => "load_environment"})
98
+
99
+ if pipe_server.read
100
+ reporter.trace("Environment loaded successfully.")
101
+ true
102
+ else
103
+ reporter.error("Couldn't load the test environment. Exiting.")
104
+ false
105
+ end
106
+ end
107
+
108
+ # Internal: Run loop for the server.
109
+ def server_run_loop(pipe_server)
110
+ pipe_server.callee!
111
+ server = Server.new(config, reporter)
112
+
113
+ while message = pipe_server.read
114
+ reporter.trace("Server Received Message: #{message[:action]}")
115
+ begin
116
+ result = server.handle(message)
117
+ pipe_server.write(result)
118
+ rescue => e
119
+ reporter.error
120
+ reporter.error("An error occured: #{e.message}")
121
+ reporter.trace_backtrace(e)
122
+ pipe_server.write(nil)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -1,9 +1,10 @@
1
1
  module TConsole
2
2
  class Server
3
- attr_accessor :config, :last_result
3
+ attr_accessor :config, :reporter, :last_result
4
4
 
5
- def initialize(config)
5
+ def initialize(config, reporter)
6
6
  self.config = config
7
+ self.reporter = reporter
7
8
  self.last_result = TConsole::TestResult.new
8
9
  end
9
10
 
@@ -23,8 +24,8 @@ module TConsole
23
24
  result = false
24
25
 
25
26
  time = Benchmark.realtime do
26
- puts
27
- puts "Loading environment..."
27
+ reporter.info
28
+ reporter.info("Loading environment...")
28
29
 
29
30
  begin
30
31
  # Append our include paths
@@ -43,20 +44,16 @@ module TConsole
43
44
 
44
45
  result = true
45
46
  rescue Exception => e
46
- puts "Error - Loading your environment failed: #{e.message}"
47
- if config.trace?
48
- puts
49
- puts " #{e.backtrace.join("\n ")}"
50
- end
51
-
47
+ reporter.error("Error - Loading your environment failed: #{e.message}")
48
+ reporter.trace_backtrace(e)
52
49
  return false
53
50
  end
54
51
 
55
52
  preload_test_ids
56
53
  end
57
54
 
58
- puts "Environment loaded in #{"%0.6f" % time}s."
59
- puts
55
+ reporter.info("Environment loaded in #{"%0.6f" % time}s.")
56
+ reporter.info
60
57
 
61
58
  result
62
59
  end
@@ -86,11 +83,11 @@ module TConsole
86
83
  Process.wait(pid)
87
84
 
88
85
  begin
89
- config.trace("Reading result from fork.")
86
+ reporter.trace("Reading result from fork.")
90
87
  Marshal.load(response.unpack("m")[0])
91
88
  rescue => e
92
- config.trace("Problem reading result from fork. Returning nil.")
93
- config.trace(e.message)
89
+ reporter.trace("Problem reading result from fork. Returning nil.")
90
+ reporter.trace(e.message)
94
91
  nil
95
92
  end
96
93
  end
@@ -99,8 +96,8 @@ module TConsole
99
96
  # with class names, method names, and test ids using match_patterns.
100
97
  def run_tests(globs, match_patterns, message = "Running tests...")
101
98
  time = Benchmark.realtime do
102
- puts message
103
- puts
99
+ reporter.info(message)
100
+ reporter.info
104
101
 
105
102
  paths = []
106
103
  globs.each do |glob|
@@ -108,34 +105,34 @@ module TConsole
108
105
  end
109
106
 
110
107
  if paths.length == 0
111
- puts ::Term::ANSIColor.yellow("No test files match your requested test set: #{globs.join(",")}.")
112
- puts ::Term::ANSIColor.yellow("Skipping execution.")
108
+ reporter.warn("No test files match your requested test set: #{globs.join(",")}.")
109
+ reporter.warn("Skipping execution.")
113
110
  return nil
114
111
  end
115
112
 
116
113
  self.last_result = run_in_fork do
117
114
 
118
115
  paths.each do |path|
119
- config.trace("Requested path `#{path}` doesn't exist.") unless File.exist?(path)
116
+ reporter.trace("Requested path `#{path}` doesn't exist.") unless File.exist?(path)
120
117
  require File.expand_path(path)
121
118
  end
122
119
 
123
- config.trace("Running before_test_run callback")
120
+ reporter.trace("Running before_test_run callback")
124
121
  config.before_test_run!
125
- config.trace("Completed before_test_run callback")
122
+ reporter.trace("Completed before_test_run callback")
126
123
 
127
124
  result = nil
128
125
  if defined?(::MiniTest)
129
- config.trace("Detected minitest.")
126
+ reporter.trace("Detected minitest.")
130
127
  require File.join(File.dirname(__FILE__), "minitest_handler")
131
128
 
132
- config.trace("Running tests.")
129
+ reporter.trace("Running tests.")
133
130
  runner = MiniTestHandler.setup(match_patterns, config)
134
131
 
135
132
  # Handle trapping interrupts
136
133
  trap("SIGINT") do
137
- puts
138
- puts "Trapped interrupt. Halting tests."
134
+ reporter.warn
135
+ reporter.warn("Trapped interrupt. Halting tests.")
139
136
 
140
137
  runner.interrupted = true
141
138
  end
@@ -147,16 +144,16 @@ module TConsole
147
144
  # Make sure minitest doesn't run automatically
148
145
  MiniTestHandler.patch_minitest
149
146
 
150
- config.trace("Finished running tests.")
147
+ reporter.trace("Finished running tests.")
151
148
 
152
149
  if runner.interrupted
153
- puts ::Term::ANSIColor.red("Test run was interrupted.")
150
+ reporter.error("Test run was interrupted.")
154
151
  end
155
152
 
156
153
  elsif defined?(::Test::Unit)
157
- puts "Sorry, but tconsole doesn't support Test::Unit yet"
154
+ reporter.error("Sorry, but tconsole doesn't support Test::Unit yet")
158
155
  elsif defined?(::RSpec)
159
- puts "Sorry, but tconsole doesn't support RSpec yet"
156
+ reporter.error("Sorry, but tconsole doesn't support RSpec yet")
160
157
  end
161
158
 
162
159
  result
@@ -172,9 +169,9 @@ module TConsole
172
169
  true
173
170
  end
174
171
 
175
- puts
176
- puts "Tests ran in #{"%0.6f" % time}s. Finished at #{Time.now.strftime('%Y-%m-%d %l:%M:%S %p')}."
177
- puts
172
+ reporter.info
173
+ reporter.info("Tests ran in #{"%0.6f" % time}s. Finished at #{Time.now.strftime('%Y-%m-%d %l:%M:%S %p')}.")
174
+ reporter.info
178
175
  end
179
176
 
180
177
  # Preloads our autocomplete cache
@@ -206,18 +203,18 @@ module TConsole
206
203
 
207
204
  def run_failed
208
205
  if last_result.failures.empty?
209
- puts "No tests failed in your last run, or you haven't run any tests in this session yet."
210
- puts
206
+ reporter.info("No tests failed in your last run, or you haven't run any tests in this session yet.")
207
+ reporter.info
211
208
  else
212
209
  run_tests(config.file_sets["all"], last_result.failures)
213
210
  end
214
211
  end
215
212
 
216
213
  def run_info
217
- puts "Defined Constants:"
218
- puts Module.constants.sort.join("\n")
219
- puts
220
- puts
214
+ reporter.info("Defined Constants:")
215
+ reporter.info(Module.constants.sort.join("\n"))
216
+ reporter.info
217
+ reporter.info
221
218
  end
222
219
 
223
220
  def show_performance(limit = nil)
@@ -227,26 +224,19 @@ module TConsole
227
224
 
228
225
  sorted_timings = last_result.timings.sort_by { |timing| timing[:time] }
229
226
 
230
- puts
231
- puts "Timings from last run:"
232
- puts
227
+ reporter.info
228
+ reporter.info("Timings from last run:")
229
+ reporter.info
233
230
 
234
231
  if sorted_timings.length == 0
235
- puts ::Term::ANSIColor.red + "No timing data available. Be sure you've run some tests." + ::Term::ANSIColor.reset
232
+ reporter.error("No timing data available. Be sure you've run some tests.")
236
233
  else
237
234
  sorted_timings.reverse[0, limit].each do |timing|
238
- output = "#{"%0.6f" % timing[:time]}s #{timing[:name]}"
239
- if timing[:time] > 1
240
- print ::Term::ANSIColor.red, output, ::Term::ANSIColor.reset
241
- else
242
- print ::Term::ANSIColor.green, output, ::Term::ANSIColor.reset
243
- end
244
-
245
- print ::Term::ANSIColor.magenta, " #{last_result.elements[timing[:name]]}", ::Term::ANSIColor.reset, "\n"
235
+ reporter.timing(timing, last_result.elements[timing[:name]])
246
236
  end
247
237
  end
248
238
 
249
- puts
239
+ reporter.info
250
240
  end
251
241
 
252
242
  def set(key, value)
@@ -259,35 +249,16 @@ module TConsole
259
249
  config.fail_fast = false
260
250
  end
261
251
 
262
- puts ::Term::ANSIColor.green + "Fail Fast is now #{config.fail_fast ? "on" : "off"}" + ::Term::ANSIColor.reset
263
- puts
252
+ reporter.exclaim("Fail Fast is now #{config.fail_fast ? "on" : "off"}")
253
+ reporter.exclaim
264
254
  else
265
- puts ::Term::ANSIColor.green + "Fail fast is currently #{config.fail_fast ? "on" : "off"}" + ::Term::ANSIColor.reset
266
- puts
255
+ reporter.exclaim("Fail fast is currently #{config.fail_fast ? "on" : "off"}")
256
+ reporter.exclaim
267
257
  end
268
258
  else
269
- puts ::Term::ANSIColor.yellow + "I don't know how to set `#{key}`." + ::Term::ANSIColor.reset + " Usage: set {key} {value}"
270
- puts
271
- end
272
- end
273
-
274
- # Internal: Runs the given command in the shell.
275
- #
276
- # command - the command to execute
277
- #
278
- # Examples
279
- #
280
- # shell("ls -la")
281
- def shell(command)
282
- system(command)
283
-
284
- result = $?
285
-
286
- puts
287
- if result.exitstatus == 0
288
- puts ::Term::ANSIColor.green + "Command exited with status code: 0" + ::Term::ANSIColor.reset
289
- else
290
- puts ::Term::ANSIColor.red + "Command exited with status code: #{result.exitstatus}" + ::Term::ANSIColor.reset
259
+ reporter.warn("I don't know how to set `#{key}`.")
260
+ reporter.info("Usage: set {key} {value}")
261
+ reporter.warn
291
262
  end
292
263
  end
293
264
  end
@@ -1,3 +1,3 @@
1
1
  module TConsole
2
- VERSION = "1.2.7"
2
+ VERSION = "1.2.8"
3
3
  end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe TConsole::Config do
4
+ context "a Config without arguments" do
5
+ before do
6
+ @config = TConsole::Config.new([])
7
+ @config.test_dir = "./spec/fixtures/minitest"
8
+ end
9
+
10
+ context "when configured test directory doesn't exist" do
11
+ before do
12
+ @config.test_dir = "./monkey_business"
13
+ end
14
+
15
+ it "sets a validation error" do
16
+ expect(@config.validation_errors[0]).to eq("Couldn't find test directory `./monkey_business`. Exiting.")
17
+ end
18
+ end
19
+
20
+ context "when the configuration doesn't include an all file set" do
21
+ before do
22
+ @config.file_sets = {}
23
+ end
24
+
25
+ it "sets a validation error" do
26
+ expect(@config.validation_errors[0]).to eq("No `all` file set is defined in your configuration. Exiting.")
27
+ end
28
+ end
29
+ end
30
+
31
+ context "a Config with the trace argument" do
32
+ before do
33
+ @config = TConsole::Config.new(Shellwords.shellwords("--trace"))
34
+ end
35
+
36
+ it "has tracing enabled" do
37
+ expect(@config.trace_execution).to be_true
38
+ end
39
+ end
40
+
41
+ context "a Config with the once argument" do
42
+ before do
43
+ @config = TConsole::Config.new(Shellwords.shellwords("--once all"))
44
+ end
45
+
46
+ it "has run once enabled" do
47
+ expect(@config.once).to be_true
48
+ end
49
+ end
50
+
51
+ context "a Config with remaining arguments" do
52
+ before do
53
+ @config = TConsole::Config.new(Shellwords.shellwords("--trace set fast on"))
54
+ end
55
+
56
+ it "sets remaining args as first command" do
57
+ expect(@config.run_command).to eq("set fast on")
58
+ end
59
+ end
60
+
61
+ describe ".run" do
62
+ before do
63
+ TConsole::Config.run do |config|
64
+ config.test_dir = "./awesome_sauce"
65
+ end
66
+ end
67
+
68
+ after do
69
+ TConsole::Config.clear_loaded_configs
70
+ end
71
+
72
+ it "saves the run proc" do
73
+ loaded_configs = TConsole::Config.instance_variable_get(:@loaded_configs)
74
+ expect(loaded_configs.length).to eq(1)
75
+ end
76
+
77
+ it "runs loaded configs from first to last" do
78
+ TConsole::Config.run do |config|
79
+ config.test_dir = "./awesomer_sauce"
80
+ end
81
+
82
+ config = TConsole::Config.configure
83
+ expect(config.test_dir).to eq("./awesomer_sauce")
84
+ end
85
+ end
86
+
87
+ describe ".load_config" do
88
+ it "loads configs" do
89
+ TConsole::Config.load_config(File.join(File.dirname(__FILE__), "sample_config"))
90
+ loaded_configs = TConsole::Config.instance_variable_get(:@loaded_configs)
91
+ expect(loaded_configs.length).to eq(1)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ describe TConsole::Runner do
4
+ before do
5
+ @runner = TConsole::Runner.new
6
+ @ps = ChattyProc::PipeServer.new
7
+ end
8
+
9
+ describe "#load_environment" do
10
+ before do
11
+ @ps.stub(:write) { }
12
+ end
13
+
14
+ it "returns false if the environment load call fails" do
15
+ @ps.stub(:read) { false }
16
+ expect(@runner.load_environment(@ps)).to be_false
17
+ end
18
+
19
+ it "returns true if the environment load call succeeds" do
20
+ @ps.stub(:read) { true }
21
+ expect(@runner.load_environment(@ps)).to be_true
22
+ end
23
+ end
24
+
25
+ describe "#console_run_loop" do
26
+ before do
27
+ @config = TConsole::Config.new
28
+ @reporter = TConsole::Reporter.new(@config)
29
+ @console = TConsole::Console.new(@config, @reporter)
30
+ end
31
+
32
+ it "returns false when loading the environment fails" do
33
+ @runner.stub(:load_environment) { false }
34
+
35
+ expect(@runner.console_run_loop(@console)).to be_false
36
+ end
37
+ end
38
+ end
File without changes
@@ -1,7 +1,4 @@
1
1
  require "rubygems"
2
2
  require "bundler/setup"
3
3
 
4
- require 'test/unit'
5
- require 'nutrasuite'
6
-
7
4
  require 'tconsole'
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe "TConsole::Util" do
4
+ describe ".filter_backtrace" do
5
+ before do
6
+ @non_tconsole_path = "/Users/alan/Projects/commondream/tconsole-test/test/functional/posts_controller_test.rb:16:in `block in <class:PostsControllerTest>'"
7
+ @tconsole_path = "#{File.expand_path(File.join(File.dirname(__FILE__), ".."))}/posts_controller_test.rb:16:in `block in <class:PostsControllerTest>'"
8
+
9
+ @backtrace = [
10
+ @non_tconsole_path,
11
+ @tconsole_path
12
+ ]
13
+
14
+ @filtered_backtrace = TConsole::Util.filter_backtrace(@backtrace)
15
+ end
16
+
17
+ context "removes tconsole paths" do
18
+ it { expect(@filtered_backtrace.length).to eq(1) }
19
+ it { expect(@filtered_backtrace).to_not include(@tconsole_path) }
20
+ end
21
+
22
+ it "doesn't remove non-tconsole paths" do
23
+ expect(@filtered_backtrace).to include(@non_tconsole_path)
24
+ end
25
+ end
26
+ end
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  # specify any dependencies here; for example:
25
25
  # s.add_development_dependency "rspec"
26
+ s.add_runtime_dependency "chattyproc", "~> 1.0.0"
26
27
  s.add_runtime_dependency "term-ansicolor", "~> 1.0.7"
27
28
  s.add_runtime_dependency "minitest", "~> 4.3.0"
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tconsole
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
4
+ version: 1.2.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-16 00:00:00.000000000 Z
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chattyproc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: term-ansicolor
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -65,16 +81,18 @@ files:
65
81
  - lib/tconsole/config.rb
66
82
  - lib/tconsole/console.rb
67
83
  - lib/tconsole/minitest_handler.rb
68
- - lib/tconsole/pipe_server.rb
84
+ - lib/tconsole/reporter.rb
85
+ - lib/tconsole/runner.rb
69
86
  - lib/tconsole/server.rb
70
87
  - lib/tconsole/test_result.rb
71
88
  - lib/tconsole/util.rb
72
89
  - lib/tconsole/version.rb
90
+ - spec/config_spec.rb
91
+ - spec/runner_spec.rb
92
+ - spec/sample_config
93
+ - spec/spec_helper.rb
94
+ - spec/util_spec.rb
73
95
  - tconsole.gemspec
74
- - test/test_helper.rb
75
- - test/unit/config_test.rb
76
- - test/unit/sample_config
77
- - test/unit/util_test.rb
78
96
  homepage: ''
79
97
  licenses: []
80
98
  post_install_message:
@@ -100,7 +118,8 @@ signing_key:
100
118
  specification_version: 3
101
119
  summary: tconsole is a helpful console for running Rails tests
102
120
  test_files:
103
- - test/test_helper.rb
104
- - test/unit/config_test.rb
105
- - test/unit/sample_config
106
- - test/unit/util_test.rb
121
+ - spec/config_spec.rb
122
+ - spec/runner_spec.rb
123
+ - spec/sample_config
124
+ - spec/spec_helper.rb
125
+ - spec/util_spec.rb
@@ -1,47 +0,0 @@
1
- module TConsole
2
- class PipeServer
3
-
4
- def initialize
5
- @callee = []
6
- @caller = []
7
- @callee[0], @caller[1] = IO.pipe
8
- @caller[0], @callee[1] = IO.pipe
9
-
10
- @me = nil
11
- end
12
-
13
- # Identifies the current process as the callee process
14
- def callee!
15
- @me = @callee
16
-
17
- @caller.each do |io|
18
- io.close
19
- end
20
- end
21
-
22
- # Identifies the current process as the caller process
23
- def caller!
24
- @me = @caller
25
-
26
- @callee.each do |io|
27
- io.close
28
- end
29
- end
30
-
31
- # Writes a message to the appropriate pipe. The message can be
32
- # anything that will Marshal cleanly
33
- def write(message)
34
- encoded_message = [Marshal.dump(message)].pack("m0")
35
- @me[1].puts(encoded_message)
36
- end
37
-
38
- # Reads a message from the appropriate pipe and unmarshalls it
39
- def read
40
- raw_message = @me[0].gets
41
-
42
- return nil if raw_message.nil?
43
-
44
- Marshal.load(raw_message.unpack("m")[0])
45
- end
46
- end
47
- end
@@ -1,91 +0,0 @@
1
- require 'test_helper'
2
-
3
- module TConsole
4
- class ConfigTest < MiniTest::Unit::TestCase
5
-
6
- a "Config" do
7
- before do
8
- @config = TConsole::Config.new([])
9
- end
10
-
11
- it "should have appropriate defaults" do
12
- assert_equal false, @config.trace_execution
13
- assert_equal "./test", @config.test_dir
14
- assert_equal ["./test", "./lib"], @config.include_paths
15
- assert_equal [], @config.preload_paths
16
- assert_equal false, @config.fail_fast
17
- assert_equal({ "all" => ["./test/**/*_test.rb"] }, @config.file_sets)
18
- end
19
-
20
- it "should have a validation error if the configured test directory doesn't exist" do
21
- @config.test_dir = "./monkey_business"
22
-
23
- errors = @config.validation_errors
24
- refute_nil errors
25
- assert_equal "Couldn't find test directory `./monkey_business`. Exiting.", errors[0]
26
- end
27
-
28
- it "should have a validation error if the configuration doesn't include an all file set" do
29
- @config.file_sets = {}
30
-
31
- errors = @config.validation_errors
32
- refute_nil errors
33
- assert_equal "No `all` file set is defined in your configuration. Exiting.", errors[0]
34
- end
35
- end
36
-
37
- a "Config with command line arguments" do
38
- it "should set up tracing correctly" do
39
- @config = Config.new(Shellwords.shellwords("--trace"))
40
-
41
- assert @config.trace_execution
42
- end
43
-
44
- it "should set up only running the passed command and exiting" do
45
- @config = Config.new(Shellwords.shellwords("--once all"))
46
-
47
- assert @config.once
48
- end
49
-
50
- it "should set all remaining unparsed text to be the first command to run" do
51
- @config = Config.new(Shellwords.shellwords("--trace set fast on"))
52
-
53
- assert_equal "set fast on", @config.run_command
54
- end
55
- end
56
-
57
- the "Config class" do
58
- before do
59
- TConsole::Config.clear_loaded_configs
60
- end
61
-
62
- it "should save the proc passed to run when it's called" do
63
- TConsole::Config.run do |config|
64
- config.test_dir = "./awesome_sauce"
65
- end
66
-
67
- assert_equal 1, TConsole::Config.instance_variable_get(:@loaded_configs).length
68
- end
69
-
70
- it "should apply the loaded configs from first to last when configure is called" do
71
- TConsole::Config.run do |config|
72
- config.test_dir = "./awesome_sauce"
73
- end
74
-
75
- TConsole::Config.run do |config|
76
- config.test_dir = "./awesomer_sauce"
77
- end
78
-
79
- config = TConsole::Config.configure
80
-
81
- assert_equal "./awesomer_sauce", config.test_dir
82
- end
83
-
84
- it "should load a config file when load_config is called" do
85
- TConsole::Config.load_config(File.join(File.dirname(__FILE__), "sample_config"))
86
-
87
- assert_equal 1, TConsole::Config.instance_variable_get(:@loaded_configs).length
88
- end
89
- end
90
- end
91
- end
@@ -1,29 +0,0 @@
1
- require 'test_helper'
2
-
3
- module TConsole
4
- class ConfigTest < MiniTest::Unit::TestCase
5
- a "Backtrace" do
6
- before do
7
- @non_tconsole_path = "/Users/alan/Projects/commondream/tconsole-test/test/functional/posts_controller_test.rb:16:in `block in <class:PostsControllerTest>'"
8
- @tconsole_path = "#{File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))}/posts_controller_test.rb:16:in `block in <class:PostsControllerTest>'"
9
-
10
- @backtrace = [
11
- @non_tconsole_path,
12
- @tconsole_path
13
- ]
14
-
15
- @filtered_backtrace = Util.filter_backtrace(@backtrace)
16
- end
17
-
18
- it "should remove the tconsole path" do
19
- assert_equal 1, @filtered_backtrace.length
20
- assert !@filtered_backtrace.include?(@tconsole_path), "Should filter backtrace item under tconsole"
21
- end
22
-
23
- it "shouldn't remove the non-tconsole path" do
24
- assert @filtered_backtrace.include?(@non_tconsole_path), "Should not filter backtrace item outside of tconsole"
25
- end
26
-
27
- end
28
- end
29
- end