autotest-run_dependencies 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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