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 +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
|