nitra 0.9.1

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.
Files changed (4) hide show
  1. data/README +3 -0
  2. data/bin/nitra +4 -0
  3. data/lib/nitra.rb +129 -0
  4. metadata +69 -0
data/README ADDED
@@ -0,0 +1,3 @@
1
+ Nitra is a multi-process rspec runner.
2
+
3
+ Copyright 2011 Powershop Limited, YouDo Limited. MIT licence.
data/bin/nitra ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'nitra'
4
+ Nitra.new.run
data/lib/nitra.rb ADDED
@@ -0,0 +1,129 @@
1
+ class Nitra
2
+ def run
3
+ start_time = Time.now
4
+ ENV["RAILS_ENV"] = "nitra"
5
+
6
+ process_count = 4
7
+ debug = false
8
+
9
+ if false
10
+ process_count.times do |index|
11
+ puts "initialising database #{index+1}..."
12
+ ENV["TEST_ENV_NUMBER"] = (index + 1).to_s
13
+ system("bundle exec rake db:schema:load")
14
+ end
15
+ end
16
+
17
+ puts "loading rails environment..." if debug
18
+
19
+ ENV["TEST_ENV_NUMBER"] = "1"
20
+
21
+ require 'config/environment'
22
+ require 'rspec'
23
+ require 'stringio'
24
+
25
+ ActiveRecord::Base.connection.disconnect!
26
+
27
+ trap("SIGINT") { Process.kill("SIGKILL", Process.pid) }
28
+
29
+ pipes = (0...process_count).collect do |index|
30
+ server_sender_pipe = IO.pipe
31
+ client_sender_pipe = IO.pipe
32
+ fork do
33
+ server_sender_pipe[1].close
34
+ client_sender_pipe[0].close
35
+ rd = server_sender_pipe[0]
36
+ wr = client_sender_pipe[1]
37
+
38
+ ENV["TEST_ENV_NUMBER"] = (index + 1).to_s
39
+
40
+ database_config = YAML.load(ERB.new(IO.read("#{Rails.root}/config/database.yml")).result)[ENV["RAILS_ENV"]]
41
+ ActiveRecord::Base.establish_connection(database_config)
42
+ Rails.cache.reset if Rails.cache.respond_to?(:reset)
43
+
44
+ puts "announcing availability" if debug
45
+ wr.write("0\n")
46
+
47
+ io = StringIO.new
48
+ loop do
49
+ puts "#{index} waiting for next job" if debug
50
+ filename = rd.gets
51
+ exit if filename.blank?
52
+ filename = filename.chomp
53
+ puts "#{index} starting to process #{filename}" if debug
54
+
55
+ RSpec::Core::CommandLine.new(["-f", "p", filename]).run(io, io)
56
+ RSpec.reset
57
+
58
+ wr.write("#{io.string.length}\n#{io.string}")
59
+ io.string = ""
60
+ end
61
+ end
62
+ server_sender_pipe[0].close
63
+ client_sender_pipe[1].close
64
+ [client_sender_pipe[0], server_sender_pipe[1]]
65
+ end
66
+
67
+ readers = pipes.collect(&:first)
68
+ files = Dir["spec/**/*_spec.rb"]
69
+
70
+ return if files.empty?
71
+
72
+ puts "Running rspec on #{files.length} files spread across #{process_count} processes\n\n"
73
+
74
+ @columns = (ENV['COLUMNS'] || 120).to_i
75
+ @file_count = files.length
76
+ @files_completed = 0
77
+ @example_count = 0
78
+ @failure_count = 0
79
+
80
+ result = ""
81
+ while readers.length > 0
82
+ print_progress
83
+ fds = IO.select(readers)
84
+ fds.first.each do |fd|
85
+ length = fd.gets
86
+
87
+ if length.nil?
88
+ break
89
+ elsif length.to_i > 0
90
+ data = fd.read(length.to_i)
91
+
92
+ @files_completed += 1
93
+ if m = data.match(/(\d+) examples?, (\d+) failure/)
94
+ @example_count += m[1].to_i
95
+ @failure_count += m[2].to_i
96
+ end
97
+
98
+ result << data.gsub(/^[.FP]+$/, '').gsub(/\nFailed examples:.+/m, '').gsub(/^Finished in.+$/, '').gsub(/^\d+ example.+$/, '').gsub(/^No examples found.$/, '').gsub(/^Failures:$/, '')
99
+ else
100
+ puts "ZERO LENGTH" if debug
101
+ end
102
+
103
+ wr = pipes.detect {|rd, wr| rd == fd}[1]
104
+ if files.length.zero?
105
+ wr.puts ""
106
+ readers.delete(fd)
107
+ else
108
+ puts "master is sending #{files.first} to fd #{wr}" if debug
109
+ wr.puts files.shift
110
+ end
111
+ end
112
+ end
113
+
114
+ print_progress
115
+ puts ""
116
+ result = result.gsub(/\n\n\n+/, "\n\n")
117
+ puts result
118
+ puts "\nFinished in #{"%0.1f" % (Time.now-start_time)} seconds"
119
+ end
120
+
121
+ protected
122
+ def print_progress
123
+ bar_length = @columns - 50
124
+ progress = @files_completed / @file_count.to_f
125
+ length_completed = (progress * bar_length).to_i
126
+ length_to_go = bar_length - length_completed
127
+ print "[#{"X" * length_completed}#{"." * length_to_go}] #{@files_completed}/#{@file_count} (#{"%0.1f%%" % (progress*100)}) * #{@example_count} examples, #{@failure_count} failures\r"
128
+ end
129
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nitra
3
+ version: !ruby/object:Gem::Version
4
+ hash: 57
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 1
10
+ version: 0.9.1
11
+ platform: ruby
12
+ authors:
13
+ - Roger Nesbitt
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-22 00:00:00 +13:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Multi-process rspec runner
23
+ email: roger@youdo.co.nz
24
+ executables:
25
+ - nitra
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - README
32
+ - lib/nitra.rb
33
+ - bin/nitra
34
+ has_rdoc: true
35
+ homepage:
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.5.3
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Multi-process rspec runner
68
+ test_files: []
69
+