diff --git a/README.rdoc b/README.rdoc index 4218325..5af74e3 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,9 +1,57 @@ = Hydra -A distributed testing toolkit. +Spread your tests over multiple machines to test your code faster. -Heavily under development and not ready for public use. +== Description + +Hydra is a distributed testing framework. It allows you to distribute +your tests locally across multiple cores and processors, as well as +run your tests remotely over SSH. + +Hydra's goals are to make distributed testing easy. So as long as +you can ssh into a computer and run the tests, you can automate +the distribution with Hydra. + +== Usage + +In your rakefile: + + require 'hydra' + require 'hydra/tasks' + + Hydra::TestTask.new('hydra') do |t| + t.add_files 'test/unit/**/*_test.rb' + t.add_files 'test/functional/**/*_test.rb' + t.add_files 'test/integration/**/*_test.rb' + end + +Then you can run 'rake hydra'. + +== Configuration + +Place the config file in the main project directory as +'hydra.yml' or 'config/hydra.yml'. + + workers: + - type: local + runners: 2 + - type: ssh + connect: user@example.com -p3022 + directory: /absolute/path/to/project + runners: 4 + +The "connect" option is passed to SSH. So if you've setup an +ssh config alias to a server, you can use that. + +The "directory" option is the path for the project directory +where the tests should be run. + +The "runners" option is how many processes will be running +on the remote machine. It's best to pick the same number +as the number of cores on that machine (as well as your +own). == Copyright Copyright (c) 2010 Nick Gauthier. See LICENSE for details. + diff --git a/hydra.gemspec b/hydra.gemspec index d78cb7c..f6db996 100644 --- a/hydra.gemspec +++ b/hydra.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Nick Gauthier"] - s.date = %q{2010-02-05} + s.date = %q{2010-02-06} s.description = %q{Spread your tests over multiple machines to test your code faster.} s.email = %q{nick@smartlogicsolutions.com} s.extra_rdoc_files = [ @@ -40,11 +40,12 @@ Gem::Specification.new do |s| "lib/hydra/safe_fork.rb", "lib/hydra/ssh.rb", "lib/hydra/stdio.rb", + "lib/hydra/tasks.rb", "lib/hydra/trace.rb", "lib/hydra/worker.rb", "test/fixtures/assert_true.rb", "test/fixtures/config.yml", - "test/fixtures/echo_the_dolphin.rb", + "test/fixtures/hello_world.rb", "test/fixtures/slow.rb", "test/fixtures/write_file.rb", "test/master_test.rb", @@ -67,7 +68,7 @@ Gem::Specification.new do |s| "test/fixtures/write_file.rb", "test/fixtures/slow.rb", "test/fixtures/assert_true.rb", - "test/fixtures/echo_the_dolphin.rb", + "test/fixtures/hello_world.rb", "test/master_test.rb", "test/worker_test.rb", "test/runner_test.rb", diff --git a/lib/hydra/tasks.rb b/lib/hydra/tasks.rb new file mode 100644 index 0000000..b6e0d2e --- /dev/null +++ b/lib/hydra/tasks.rb @@ -0,0 +1,76 @@ +module Hydra #:nodoc: + # Define a test task that uses hydra to test the files. + # + # TODO: examples + class TestTask + # Name of the task. Default 'hydra' + attr_accessor :name + + # Files to test. + # You can add files manually via: + # t.files << [file1, file2, etc] + # + # Or you can use the add_files method + attr_accessor :files + + # True if you want to see Hydra's message traces + attr_accessor :verbose + + # Path to the hydra config file. + # If not set, it will check 'hydra.yml' and 'config/hydra.yml' + attr_accessor :config + + # Create a new HydraTestTask + def initialize(name = :hydra) + @name = name + @files = [] + @verbose = false + + yield self if block_given? + + @config = find_config_file + + @opts = { + :verbose => @verbose, + :files => @files + } + if @config + @opts.merge!(:config => @config) + else + $stderr.write "Hydra: No configuration file found at 'hydra.yml' or 'config/hydra.yml'\n" + $stderr.write "Hydra: Using default configuration for a single-core machine\n" + @opts.merge!(:workers => [{:type => :local, :runners => 1}]) + end + + define + end + + # Create the rake task defined by this HydraTestTask + def define + desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}") + task @name do + $stdout.write "Hydra Testing #{files.inspect}\n" + Hydra::Master.new(@opts) + $stdout.write "\nHydra Completed\n" + exit(0) #bypass test on_exit output + end + end + + # Add files to test by passing in a string to be run through Dir.glob. + # For example: + # + # t.add_files 'test/units/*.rb' + def add_files(pattern) + @files += Dir.glob(pattern) + end + + # Search for the hydra config file + def find_config_file + @config ||= 'hydra.yml' + return @config if File.exists?(@config) + @config = File.join('config', 'hydra.yml') + return @config if File.exists?(@config) + @config = nil + end + end +end diff --git a/lib/hydra/worker.rb b/lib/hydra/worker.rb index 94448c3..6854b2e 100644 --- a/lib/hydra/worker.rb +++ b/lib/hydra/worker.rb @@ -91,6 +91,7 @@ module Hydra #:nodoc: @listeners.each{|l| l.join } @io.close trace "Done processing messages" + exit(0) # avoids test summaries end def process_messages_from_master