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 +22 -0
- data/README.rdoc +130 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/lib/autotest-run_dependencies.rb +11 -0
- data/lib/autotest/run_dependencies.rb +214 -0
- data/spec/autotest-run_dependencies_spec.rb +349 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +17 -0
- metadata +91 -0
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.
|
data/README.rdoc
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|