guard-test 0.1.1

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Rémy Coutable
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,77 @@
1
+ = Guard::Test
2
+
3
+ Test::Unit guard allows to automatically & intelligently launch tests when files are modified.
4
+
5
+ - Compatible with Test::Unit 2.1.1.
6
+ - Tested on Ruby 1.8.6, 1.8.7, REE & 1.9.2 (display a annoying "uninitialized constant Test::Unit::UI::Console::Diff" warning though).
7
+
8
+ == Install
9
+
10
+ Please be sure to have {guard}[http://github.com/guard/guard] installed before continue.
11
+
12
+ Install the gem:
13
+
14
+ gem install guard-test
15
+
16
+ Add it to your Gemfile (inside test group):
17
+
18
+ gem 'guard-test'
19
+
20
+ Add guard definition to your Guardfile by running this command:
21
+
22
+ guard init test
23
+
24
+ == Usage
25
+
26
+ Please read {guard usage doc}[http://github.com/guard/guard#readme]
27
+
28
+ == Guardfile
29
+
30
+ Test::Unit guard can be really be adapted to all kind of projects.
31
+ Please read {guard doc}[http://github.com/guard/guard#readme] for more info about Guardfile DSL.
32
+
33
+ === Standard ruby gems
34
+
35
+ guard 'test' do
36
+ watch('^lib/(.*)\.rb') { |m| "test/lib/#{m[1]}_test.rb" }
37
+ watch('^test/(.*)_test.rb')
38
+ watch('^test/test_helper.rb') { "test" }
39
+ end
40
+
41
+ === Rails app
42
+
43
+ guard 'test' do
44
+ watch('^app/models/(.*)\.rb') { |m| "test/unit/#{m[1]}_test.rb" }
45
+ watch('^app/controllers/(.*)\.rb') { |m| "test/functional/#{m[1]}_test.rb" }
46
+ watch('^app/controllers/application_controller.rb') { "test/functional" }
47
+ watch('^app/controllers/application_controller.rb') { "test/integration" }
48
+ watch('^app/views/(.*)\.rb') { "test/integration" }
49
+ watch('^lib/(.*)\.rb') { |m| "test/lib/#{m[1]}_test.rb" }
50
+ watch('^test/(.*)_test.rb')
51
+ watch('^test/factories.rb') { "test/unit" }
52
+ watch('^test/test_helper.rb') { "test" }
53
+ end
54
+
55
+ == Options
56
+
57
+ Test::Unit guard allow you to choose between two different runners:
58
+
59
+ - 'default' (obviously, guard-test will use this by default): Display progress as chars ('.' for pass, 'F' for fail, 'E' for error) and errors when all the tests are finished.
60
+ - 'fastfail': Display failures/errors messages as they happen, not at the end and passing tests with '.'.
61
+
62
+ Set the desired runner by passing the :runner option to the <tt>guard</tt> method:
63
+
64
+ guard 'test', :runner => 'fastfail' do
65
+ ...
66
+ end
67
+
68
+ == Development
69
+
70
+ - Source hosted at {GitHub}[http://github.com/guard/guard-test]
71
+ - Report issues/Questions/Feature requests on {GitHub Issues}[http://github.com/guard/guard-test/issues]
72
+
73
+ Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change you make.
74
+
75
+ == Authors
76
+
77
+ {Rémy Coutable}[http://github.com/rymai]
@@ -0,0 +1,61 @@
1
+ require "#{File.dirname(__FILE__)}/../test"
2
+
3
+ module Formatter
4
+
5
+ def output_results(test_count, assertion_count, failure_count, error_count, duration, options = {})
6
+ output(duration_text(duration, options)) if options[:with_duration]
7
+ color = (failure_count > 0 ? "failure" : (error_count > 0 ? "error" : "pass"))
8
+ output(results_text(test_count, assertion_count, failure_count, error_count), color)
9
+ end
10
+
11
+ def notify_results(test_count, assertion_count, failure_count, error_count, duration)
12
+ notify(
13
+ results_text(test_count, assertion_count, failure_count, error_count) + duration_text(duration, :short => true),
14
+ image(failure_count)
15
+ )
16
+ end
17
+
18
+ def output_and_notify_results(test_count, assertion_count, failure_count, error_count, duration, options = {})
19
+ output_results(test_count, assertion_count, failure_count, error_count, duration, options)
20
+ notify_results(test_count, assertion_count, failure_count, error_count, duration)
21
+ end
22
+
23
+ def image(failure_count)
24
+ failure_count > 0 ? :failed : :success
25
+ end
26
+
27
+ def notify(message, image)
28
+ Guard::Notifier.notify(message, :title => "Test::Unit results", :image => image)
29
+ end
30
+
31
+ def output_single(something, color_name = "reset")
32
+ something = "%s%s%s" % [color_sequence(color_name), something, color_sequence("reset")]
33
+ $stdout.write(something)
34
+ $stdout.flush
35
+ true
36
+ end
37
+
38
+ def output(something, color_name = "reset")
39
+ output_single(something, color_name)
40
+ $stdout.puts
41
+ end
42
+
43
+ private
44
+
45
+ def color_sequence(color_name = "reset")
46
+ "\e[0#{color_code(color_name)}m"
47
+ end
48
+
49
+ def color_code(name = "reset")
50
+ { "pass" => ";32", "failure" => ";31", "pending" => ";33", "error" => ";35", "reset" => "" }[name]
51
+ end
52
+
53
+ def results_text(test_count, assertion_count, failure_count, error_count)
54
+ "#{test_count} tests, #{assertion_count} asserts, #{failure_count} fails, #{error_count} errors"
55
+ end
56
+
57
+ def duration_text(duration, options = {})
58
+ "\n\n#{"Finished " unless options[:short]}in #{duration} seconds\n"
59
+ end
60
+
61
+ end
@@ -0,0 +1,45 @@
1
+ module Guard
2
+ class Test
3
+ module Inspector
4
+ class << self
5
+
6
+ def clean(paths)
7
+ paths.uniq!
8
+ paths.compact!
9
+ clean_paths = paths.select { |p| test_file?(p) || test_folder?(p) }
10
+
11
+ paths.each do |path|
12
+ if File.directory?(path)
13
+ clean_paths.delete(path)
14
+ clean_paths = clean_paths + Dir.glob("#{path}/**/*_test.rb")
15
+ end
16
+ end
17
+
18
+ clean_paths.uniq!
19
+ clean_paths.compact!
20
+ clear_test_files_list
21
+ clean_paths.sort
22
+ end
23
+
24
+ private
25
+
26
+ def test_folder?(path)
27
+ path.match(/^\/?test/) && !path.match(/\..+$/)
28
+ end
29
+
30
+ def test_file?(path)
31
+ test_files.include?(path)
32
+ end
33
+
34
+ def test_files
35
+ @test_files ||= Dir.glob("test/**/*_test.rb")
36
+ end
37
+
38
+ def clear_test_files_list
39
+ @test_files = nil
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ module Guard
2
+ class Test
3
+ module Runner
4
+ class << self
5
+ attr_reader :test_unit_runner
6
+
7
+ AVAILABLE_TEST_UNIT_RUNNERS = %w[default fastfail]
8
+
9
+ def set_test_unit_runner(options = {})
10
+ @test_unit_runner = AVAILABLE_TEST_UNIT_RUNNERS.include?(options[:runner]) ? options[:runner] : 'default'
11
+ end
12
+
13
+ def run(paths, options = {})
14
+ message = "\n" + (options[:message] || "Running (#{@test_unit_runner} runner): #{paths.join(' ') }")
15
+ UI.info(message, :reset => true)
16
+ system(test_unit_command(paths))
17
+ end
18
+
19
+ private
20
+
21
+ def test_unit_command(files)
22
+ cmd_parts = ["ruby"]
23
+ cmd_parts << "-r#{File.dirname(__FILE__)}/runners/#{@test_unit_runner}_test_unit_runner"
24
+ cmd_parts << "-Itest"
25
+ cmd_parts << "-e \"%w[#{files.join(' ')}].each { |f| load f }\""
26
+ cmd_parts << files.map { |f| "\"#{f}\"" }.join(' ')
27
+ cmd_parts << "--runner=guard-#{@test_unit_runner}"
28
+ cmd_parts.join(' ')
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ require "#{File.dirname(__FILE__)}/../formatter"
2
+ require 'test/unit'
3
+ require 'test/unit/testcase'
4
+ require 'test/unit/ui/console/testrunner'
5
+
6
+ # Thanks to Adam Sanderson for the really good starting point:
7
+ # http://endofline.wordpress.com/2008/02/11/a-custom-testrunner-to-scratch-an-itch/
8
+ #
9
+ # This class inherits from Test::Unit' standard console TestRunner
10
+ # I'm just overriding some callbacks methods to display nice results
11
+ class DefaultGuardTestRunner < Test::Unit::UI::Console::TestRunner
12
+ include Formatter
13
+
14
+ def initialize(suite, options = {})
15
+ super
16
+ @use_color = true
17
+ end
18
+
19
+ protected
20
+
21
+ # Test::Unit::UI::Console::TestRunner overrided methods
22
+ def setup_mediator
23
+ @mediator = Test::Unit::UI::TestRunnerMediator.new(@suite)
24
+ end
25
+
26
+ def started(result)
27
+ @result = result
28
+ end
29
+
30
+ def test_started(name) # silence!
31
+ end
32
+
33
+ def add_fault(fault)
34
+ @faults << fault
35
+ output_single(fault.single_character_display, fault_color_name(fault))
36
+ @already_outputted = true
37
+ end
38
+
39
+ def test_finished(name)
40
+ output_single(".", "pass") unless @already_outputted
41
+ @already_outputted = false
42
+ end
43
+
44
+ def finished(elapsed_time)
45
+ nl
46
+ super
47
+ notify_results(@result.run_count, @result.assertion_count, @result.failure_count, @result.error_count, elapsed_time)
48
+ end
49
+
50
+ def fault_color_name(fault)
51
+ fault.class.name.split(/::/).last.downcase
52
+ end
53
+
54
+ end
55
+
56
+ Test::Unit::AutoRunner::RUNNERS["guard-default"] = Proc.new { |r| DefaultGuardTestRunner }
@@ -0,0 +1,24 @@
1
+ require "#{File.dirname(__FILE__)}/default_test_unit_runner"
2
+
3
+ # This class is directly inspired by a blog post by Adam Sanderson:
4
+ # http://endofline.wordpress.com/2008/02/11/a-custom-testrunner-to-scratch-an-itch/
5
+ # It inherits DefaultGuardTestRunner and redefines only 2 methods in order to display failures
6
+ # as they happen (the default display them when all the tests are finished).
7
+ class FastfailGuardTestUnitRunner < DefaultGuardTestRunner
8
+
9
+ private
10
+
11
+ def add_fault(fault)
12
+ @faults << fault
13
+ nl
14
+ output("%3d) %s" % [@faults.length, fault.long_display])
15
+ @already_outputted = true
16
+ end
17
+
18
+ def finished(elapsed_time)
19
+ output_and_notify_results(@result.run_count, @result.assertion_count, @result.failure_count, @result.error_count, elapsed_time, :with_duration => true)
20
+ end
21
+
22
+ end
23
+
24
+ Test::Unit::AutoRunner::RUNNERS["guard-fastfail"] = Proc.new { |r| FastfailGuardTestUnitRunner }
@@ -0,0 +1,13 @@
1
+ guard 'test' do
2
+ watch('^lib/(.*)\.rb') { |m| "test/lib/#{m[1]}_test.rb" }
3
+ watch('^test/(.*)_test.rb')
4
+ watch('^test/test_helper.rb') { "test" }
5
+
6
+ # Rails example
7
+ watch('^app/models/(.*)\.rb') { |m| "test/unit/#{m[1]}_test.rb" }
8
+ watch('^app/controllers/(.*)\.rb') { |m| "test/functional/#{m[1]}_test.rb" }
9
+ watch('^app/controllers/application_controller.rb') { "test/functional" }
10
+ watch('^app/controllers/application_controller.rb') { "test/integration" }
11
+ watch('^app/views/(.*)\.rb') { "test/integration" }
12
+ watch('^test/factories.rb') { "test/unit" }
13
+ end
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module TestVersion
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
data/lib/guard/test.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'guard'
3
+ require 'guard/guard'
4
+
5
+ module Guard
6
+ class Test < Guard
7
+
8
+ autoload :Runner, 'guard/test/runner'
9
+ autoload :Inspector, 'guard/test/inspector'
10
+
11
+ def start
12
+ Runner.set_test_unit_runner(options)
13
+ UI.info "Guard::Test is guarding your tests!"
14
+ end
15
+
16
+ def run_all
17
+ clean_and_run(["test"], :message => "Running all tests")
18
+ end
19
+
20
+ def run_on_change(paths)
21
+ clean_and_run(paths)
22
+ end
23
+
24
+ private
25
+
26
+ def clean_and_run(paths, options = {})
27
+ paths = Inspector.clean(paths)
28
+ Runner.run(paths, options) unless paths.empty?
29
+ end
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guard-test
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - "R\xC3\xA9my Coutable"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-19 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: guard
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 62196353
30
+ segments:
31
+ - 0
32
+ - 2
33
+ - 0
34
+ - beta
35
+ - 1
36
+ version: 0.2.0.beta.1
37
+ type: :runtime
38
+ version_requirements: *id001
39
+ - !ruby/object:Gem::Dependency
40
+ name: bundler
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ hash: 19
48
+ segments:
49
+ - 1
50
+ - 0
51
+ - 2
52
+ version: 1.0.2
53
+ type: :development
54
+ version_requirements: *id002
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ prerelease: false
58
+ requirement: &id003 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ hash: 15
64
+ segments:
65
+ - 2
66
+ - 0
67
+ - 0
68
+ version: 2.0.0
69
+ type: :development
70
+ version_requirements: *id003
71
+ - !ruby/object:Gem::Dependency
72
+ name: guard-rspec
73
+ prerelease: false
74
+ requirement: &id004 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ hash: 29
80
+ segments:
81
+ - 0
82
+ - 1
83
+ - 3
84
+ version: 0.1.3
85
+ type: :development
86
+ version_requirements: *id004
87
+ - !ruby/object:Gem::Dependency
88
+ name: test-unit
89
+ prerelease: false
90
+ requirement: &id005 !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ hash: 9
96
+ segments:
97
+ - 2
98
+ - 1
99
+ - 1
100
+ version: 2.1.1
101
+ type: :development
102
+ version_requirements: *id005
103
+ description: Guard::Test automatically run your tests and notify you of the result when a file is modified.
104
+ email:
105
+ - rymai@rymai.com
106
+ executables: []
107
+
108
+ extensions: []
109
+
110
+ extra_rdoc_files: []
111
+
112
+ files:
113
+ - lib/guard/test/formatter.rb
114
+ - lib/guard/test/inspector.rb
115
+ - lib/guard/test/runner.rb
116
+ - lib/guard/test/runners/default_test_unit_runner.rb
117
+ - lib/guard/test/runners/fastfail_test_unit_runner.rb
118
+ - lib/guard/test/templates/Guardfile
119
+ - lib/guard/test/version.rb
120
+ - lib/guard/test.rb
121
+ - LICENSE
122
+ - README.rdoc
123
+ has_rdoc: true
124
+ homepage: http://rubygems.org/gems/guard-test
125
+ licenses: []
126
+
127
+ post_install_message:
128
+ rdoc_options: []
129
+
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ hash: 23
147
+ segments:
148
+ - 1
149
+ - 3
150
+ - 6
151
+ version: 1.3.6
152
+ requirements: []
153
+
154
+ rubyforge_project: guard-test
155
+ rubygems_version: 1.3.7
156
+ signing_key:
157
+ specification_version: 3
158
+ summary: Guard gem for Test::Unit
159
+ test_files: []
160
+