autotest-run_dependencies 0.1.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.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009 Toby Clemson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,130 @@
1
+ = Autotest::RunDependencies
2
+
3
+ * Author: Toby Clemson (tobyclemson@gmail.com)
4
+
5
+ == DESCRIPTION:
6
+
7
+ This gem provides a mechanism through which it is possible to specify that an
8
+ arbitrary number of external dependencies are satisfied before a test run can
9
+ be executed.
10
+
11
+ Dependencies are added by specifying a name, command, satisfied_regexp and
12
+ errors_regexp parameter for each. The command refers to a script that is run
13
+ to satisfy or test the dependency. If the output of the command (either
14
+ to standard output or standard error) matches the satisfied_regexp then the
15
+ dependency is considered met otherwise any lines in the output matching
16
+ errors_regexp are output and the dependency test waits for changes to the
17
+ codebase before trying to satisfy the dependency again.
18
+
19
+ By default, the output is colourised in green if a dependency is satisfied
20
+ and red if a dependency is not satisfied. This colourisation can be turned
21
+ off if required.
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * ZenTest >= 3.9.0
26
+
27
+ == INSTALL:
28
+
29
+ The gem can be installed using the following command:
30
+
31
+ sudo gem install autotest-run_dependencies
32
+
33
+ == SETUP & CONFIGURATION:
34
+
35
+ To add a dependency to the autotest test runs for a particular project, add
36
+ the following to a .autotest file in the root of your project:
37
+
38
+ require "autotest/run_requirements"
39
+
40
+ Autotest::RunDependencies.add do |dependency|
41
+ dependency.name = "dependency name" # used to identify the dependency
42
+ dependency.command = "command_or_script" # the command to run
43
+ dependency.satisfied_regexp = /success/ # a regexp matching the output if successful
44
+ dependency.errors_regexp = /error: (.*)/ # a regexp matching errors in the command output
45
+ end
46
+
47
+ The only required parameters are command and satisfied_regexp. This call
48
+ automatically registers your dependency with autotest so that it will run
49
+ before every test autotest test run.
50
+
51
+ By default the status messages are coloured green for success, red for
52
+ failure. This can be turned off by setting colourised_output to false:
53
+
54
+ Autotest::RunDependencies.colourised_output = false
55
+
56
+ == EXAMPLE
57
+
58
+ Using JRuby it is possible to use RSpec to specify Java code. In such an
59
+ instance it is required that the codebase compiles successfully before the
60
+ specs are run against it. Many Java developers use the popular 'ant' tool to
61
+ compile their code and so here we will assume the codebase is compiled using
62
+ the command 'ant clean jar'. This dependency can be accomplished using
63
+ Autotest::RunDependencies by creating a .autotest file in your project root
64
+ containing the following:
65
+
66
+ require "autotest/run_requirements"
67
+
68
+ Autotest::RunDependencies.add do |dependency|
69
+ dependency.name = "codebase compiles successfully"
70
+ dependency.command = "ant clean jar"
71
+ dependency.satisfied_regexp = /^BUILD SUCCESSFUL$/
72
+ dependency.errors_regexp = /^\s*\[javac\]\s(.*)$/
73
+ end
74
+
75
+ This ensures that the command "ant clean jar" is called and outputs
76
+ 'BUILD SUCCESSFUL' before the test suite is run. If the build fails,
77
+ each line beginning with '[javac]' is output and the dependency test waits
78
+ for the compile errors to be fixed before rerunning the build.
79
+
80
+ You may also need to set up a mapping from the Java source files to spec
81
+ files. Assuming the source files are in a directory 'src/' and that Java
82
+ classes use camel case (SomeClass.java) whilst specification files use
83
+ underscore separated lowercase (some_class_spec.rb) this can be accomplished
84
+ using: (conversion code taken from ActiveSupport)
85
+
86
+ Autotest.add_hook :initialize do |autotest|
87
+ autotest.add_mapping(%r%^src/(.*)\.java$%) { |_, m|
88
+ ruby_style_name = m[1].gsub(
89
+ /([A-Z]+)([A-Z][a-z])/,'\1_\2'
90
+ ).gsub(
91
+ /([a-z\d])([A-Z])/,'\1_\2'
92
+ ).tr("-", "_").downcase
93
+ ["spec/#{ruby_style_name}_spec.rb"]
94
+ }
95
+ false # important: allows other hooks to be called
96
+ end
97
+
98
+ == DEVELOPMENT:
99
+
100
+ The code is hosted on github at
101
+ http://www.github.com/tobyclemson/autotest-run_requirements and so forking is
102
+ encouraged.
103
+
104
+ Alternatively, suggestions for improvements are welcome at my email address
105
+ tobyclemson@gmail.com
106
+
107
+ == LICENSE:
108
+
109
+ (The MIT License)
110
+
111
+ Copyright (c) 2009 Toby Clemson
112
+
113
+ Permission is hereby granted, free of charge, to any person obtaining
114
+ a copy of this software and associated documentation files (the
115
+ 'Software'), to deal in the Software without restriction, including
116
+ without limitation the rights to use, copy, modify, merge, publish,
117
+ distribute, sublicense, and/or sell copies of the Software, and to
118
+ permit persons to whom the Software is furnished to do so, subject to
119
+ the following conditions:
120
+
121
+ The above copyright notice and this permission notice shall be
122
+ included in all copies or substantial portions of the Software.
123
+
124
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
125
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
126
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
127
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
128
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
129
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
130
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'spec/rake/spectask'
5
+ require 'jeweler'
6
+
7
+ Rake::RDocTask.new do |rd|
8
+ rd.main = "README.rdoc"
9
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
10
+ rd.rdoc_dir = 'doc'
11
+ rd.title = 'Autotest::RunDependencies RDoc Documentation'
12
+ end
13
+
14
+ Spec::Rake::SpecTask.new
15
+
16
+ Jeweler::Tasks.new do |gemspec|
17
+ gemspec.name = "autotest-run_dependencies"
18
+ gemspec.summary = "Test dependencies for autotest."
19
+ gemspec.description = <<EOF
20
+ This gem provides a mechanism through which it is possible to specify that
21
+ an arbitrary number of external dependencies are satisfied before a test
22
+ run can be executed.
23
+
24
+ Dependencies are added by specifying a name, command, satisfied_regexp and
25
+ errors_regexp parameter for each. The command refers to a script that is
26
+ run to satisfy or test the dependency. If the output of the command
27
+ (either to standard output or standard error) matches the satisfied_regexp
28
+ then the dependency is considered met otherwise any lines in the output
29
+ matching errors_regexp are output and the dependency test waits for changes
30
+ to the codebase before trying to satisfy the dependency again.
31
+ EOF
32
+ gemspec.email = "tobyclemson@gmail.com"
33
+ gemspec.homepage = "http://github.com/tobyclemson/autotest-run_dependencies"
34
+ gemspec.authors = ["Toby Clemson"]
35
+ gemspec.add_dependency('ZenTest', '>= 3.9.0')
36
+ gemspec.files.exclude ".gitignore"
37
+ gemspec.rdoc_options << '--main' << 'README.rdoc' <<
38
+ '--title' << 'Autotest::RunDependencies RDoc Documentation' <<
39
+ '--line-numbers'
40
+ gemspec.development_dependencies << 'rspec'
41
+ end
42
+
43
+ Jeweler::GemcutterTasks.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,11 @@
1
+ $:.unshift(
2
+ File.dirname(__FILE__)
3
+ ) unless
4
+ $:.include?(File.dirname(__FILE__)) ||
5
+ $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ require File.join(File.dirname(__FILE__), 'autotest', 'run_dependencies')
8
+
9
+ class Autotest::RunDependencies
10
+ VERSION = '0.1'
11
+ end
@@ -0,0 +1,214 @@
1
+ require 'rubygems'
2
+ require 'autotest'
3
+ require 'ostruct'
4
+
5
+ # Autotest::RunDependencies
6
+ #
7
+ # == FEATURES:
8
+ # * Allows an arbitrary number of dependencies to be set that must be
9
+ # satisfied before a test run is executed.
10
+ # * The dependencies take the form of scripts that output to stdout or stderr.
11
+ # * The dependency is considered satisfied if the output matches some user
12
+ # specified regular expression.
13
+ # * If the dependency is not satisfied, a list of errors is printed where
14
+ # each error is a match of the user supplied errors regular expression.
15
+ # * By default, output is colourised green on success, red on failure.
16
+ # * Colourisation can be turned off.
17
+ #
18
+ # == SYNOPSIS:
19
+ # PROJECT_ROOT/.autotest
20
+ # require 'autotest/run_dependencies.rb'
21
+ #
22
+ # # Add a dependency to the run dependencies
23
+ # Autotest::RunDependencies.add do |dependency|
24
+ # dependency.name = 'some dependency'
25
+ # dependency.command = 'echo "success"'
26
+ # dependency.satisfied_regexp = /success/
27
+ # dependency.errors_regexp = /error (.*)/
28
+ # end
29
+ class Autotest::RunDependencies
30
+
31
+ attr_accessor :name,
32
+ :command,
33
+ :satisfied_regexp,
34
+ :errors_regexp,
35
+ :last_dependency_check_time,
36
+ :autotest_instance
37
+
38
+ # By default the output produced is colourised.
39
+ @@colourise_output = true
40
+
41
+ class << self
42
+ # Returns true if Autotest::RunDependencies is currently
43
+ # configured to colourise its output, false otherwise.
44
+ def colourise_output
45
+ @@colourise_output
46
+ end
47
+ alias_method :colorize_output, :colourise_output
48
+
49
+ # Sets whether or not Autotest::RunDependencies should colourise
50
+ # its output.
51
+ def colourise_output=(boolean)
52
+ @@colourise_output = boolean
53
+ end
54
+ alias_method :colorize_output=, :colourise_output=
55
+ end
56
+
57
+ # Adds a test dependency to any autotest test run.
58
+ #
59
+ # Expects a block to be supplied that sets the dependency parameters, e.g.,
60
+ #
61
+ # Autotest::RunDependencies.add do |dependency|
62
+ # dependency.name = 'some dependency'
63
+ # dependency.command = 'echo "success"'
64
+ # dependency.satisfied_regexp = /success/
65
+ # dependency.errors_regexp = /error (.*)/
66
+ # end
67
+ #
68
+ # Returns the dependency (an instance of Autotest::RunDependencies).
69
+ #
70
+ # It is possible not to pass a block and set the parameters on the returned
71
+ # object but if a dependency object has no #command and #satisfied_regexp
72
+ # set then on calling #ensure_dependency_is_satisfied a RuntimeError is
73
+ # raised.
74
+ #
75
+ # The method also registers the relevant hooks with Autotest so that the
76
+ # dependency is required to be satisfied before the test run.
77
+ def self.add(&block)
78
+ parameters = OpenStruct.new
79
+ block.call(parameters) if block
80
+ dependency = self.new(
81
+ :name => parameters.name,
82
+ :command => parameters.command,
83
+ :satisfied_regexp => parameters.satisfied_regexp,
84
+ :errors_regexp => parameters.errors_regexp
85
+ )
86
+
87
+ Autotest.add_hook(:initialize) do |autotest|
88
+ dependency.autotest_instance = autotest
89
+ false
90
+ end
91
+
92
+ Autotest.add_hook(:run_command) do |autotest|
93
+ dependency.ensure_dependency_is_satisfied
94
+ false
95
+ end
96
+
97
+ Autotest.add_hook(:interrupt) do |autotest|
98
+ dependency.reset
99
+ false
100
+ end
101
+
102
+ return dependency
103
+ end
104
+
105
+ # Creates an instance of Autotest::RunDependencies.
106
+ #
107
+ # The optional _options_ hash can contain values for the keys :name,
108
+ # :command, :satisfied_regexp and :errors_regexp. Any other entries will be
109
+ # ignored. The values of the parameters are used as default values for the
110
+ # instance's attributes.
111
+ def initialize(options = {})
112
+ self.name = options[:name]
113
+ self.command = options[:command]
114
+ self.satisfied_regexp = options[:satisfied_regexp]
115
+ self.errors_regexp = options[:errors_regexp]
116
+ self.last_dependency_check_time = Time.at(0)
117
+ end
118
+
119
+ # Runs the dependency test command if any files have been modified since the
120
+ # last time the dependency was checked. If the dependency is satisfied,
121
+ # i.e., the output of the command matches the regular expression in
122
+ # the #satisfied_regexp attribute, then the test run is allowed to continue,
123
+ # otherwise the method prints any lines in the output that match the regular
124
+ # expression in the #errors_regexp attribute and waits for further changes
125
+ # to the codebase before trying to test the dependency again.
126
+ #
127
+ # This method raises a RuntimeError unless both the #command and
128
+ # #satisfied_regexp attributes are set.
129
+ def ensure_dependency_is_satisfied
130
+ unless self.command and self.satisfied_regexp
131
+ raise(
132
+ RuntimeError,
133
+ "Dependencies must have at least a command and a satisfied_regexp " +
134
+ " set."
135
+ )
136
+ end
137
+ if find_changed_files
138
+ puts "\nChecking dependency: #{self.name}"
139
+ loop do
140
+ self.last_dependency_check_time = Time.now
141
+ test_dependency
142
+ if satisfied?
143
+ puts "-> #{green_command}Dependency satisfied\n#{no_colour_command}"
144
+ break
145
+ else
146
+ puts "-> #{red_command}Dependency not satisfied:\n" +
147
+ "#{errors}#{no_colour_command}"
148
+ wait_for_changes
149
+ puts "Rechecking dependency: #{self.name}"
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ # Resets the dependency state so that it will recheck the dependency during
156
+ # the next test run regardless of whether any files have changed.
157
+ def reset
158
+ self.last_dependency_check_time = Time.at(0)
159
+ end
160
+
161
+ private
162
+
163
+ # Runs the dependency command redirecting stderr into stdout.
164
+ def test_dependency
165
+ @results = `#{self.command} 2>&1`
166
+ end
167
+
168
+ # Returns true if the output of the dependency command matches the
169
+ # #satisfied_regexp, false otherwise.
170
+ def satisfied?
171
+ (@results =~ self.satisfied_regexp) ? true : false
172
+ end
173
+
174
+ # Returns a string of errors matching the #errors_regexp on separate lines
175
+ # indented by four spaces.
176
+ def errors
177
+ " " + @results.scan(self.errors_regexp).join("\n ")
178
+ end
179
+
180
+ # Sleeps until files in the codebase are modified.
181
+ def wait_for_changes
182
+ sleep(self.autotest_instance.sleep) until find_changed_files
183
+ end
184
+
185
+ # Searches the codebase for files that have been modified since the last
186
+ # dependency check.
187
+ def find_changed_files
188
+ changed_files = self.autotest_instance.
189
+ find_files.
190
+ delete_if do |filename, modification_time|
191
+ modification_time < self.last_dependency_check_time
192
+ end
193
+
194
+ changed_files.empty? ? false : true
195
+ end
196
+
197
+ # Returns a string representing the colour code for green output if
198
+ # output colorisation is turned on.
199
+ def green_command
200
+ self.class.colourise_output ? "\e\[32m" : nil
201
+ end
202
+
203
+ # Returns a string representing the colour code for red output if
204
+ # output colorisation is turned on.
205
+ def red_command
206
+ self.class.colourise_output ? "\e\[31m" : nil
207
+ end
208
+
209
+ # Returns a string representing the colour code for colourless output if
210
+ # output colorisation is turned on.
211
+ def no_colour_command
212
+ self.class.colourise_output ? "\e\[0m" : nil
213
+ end
214
+ end
@@ -0,0 +1,349 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ describe Autotest::RunDependencies do
4
+ before(:each) do
5
+ @dependency_parameters = {
6
+ :name => 'Generic dependency',
7
+ :command => 'script_ensuring_dependency_is_in_place arg arg',
8
+ :satisfied_regexp => /success/,
9
+ :errors_regexp => /error: (.*)/
10
+ }
11
+ @dependency = Autotest::RunDependencies.new(@dependency_parameters)
12
+ end
13
+
14
+ describe "#initialize" do
15
+ it "sets the dependency name to the supplied name" do
16
+ @dependency.name.should == @dependency_parameters[:name]
17
+ end
18
+
19
+ it "sets the dependency command to the supplied command" do
20
+ @dependency.command.should == @dependency_parameters[:command]
21
+ end
22
+
23
+ it "sets the dependency satisfied_regexp to the supplied " +
24
+ "satisfied_regexp" do
25
+ @dependency.satisfied_regexp.should ==
26
+ @dependency_parameters[:satisfied_regexp]
27
+ end
28
+
29
+ it "sets the dependency errors_regexp to the supplied " +
30
+ "errors_regexp" do
31
+ @dependency.errors_regexp.should ==
32
+ @dependency_parameters[:errors_regexp]
33
+ end
34
+
35
+ it "sets the dependency last_dependency_check_time to the epoch" do
36
+ @dependency.last_dependency_check_time.should == Time.at(0)
37
+ end
38
+ end
39
+
40
+ describe ".add" do
41
+ before(:each) do
42
+ Autotest.stub(:add_hook)
43
+ end
44
+
45
+ it "creates a new dependecy with the parameters set in the block" do
46
+ Autotest::RunDependencies.should_receive(:new).with(
47
+ :name => 'Dependency name',
48
+ :command => 'dependency_command',
49
+ :satisfied_regexp => /satisfied/,
50
+ :errors_regexp => /error/
51
+ )
52
+ Autotest::RunDependencies.add do |dependency|
53
+ dependency.name = 'Dependency name'
54
+ dependency.command = 'dependency_command'
55
+ dependency.satisfied_regexp = /satisfied/
56
+ dependency.errors_regexp = /error/
57
+ end
58
+ end
59
+
60
+ it "adds an :initialize hook to autotest in which the dependencies' " +
61
+ "autotest instance is set" do
62
+ mock_dependency = mock('dependency', :null_object => true)
63
+ Autotest::RunDependencies.stub(:new).and_return(mock_dependency)
64
+
65
+ mock_dependency.should_receive(:autotest_instance=).with('autotest')
66
+ Autotest.
67
+ should_receive(:add_hook).
68
+ with(:initialize).
69
+ and_yield('autotest')
70
+
71
+ Autotest::RunDependencies.add do |dependency|
72
+ dependency.name = 'Dependency name'
73
+ dependency.command = 'dependency_command'
74
+ dependency.satisfied_regexp = /satisfied/
75
+ dependency.errors_regexp = /error/
76
+ end
77
+ end
78
+
79
+ it "adds a :run_command hook to autotest in which the " +
80
+ "ensure_dependency_is_satisfied method is called on the dependency" do
81
+ mock_dependency = mock('dependency', :null_object => true)
82
+ Autotest::RunDependencies.stub(:new).and_return(mock_dependency)
83
+
84
+ mock_dependency.should_receive(:ensure_dependency_is_satisfied)
85
+ Autotest.
86
+ should_receive(:add_hook).
87
+ with(:run_command).
88
+ and_yield('autotest')
89
+
90
+ Autotest::RunDependencies.add do |dependency|
91
+ dependency.name = 'Dependency name'
92
+ dependency.command = 'dependency_command'
93
+ dependency.satisfied_regexp = /satisfied/
94
+ dependency.errors_regexp = /error/
95
+ end
96
+ end
97
+
98
+ it "adds an :interrupt hook to autotest in which the reset method is " +
99
+ "called on the dependency" do
100
+ mock_dependency = mock('dependency', :null_object => true)
101
+ Autotest::RunDependencies.stub(:new).and_return(mock_dependency)
102
+
103
+ mock_dependency.should_receive(:reset)
104
+ Autotest.
105
+ should_receive(:add_hook).
106
+ with(:interrupt).
107
+ and_yield('autotest')
108
+
109
+ Autotest::RunDependencies.add do |dependency|
110
+ dependency.name = 'Dependency name'
111
+ dependency.command = 'dependency_command'
112
+ dependency.satisfied_regexp = /satisfied/
113
+ dependency.errors_regexp = /error/
114
+ end
115
+ end
116
+
117
+ it "returns the created dependency" do
118
+ mock_dependency = mock('dependency', :null_object => true)
119
+ Autotest::RunDependencies.stub(:new).and_return(mock_dependency)
120
+
121
+ Autotest::RunDependencies.add.should == mock_dependency
122
+ end
123
+ end
124
+
125
+ describe "#ensure_dependency_is_satisfied" do
126
+ before(:each) do
127
+ @autotest = mock('autotest')
128
+ @autotest.stub(:sleep).and_return(1)
129
+ @dependency.stub(:`).and_return('success')
130
+ @dependency.stub(:puts).and_return('true')
131
+ @dependency.autotest_instance = @autotest
132
+ end
133
+
134
+ it "raises a runtime error if no command is set" do
135
+ @dependency.command = nil
136
+ expect {
137
+ @dependency.ensure_dependency_is_satisfied
138
+ }.to raise_error(RuntimeError)
139
+ end
140
+
141
+ it "raises a runtime error if no satisfied_regexp is set" do
142
+ @dependency.satisfied_regexp = nil
143
+ expect {
144
+ @dependency.ensure_dependency_is_satisfied
145
+ }.to raise_error(RuntimeError)
146
+ end
147
+
148
+ describe "if files have been modified since the last dependency test" do
149
+ before(:each) do
150
+ @dependency.last_dependency_check_time = Time.at(0)
151
+ @autotest.stub(:find_files).and_return(
152
+ {'file1' => Time.at(10), 'file2' => Time.at(20)}
153
+ )
154
+ end
155
+
156
+ it "calls the stored command, redirecting stderr to stdout" do
157
+ @dependency.should_receive(:`).with(@dependency.command + " 2>&1")
158
+ @dependency.ensure_dependency_is_satisfied
159
+ end
160
+
161
+ it "outputs a message on a new line saying that it is about to " +
162
+ "check the dependency" do
163
+ @dependency.should_receive(:puts).with(
164
+ "\nChecking dependency: #{@dependency.name}"
165
+ )
166
+ @dependency.ensure_dependency_is_satisfied
167
+ end
168
+
169
+ describe "and the dependency is satisfied" do
170
+ it "outputs a message saying the dependency has been satisfied" do
171
+ @dependency.should_receive(:puts).with(
172
+ /Dependency satisfied/
173
+ )
174
+ @dependency.ensure_dependency_is_satisfied
175
+ end
176
+
177
+ it "only calls the stored command once and returns" do
178
+ @dependency.should_receive(:`).once
179
+ @dependency.ensure_dependency_is_satisfied
180
+ end
181
+ end
182
+
183
+ describe "and the dependency is not satisfied" do
184
+ before(:each) do
185
+ @dependency.stub(:`).and_return(
186
+ "failed:\nerror: dependency not met\nerror: sorry mate",
187
+ "success"
188
+ )
189
+ @autotest.stub(:find_files).and_return(
190
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
191
+ {'file1' => Time.now + 100, 'file2' => Time.at(20)}
192
+ )
193
+ end
194
+
195
+ it "outputs a message saying the dependency hasn't been satisfied" do
196
+ @dependency.should_receive(:puts).with(
197
+ /Dependency not satisfied:/
198
+ )
199
+ @dependency.ensure_dependency_is_satisfied
200
+ end
201
+
202
+ it "outputs any lines in the command result that match the error " +
203
+ "regexp on newlines and indented by a tab character" do
204
+ @dependency.should_receive(:puts).with(
205
+ /\s*dependency not met\n\s*sorry mate/
206
+ )
207
+ @dependency.ensure_dependency_is_satisfied
208
+ end
209
+
210
+ it "sleeps until some files have a modification time more recent " +
211
+ "than the last_dependency_check_time" do
212
+ @autotest.stub(:find_files).and_return(
213
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
214
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
215
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
216
+ {'file1' => (Time.now + 100), 'file2' => Time.at(20)}
217
+ )
218
+ @dependency.should_receive(:sleep).with(@autotest.sleep).twice
219
+ @dependency.ensure_dependency_is_satisfied
220
+ end
221
+
222
+ it "outputs a message saying that it is rechecking the dependency " +
223
+ "if a file is changed" do
224
+ @dependency.should_receive(:puts).with(
225
+ "Rechecking dependency: #{@dependency.name}"
226
+ )
227
+ @dependency.ensure_dependency_is_satisfied
228
+ end
229
+
230
+ it "reruns the dependency check until it is successful" do
231
+ @autotest.stub(:find_files).and_return(
232
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
233
+ {'file1' => (Time.now + 100), 'file2' => Time.at(20)},
234
+ {'file1' => (Time.now + 100), 'file2' => (Time.now + 200)}
235
+ )
236
+ @dependency.should_receive(:`).exactly(3).times.and_return(
237
+ "failed:\nerror: dependency not met\nerror: sorry mate",
238
+ "failed:\nerror: dependency not met\nerror: sorry mate",
239
+ "success"
240
+ )
241
+ @dependency.ensure_dependency_is_satisfied
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ describe "#reset" do
248
+ it "resets the last_dependency_check_time to the epoch" do
249
+ @dependency.last_dependency_check_time = Time.now
250
+ @dependency.reset
251
+ @dependency.last_dependency_check_time.should == Time.at(0)
252
+ end
253
+ end
254
+
255
+ describe "colourised output" do
256
+ before(:each) do
257
+ @autotest = mock('autotest')
258
+ @autotest.stub(:sleep).and_return(1)
259
+ @autotest.stub(:find_files).and_return(
260
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
261
+ {'file1' => Time.now + 100, 'file2' => Time.at(20)}
262
+ )
263
+ @dependency.stub(:`).and_return('success')
264
+ @dependency.stub(:puts).and_return('true')
265
+ @dependency.autotest_instance = @autotest
266
+ end
267
+
268
+ describe "#colourise_output" do
269
+ describe "by default" do
270
+ it "is true" do
271
+ Autotest::RunDependencies.colourise_output.should be_true
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "#colourise_output=" do
277
+ it "allows colourised output to be turned off" do
278
+ Autotest::RunDependencies.colourise_output = false
279
+ Autotest::RunDependencies.colourise_output.should be_false
280
+ end
281
+ end
282
+
283
+ describe "when on" do
284
+ before(:each) do
285
+ Autotest::RunDependencies.colourise_output = true
286
+ end
287
+
288
+ it "outputs the dependency satisfied message in green" do
289
+ @dependency.should_receive(:puts).with(
290
+ /\e\[32mDependency satisfied\n\e\[0m/
291
+ )
292
+ @dependency.ensure_dependency_is_satisfied
293
+ end
294
+
295
+ it "outputs the dependency not satisfied message and errors in red" do
296
+ @dependency.stub(:`).and_return(
297
+ "failed:\nerror: dependency not met\nerror: sorry mate",
298
+ "success"
299
+ )
300
+ @autotest.stub(:find_files).and_return(
301
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
302
+ {'file1' => Time.now + 100, 'file2' => Time.at(20)}
303
+ )
304
+
305
+ @dependency.should_receive(:puts).with(
306
+ /\e\[31mDependency\snot\ssatisfied:\n
307
+ .*dependency\snot\smet.*\n
308
+ .*sorry\smate.*\e\[0m/x
309
+ )
310
+
311
+ @dependency.ensure_dependency_is_satisfied
312
+ end
313
+ end
314
+
315
+ describe "when off" do
316
+ before(:each) do
317
+ Autotest::RunDependencies.colourise_output = false
318
+ end
319
+
320
+ it "outputs the dependency satisfied message with no colour commands" do
321
+ @dependency.should_receive(:puts).with(
322
+ "-> Dependency satisfied\n"
323
+ )
324
+ @dependency.ensure_dependency_is_satisfied
325
+ end
326
+
327
+ it "outputs the dependency not satisfied message and errors with no " +
328
+ "colour commands" do
329
+ @dependency.stub(:`).and_return(
330
+ "failed:\nerror: dependency not met\nerror: sorry mate",
331
+ "success"
332
+ )
333
+ @autotest.stub(:find_files).and_return(
334
+ {'file1' => Time.at(10), 'file2' => Time.at(20)},
335
+ {'file1' => Time.now + 100, 'file2' => Time.at(20)}
336
+ )
337
+
338
+ @dependency.should_receive(:puts).with(
339
+ "-> Dependency not satisfied:\n" +
340
+ " dependency not met\n" +
341
+ " sorry mate"
342
+ )
343
+
344
+ @dependency.ensure_dependency_is_satisfied
345
+ end
346
+ end
347
+ end
348
+
349
+ end
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format specdoc
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(
10
+ File.join(File.dirname(__FILE__), '..', 'lib')
11
+ ) unless
12
+ $:.include?(File.join(File.dirname(__FILE__), '..', 'lib')) ||
13
+ $:.include?(
14
+ File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ )
16
+
17
+ require 'autotest/run_dependencies'
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autotest-run_dependencies
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Toby Clemson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-06 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ZenTest
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 3.9.0
24
+ version:
25
+ description: |
26
+ This gem provides a mechanism through which it is possible to specify that
27
+ an arbitrary number of external dependencies are satisfied before a test
28
+ run can be executed.
29
+
30
+ Dependencies are added by specifying a name, command, satisfied_regexp and
31
+ errors_regexp parameter for each. The command refers to a script that is
32
+ run to satisfy or test the dependency. If the output of the command
33
+ (either to standard output or standard error) matches the satisfied_regexp
34
+ then the dependency is considered met otherwise any lines in the output
35
+ matching errors_regexp are output and the dependency test waits for changes
36
+ to the codebase before trying to satisfy the dependency again.
37
+
38
+ email: tobyclemson@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - LICENSE
45
+ - README.rdoc
46
+ files:
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - lib/autotest-run_dependencies.rb
52
+ - lib/autotest/run_dependencies.rb
53
+ - spec/autotest-run_dependencies_spec.rb
54
+ - spec/spec.opts
55
+ - spec/spec_helper.rb
56
+ has_rdoc: true
57
+ homepage: http://github.com/tobyclemson/autotest-run_dependencies
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=UTF-8
63
+ - --main
64
+ - README.rdoc
65
+ - --title
66
+ - Autotest::RunDependencies RDoc Documentation
67
+ - --line-numbers
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.5
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Test dependencies for autotest.
89
+ test_files:
90
+ - spec/autotest-run_dependencies_spec.rb
91
+ - spec/spec_helper.rb