tork 15.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (the ISC license)
2
+
3
+ Copyright 2010 Suraj N. Kurapati <sunaku@gmail.com>
4
+ Copyright 2011 Brian D. Burns <burns180@gmail.com>
5
+ Copyright 2011 Daniel Pittman <daniel@rimspace.net>
6
+ Copyright 2011 Jacob Helwig <jacob@technosorcery.net>
7
+ Copyright 2011 Corné Verbruggen <corne@g-majeur.nl>
8
+ Copyright 2012 Jose Pablo Barrantes <xjpablobrx@gmail.com>
9
+ Copyright 2012 Spencer Steffen <spencer@citrusme.com>
10
+
11
+ Permission to use, copy, modify, and/or distribute this software for any
12
+ purpose with or without fee is hereby granted, provided that the above
13
+ copyright notice and this permission notice appear in all copies.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,305 @@
1
+ _______ _______
2
+ ___ /___________ /__
3
+ _ __/ __ \ __/ /_/
4
+ / /_/ /_/ / / / ,\
5
+ \__/\____/_/ /_/|_\
6
+ >>>------>
7
+
8
+ _Test with fork_
9
+ ==============================================================================
10
+
11
+ Tork is a continuous testing tool for Ruby that automatically detects and
12
+ tests changes in your Ruby application or test suite in an efficient manner:
13
+
14
+ 1. Absorbs your test execution overhead into a master process.
15
+
16
+ 2. Forks to run your test files in parallel, without overhead.
17
+
18
+ 3. Avoids running unchanged tests inside changed test files.
19
+
20
+ ------------------------------------------------------------------------------
21
+ Features
22
+ ------------------------------------------------------------------------------
23
+
24
+ * Executes test files in parallel, making full use of multi-core CPUs.
25
+
26
+ * Tests *changes* in your Ruby application: avoids running (1) unchanged
27
+ test files and (2) unchanged tests inside changed test files.
28
+
29
+ * Supports MiniTest, Test::Unit, RSpec, and any testing framework that (1)
30
+ reflects failures in the process' exit status and (2) is loaded by your
31
+ application's `test/test_helper.rb` or `spec/spec_helper.rb` file.
32
+
33
+ * Logs the output from your tests into separate files: one log per test.
34
+ The path of a log file is simply the path of its test file plus ".log".
35
+
36
+ * Configurable through a Ruby script in your current working directory.
37
+
38
+ * Implemented in less than 400 lines (SLOC) of pure Ruby code! :-)
39
+
40
+ ------------------------------------------------------------------------------
41
+ Architecture
42
+ ------------------------------------------------------------------------------
43
+
44
+ Following UNIX philosophy, Tork is made of simple text-based programs: thus
45
+ you can build your own custom Tork user interface by wrapping `tork-driver`!
46
+
47
+ * `tork` is an interactive command-line user interface (CLI) for driver
48
+ * `tork-herald` monitors current directory tree and reports changed files
49
+ * `tork-driver` tells master to run tests and keeps track of test results
50
+ * `tork-master` absorbs test execution overhead and forks to run your tests
51
+
52
+ When the herald observes that files in or beneath the current directory have
53
+ been written to, it tells the driver, which then commands the master to fork a
54
+ worker process to run the tests affected by those changed files. This is all
55
+ performed automatically. But what if you want to manually run a test file?
56
+
57
+ You can (re)run any test file by simply saving it! When you do, Tork tries to
58
+ figure out which tests inside your newly saved test file have changed (using
59
+ diff and regexps) and then attempts to run just those. To make it run *all*
60
+ tests in your saved file, simply save the file *again* without changing it.
61
+
62
+ ------------------------------------------------------------------------------
63
+ Prerequisites
64
+ ------------------------------------------------------------------------------
65
+
66
+ * Ruby 1.8.7 or 1.9.2 or newer.
67
+
68
+ * Operating system that supports POSIX signals and the `fork()` system call.
69
+
70
+ To check if your system qualifies, launch `irb` and enter the following:
71
+
72
+ Process.respond_to? :fork # must be true
73
+ Signal.list.key? 'TERM' # must be true
74
+
75
+ ------------------------------------------------------------------------------
76
+ Installation
77
+ ------------------------------------------------------------------------------
78
+
79
+ As a Ruby gem:
80
+
81
+ gem install tork
82
+
83
+ As a Git clone:
84
+
85
+ git clone git://github.com/sunaku/tork
86
+ cd tork
87
+ rake install
88
+
89
+ ------------------------------------------------------------------------------
90
+ Invocation
91
+ ------------------------------------------------------------------------------
92
+
93
+ If installed as a Ruby gem:
94
+
95
+ tork --help
96
+
97
+ If installed as a Git clone:
98
+
99
+ bundle exec ruby -Ilib bin/tork --help
100
+
101
+ You can monitor your test processes in another terminal:
102
+
103
+ watch 'ps xuw | sed -n "1p; /test[r]/p" | fgrep -v sed'
104
+
105
+ You can forcefully terminate Tork from another terminal:
106
+
107
+ pkill -f tork
108
+
109
+ ------------------------------------------------------------------------------
110
+ Configuration
111
+ ------------------------------------------------------------------------------
112
+
113
+ Tork looks for a configuration file named `.tork.rb` in its current working
114
+ directory. The configuration file is a normal Ruby script. Inside it, you
115
+ can query and modify the `Tork::Config` object (OpenStruct) according to the
116
+ configuration options listed below.
117
+
118
+ ### Tork::Config.max_forked_workers
119
+
120
+ Maximum number of worker processes at any given time. The default value is
121
+ the number of processors detected on your system, or 1 if detection fails.
122
+
123
+ ### Tork::Config.overhead_load_paths
124
+
125
+ Array of paths that are prepended to Ruby's `$LOAD_PATH` before the
126
+ test execution overhead is loaded into `tork-master`.
127
+
128
+ ### Tork::Config.overhead_file_globs
129
+
130
+ Array of file globbing patterns that describe a set of Ruby scripts that are
131
+ loaded into `tork-master` as test execution overhead.
132
+
133
+ ### Tork::Config.reabsorb_file_greps
134
+
135
+ Array of regular expressions that describe a set of file paths that cause the
136
+ test execution overhead to be reabsorbed in `tork-master` when they change.
137
+
138
+ ### Tork::Config.all_test_file_globs
139
+
140
+ Array of file globbing patterns that describe the set of all test files in
141
+ your Ruby application.
142
+
143
+ ### Tork::Config.test_file_globbers
144
+
145
+ Hash that maps (1) a regular expression describing a set of file paths to (2)
146
+ a lambda function yielding a file globbing pattern describing a set of
147
+ test files that need to be run. In other words, whenever the source files
148
+ (the hash key; left-hand side of the mapping) change, their associated test
149
+ files (the hash value; right-hand side of the mapping) are run.
150
+
151
+ For example, if test files had the same names as their source files followed
152
+ by an underscore and the file name in reverse like this:
153
+
154
+ * `lib/hello.rb` => `test/hello_olleh.rb`
155
+ * `app/world.rb` => `spec/world_ldrow.rb`
156
+
157
+ Then you would add the following to your configuration file:
158
+
159
+ Tork::Config.test_file_globbers[%r<^(lib|app)/.+\.rb$>] = lambda do |path|
160
+ name = File.basename(path, '.rb')
161
+ "{test,spec}/**/#{name}_#{name.reverse}.rb"
162
+ end
163
+
164
+ In addition, these lambda functions can return `nil` if they do not wish for a
165
+ particular source file to be tested. For example, to ignore tests for all
166
+ source files except those within a `models/` directory, you would write:
167
+
168
+ Tork::Config.test_file_globbers[%r<^(lib|app)/.+\.rb$>] = lambda do |path|
169
+ if path.include? '/models/'
170
+ "{test,spec}/**/#{File.basename(path)}"
171
+ end
172
+ end
173
+
174
+ ### Tork::Config.test_name_extractor
175
+
176
+ Lambda function that is given a line of source code to determine whether it
177
+ can be considered as a test definition. In which case, the function must
178
+ extract and return the name of the test being defined.
179
+
180
+ ### Tork::Config.before_fork_hooks
181
+
182
+ Array of lambda functions that are executed inside `tork-master` before a
183
+ worker process is forked to run a test file. These functions are given:
184
+
185
+ 1. The sequence number of the worker process that will be forked shortly.
186
+
187
+ 2. The path of the log file containing the live output of the worker process.
188
+
189
+ 3. The path of the test file that will be run by the worker process.
190
+
191
+ 4. An array of names of tests inside the test file that will be run. If this
192
+ array is empty, then all tests in the test file will be run.
193
+
194
+ For example, to see some real values:
195
+
196
+ Tork::Config.before_fork_hooks << lambda do |worker_number, log_file, test_file, test_names|
197
+ p :before_fork_hooks => {
198
+ :worker_number => worker_number,
199
+ :log_file => log_file,
200
+ :test_file => test_file,
201
+ :test_names => test_names,
202
+ }
203
+ end
204
+
205
+ ### Tork::Config.after_fork_hooks
206
+
207
+ Array of lambda functions that are executed inside a worker process forked
208
+ by `tork-master`. These functions are given:
209
+
210
+ 1. The sequence number of the worker process.
211
+
212
+ 2. The path of the log file containing the live output of the worker process.
213
+
214
+ 3. The path of the test file that will be run by the worker process.
215
+
216
+ 4. An array of names of tests inside the test file that will be run. If this
217
+ array is empty, then all tests in the test file will be run.
218
+
219
+ For example, to see some real values, including the worker process' PID:
220
+
221
+ Tork::Config.after_fork_hooks << lambda do |worker_number, log_file, test_file, test_names|
222
+ p :after_fork_hooks => {
223
+ :worker_pid => $$,
224
+ :worker_number => worker_number,
225
+ :log_file => log_file,
226
+ :test_file => test_file,
227
+ :test_names => test_names,
228
+ }
229
+ end
230
+
231
+ The first function in this array instructs Test::Unit and RSpec to only run
232
+ those tests that correspond to the given `test_names` values. This
233
+ accelerates your test-driven development cycle and improves productivity!
234
+
235
+ ------------------------------------------------------------------------------
236
+ Configuration helpers
237
+ ------------------------------------------------------------------------------
238
+
239
+ The following libraries assist you with configuring Tork. To use them,
240
+ simply add the `require()` lines shown below to your configuration file
241
+ *or* pass their basenames to the tork(1) command, also as shown below.
242
+
243
+ ### require 'tork/config/rails' # tork rails
244
+
245
+ Support for the [Ruby on Rails] web framework.
246
+
247
+ ### require 'tork/config/parallel_tests' # tork parallel_tests
248
+
249
+ Support for the [parallel_tests] library.
250
+
251
+ ------------------------------------------------------------------------------
252
+ Usage tips
253
+ ------------------------------------------------------------------------------
254
+
255
+ ### [factory_girl] factories
256
+
257
+ Don't load your factories in master process (as part of your test execution
258
+ overhead) because that would necessitate the reloading of said overhead
259
+ whenever you change an existing factory definition or create a new one.
260
+
261
+ Instead, use `at_exit()` to wait until (1) after the master process has forked
262
+ a worker process and (2) just before that worker process runs its test suite
263
+ (whose execution is started by your test framework's own `at_exit()` handler):
264
+
265
+ require 'factory_girl'
266
+ at_exit { FactoryGirl.find_definitions unless $! }
267
+
268
+ This way, worker processes will pick up changes in your factories "for free"
269
+ whenever they (re)run your test files. Also, don't load your factories or do
270
+ anything else in your `at_exit()` handler if Ruby is exiting because of a
271
+ raised exception (denoted by the `$!` global variable in the snippet above).
272
+
273
+ ------------------------------------------------------------------------------
274
+ Known issues
275
+ ------------------------------------------------------------------------------
276
+
277
+ ### Ruby on Rails
278
+
279
+ * Ensure that your `config/environments/test.rb` file disables class caching
280
+ as follows (**NOTE:** if you are using Rails 3, the `tork/config/rails`
281
+ configuration helper can do this for you automatically):
282
+
283
+ config.cache_classes = false
284
+
285
+ Otherwise, Tork will appear to ignore source-code changes in your
286
+ models, controllers, helpers, and other Ruby source files.
287
+
288
+ * If SQLite3 raises one of the following errors, try using an [in-memory
289
+ adapter for SQLite3][memory_test_fix] or use different database software
290
+ (such as MySQL) for your test environment.
291
+
292
+ * SQLite3::BusyException: database is locked
293
+
294
+ * cannot start a transaction within a transaction
295
+
296
+ ------------------------------------------------------------------------------
297
+ License
298
+ ------------------------------------------------------------------------------
299
+
300
+ Released under the ISC license. See the LICENSE file for details.
301
+
302
+ [factory_girl]: https://github.com/thoughtbot/factory_girl
303
+ [memory_test_fix]: https://github.com/mvz/memory_test_fix
304
+ [parallel_tests]: https://github.com/grosser/parallel_tests
305
+ [Ruby on Rails]: http://rubyonrails.org
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ require "binman/rakefile"
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ =begin
3
+
4
+ TORK 1 2012-01-23 15.0.0
5
+ ==============================================================================
6
+
7
+ NAME
8
+ ------------------------------------------------------------------------------
9
+
10
+ tork - Continuous testing tool for Ruby
11
+
12
+ SYNOPSIS
13
+ ------------------------------------------------------------------------------
14
+
15
+ `tork` [*OPTION*]... [*CONFIG*]...
16
+
17
+ DESCRIPTION
18
+ ------------------------------------------------------------------------------
19
+
20
+ This program is a simple command-line user interface for tork-driver(1). It
21
+ loads the given *CONFIG* files (which are either paths to actual files or
22
+ names of helper libraries in the tork/config/ namespace of Ruby's load path)
23
+ and then waits for you to supply interactive commands on its stdin. You may
24
+ press the ENTER key (supplying no command) to see a menu of accepted commands.
25
+
26
+ OPTIONS
27
+ ------------------------------------------------------------------------------
28
+
29
+ `-h`, `--help`
30
+ Display this help manual using man(1).
31
+
32
+ SEE ALSO
33
+ ------------------------------------------------------------------------------
34
+
35
+ tork(1), tork-driver(1), tork-master(1), tork-herald(1)
36
+
37
+ =end =========================================================================
38
+
39
+ $0 = File.basename(__FILE__) # for easier indentification in ps(1) output
40
+
41
+ require 'binman'
42
+ BinMan.help
43
+
44
+ require 'json'
45
+ ENV['TORK_CONFIGS'] = JSON.dump(ARGV)
46
+
47
+ #-----------------------------------------------------------------------------
48
+ # backend
49
+ #-----------------------------------------------------------------------------
50
+
51
+ require 'tork/client'
52
+
53
+ warn 'tork: Absorbing test execution overhead...'
54
+ @driver = Tork::Client::Transceiver.new('tork-driver') do |line|
55
+ evstr, *details = JSON.load(line)
56
+ event = evstr.to_sym
57
+
58
+ case event
59
+ when :load then warn 'tork: Overhead absorbed. Ready for testing!'
60
+ when :over then warn 'tork: Reabsorbing changed overhead files...'
61
+ else
62
+ test_file, test_names, *details = details
63
+ message = [evstr.upcase, test_file, test_names.inspect, details].join(' ')
64
+
65
+ color = case event
66
+ when :pass then "\e[34m%s\e[0m" # blue
67
+ when :fail then "\e[31m%s\e[0m" # red
68
+ end
69
+ message = color % message if color and STDOUT.tty?
70
+ message = [message, File.read(test_file + '.log'), message] if event == :fail
71
+
72
+ puts message
73
+ end
74
+ end
75
+
76
+ #-----------------------------------------------------------------------------
77
+ # frontend
78
+ #-----------------------------------------------------------------------------
79
+
80
+ COMMANDS = {
81
+ 't' => :run_all_test_files,
82
+ 's' => :stop_running_test_files,
83
+ 'p' => :rerun_passed_test_files,
84
+ 'f' => :rerun_failed_test_files,
85
+ 'o' => :reabsorb_overhead_files,
86
+ 'q' => :quit,
87
+ }
88
+
89
+ begin
90
+ while key = STDIN.gets.chomp
91
+ if command = COMMANDS[key]
92
+ warn "tork: Sending #{command.to_s.inspect} command..."
93
+ @driver.send [command]
94
+ break if command == :quit
95
+ else # invalid command
96
+ COMMANDS.each do |key, command|
97
+ warn "tork: Type #{key} then ENTER to #{command.to_s.tr('_', ' ')}."
98
+ end
99
+ end
100
+ end
101
+ rescue Interrupt
102
+ # forced quit
103
+ end
104
+
105
+ Process.waitall
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ =begin
3
+
4
+ TORK-DRIVER 1 2012-01-23 15.0.0
5
+ ==============================================================================
6
+
7
+ NAME
8
+ ------------------------------------------------------------------------------
9
+
10
+ tork-driver - drives tork-master(1) and does bookkeeping
11
+
12
+ SYNOPSIS
13
+ ------------------------------------------------------------------------------
14
+
15
+ `tork-driver` [*OPTION*]...
16
+
17
+ DESCRIPTION
18
+ ------------------------------------------------------------------------------
19
+
20
+ This program reads the following single-line commands (JSON arrays) from its
21
+ standard input stream and performs the respective actions as described below.
22
+ It also funnels the standard output stream of tork-master(1) into its own.
23
+
24
+ `["run_all_test_files"]`
25
+ Runs all test files found within and beneath the current working directory.
26
+
27
+ `["stop_running_test_files"]`
28
+ Stops any test files that are currently running.
29
+
30
+ `["rerun_passed_test_files"]`
31
+ Runs all test files that have passed during their most recent run.
32
+
33
+ `["reabsorb_overhead_files"]`
34
+ Stops any test files that are currently running, reabsorbs the test
35
+ execution overhead, and resumes running those interrupted test files.
36
+
37
+ `["quit"]`
38
+ Stops all tests that are currently running and exits.
39
+
40
+ When tork-herald(1) reports that a file belonging to the test execution
41
+ overhead has been modified, this program replaces tork-master(1) with a new
42
+ instance, which then absorbs the modified test execution overhead into itself.
43
+
44
+ This program emits the following single-line status messages (JSON arrays) on
45
+ its standard output stream to provide notifications about its activity:
46
+
47
+ `["over",` *overhead_file*`]`
48
+ The test execution overhead is currently being reabsorbed, by replacing
49
+ tork-master(1) with a new instance, because *overhead_file* has changed.
50
+
51
+ OPTIONS
52
+ ------------------------------------------------------------------------------
53
+
54
+ `-h`, `--help`
55
+ Display this help manual using man(1).
56
+
57
+ FILES
58
+ ------------------------------------------------------------------------------
59
+
60
+ *.tork.rb*
61
+ Optional Ruby script for configuring tork(1).
62
+
63
+ ENVIRONMENT
64
+ ------------------------------------------------------------------------------
65
+
66
+ `TORK_CONFIGS`
67
+ A single-line JSON array containing paths to actual files or names of
68
+ helper libraries in the tork/config/ namespace of Ruby's load path.
69
+ These configuration files are loaded just before *.tork.rb* is loaded.
70
+
71
+ SEE ALSO
72
+ ------------------------------------------------------------------------------
73
+
74
+ tork(1), tork-driver(1), tork-master(1), tork-herald(1)
75
+
76
+ =end =========================================================================
77
+
78
+ $0 = File.basename(__FILE__) # for easier indentification in ps(1) output
79
+
80
+ require 'binman'
81
+ BinMan.help
82
+
83
+ require 'tork/driver'
84
+ Tork::Driver.loop
85
+
86
+ Process.waitall