parallelized_specs 0.0.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.
- data/Gemfile +10 -0
- data/Gemfile.lock +30 -0
- data/Rakefile +21 -0
- data/Readme.md +240 -0
- data/VERSION +1 -0
- data/bin/parallel_spec +2 -0
- data/bin/parallel_test +97 -0
- data/lib/parallel_specs/spec_error_count_logger.rb +30 -0
- data/lib/parallel_specs/spec_error_logger.rb +45 -0
- data/lib/parallel_specs/spec_failures_logger.rb +43 -0
- data/lib/parallel_specs/spec_logger_base.rb +56 -0
- data/lib/parallel_specs/spec_runtime_logger.rb +34 -0
- data/lib/parallel_specs/spec_start_finish_logger.rb +38 -0
- data/lib/parallel_specs/spec_summary_logger.rb +19 -0
- data/lib/parallel_specs.rb +52 -0
- data/lib/parallel_tests/grouper.rb +49 -0
- data/lib/parallel_tests/railtie.rb +10 -0
- data/lib/parallel_tests/runtime_logger.rb +78 -0
- data/lib/parallel_tests/tasks.rb +80 -0
- data/lib/parallel_tests.rb +163 -0
- data/lib/tasks/parallel_tests.rake +1 -0
- data/parallelized_specs.gemspec +64 -0
- data/spec/integration_spec.rb +133 -0
- data/spec/parallel_specs/spec_failure_logger_spec.rb +82 -0
- data/spec/parallel_specs/spec_runtime_logger_spec.rb +76 -0
- data/spec/parallel_specs/spec_summary_logger_spec.rb +33 -0
- data/spec/parallel_specs_spec.rb +165 -0
- data/spec/parallel_tests/runtime_logger_spec.rb +74 -0
- data/spec/parallel_tests_spec.rb +229 -0
- data/spec/spec_helper.rb +149 -0
- metadata +109 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'parallel'
|
2
|
+
require 'parallel_tests/grouper'
|
3
|
+
require 'parallel_tests/railtie'
|
4
|
+
|
5
|
+
class ParallelTests
|
6
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
7
|
+
|
8
|
+
# parallel:spec[:count, :pattern, :options]
|
9
|
+
def self.parse_rake_args(args)
|
10
|
+
# order as given by user
|
11
|
+
args = [args[:count], args[:pattern], args[:options]]
|
12
|
+
|
13
|
+
# count given or empty ?
|
14
|
+
# parallel:spec[2,models,options]
|
15
|
+
# parallel:spec[,models,options]
|
16
|
+
count = args.shift if args.first.to_s =~ /^\d*$/
|
17
|
+
num_processes = count.to_i unless count.to_s.empty?
|
18
|
+
num_processes ||= ENV['PARALLEL_TEST_PROCESSORS'].to_i if ENV['PARALLEL_TEST_PROCESSORS']
|
19
|
+
num_processes ||= Parallel.processor_count
|
20
|
+
|
21
|
+
pattern = args.shift
|
22
|
+
options = args.shift
|
23
|
+
|
24
|
+
[num_processes.to_i, pattern.to_s, options.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
# finds all tests and partitions them into groups
|
28
|
+
def self.tests_in_groups(root, num_groups, options={})
|
29
|
+
tests = find_tests(root, options)
|
30
|
+
if options[:no_sort] == true
|
31
|
+
Grouper.in_groups(tests, num_groups)
|
32
|
+
else
|
33
|
+
tests = with_runtime_info(tests)
|
34
|
+
Grouper.in_even_groups_by_size(tests, num_groups, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.run_tests(test_files, process_number, options)
|
39
|
+
require_list = test_files.map { |filename| %{"#{File.expand_path filename}"} }.join(",")
|
40
|
+
cmd = "ruby -Itest -e '[#{require_list}].each {|f| require f }' -- #{options[:test_options]}"
|
41
|
+
execute_command(cmd, process_number, options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.execute_command(cmd, process_number, options)
|
45
|
+
cmd = "TEST_ENV_NUMBER=#{test_env_number(process_number)} ; export TEST_ENV_NUMBER; #{cmd}"
|
46
|
+
f = open("|#{cmd}", 'r')
|
47
|
+
output = fetch_output(f, options)
|
48
|
+
f.close
|
49
|
+
{:stdout => output, :exit_status => $?.exitstatus}
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.find_results(test_output)
|
53
|
+
test_output.split("\n").map {|line|
|
54
|
+
line = line.gsub(/\.|F|\*/,'')
|
55
|
+
next unless line_is_result?(line)
|
56
|
+
line
|
57
|
+
}.compact
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.test_env_number(process_number)
|
61
|
+
process_number == 0 ? '' : process_number + 1
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.runtime_log
|
65
|
+
'tmp/parallel_runtime_test.log'
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.summarize_results(results)
|
69
|
+
results = results.join(' ').gsub(/s\b/,'') # combine and singularize results
|
70
|
+
counts = results.scan(/(\d+) (\w+)/)
|
71
|
+
sums = counts.inject(Hash.new(0)) do |sum, (number, word)|
|
72
|
+
sum[word] += number.to_i
|
73
|
+
sum
|
74
|
+
end
|
75
|
+
sums.sort.map{|word, number| "#{number} #{word}#{'s' if number != 1}" }.join(', ')
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
# read output of the process and print in in chucks
|
81
|
+
def self.fetch_output(process, options)
|
82
|
+
all = ''
|
83
|
+
buffer = ''
|
84
|
+
timeout = options[:chunk_timeout] || 0.2
|
85
|
+
flushed = Time.now.to_f
|
86
|
+
|
87
|
+
while char = process.getc
|
88
|
+
char = (char.is_a?(Fixnum) ? char.chr : char) # 1.8 <-> 1.9
|
89
|
+
all << char
|
90
|
+
|
91
|
+
# print in chunks so large blocks stay together
|
92
|
+
now = Time.now.to_f
|
93
|
+
buffer << char
|
94
|
+
if flushed + timeout < now
|
95
|
+
print buffer
|
96
|
+
STDOUT.flush
|
97
|
+
buffer = ''
|
98
|
+
flushed = now
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# print the remainder
|
103
|
+
print buffer
|
104
|
+
STDOUT.flush
|
105
|
+
|
106
|
+
all
|
107
|
+
end
|
108
|
+
|
109
|
+
# copied from http://github.com/carlhuda/bundler Bundler::SharedHelpers#find_gemfile
|
110
|
+
def self.bundler_enabled?
|
111
|
+
return true if Object.const_defined?(:Bundler)
|
112
|
+
|
113
|
+
previous = nil
|
114
|
+
current = File.expand_path(Dir.pwd)
|
115
|
+
|
116
|
+
until !File.directory?(current) || current == previous
|
117
|
+
filename = File.join(current, "Gemfile")
|
118
|
+
return true if File.exists?(filename)
|
119
|
+
current, previous = File.expand_path("..", current), current
|
120
|
+
end
|
121
|
+
|
122
|
+
false
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.line_is_result?(line)
|
126
|
+
line =~ /\d+ failure/
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.test_suffix
|
130
|
+
"_test.rb"
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.with_runtime_info(tests)
|
134
|
+
lines = File.read(runtime_log).split("\n") rescue []
|
135
|
+
|
136
|
+
# use recorded test runtime if we got enough data
|
137
|
+
if lines.size * 1.5 > tests.size
|
138
|
+
puts "Using recorded test runtime"
|
139
|
+
times = Hash.new(1)
|
140
|
+
lines.each do |line|
|
141
|
+
test, time = line.split(":")
|
142
|
+
next unless test and time
|
143
|
+
times[File.expand_path(test)] = time.to_f
|
144
|
+
end
|
145
|
+
tests.sort.map{|test| [test, times[test]] }
|
146
|
+
else # use file sizes
|
147
|
+
tests.sort.map{|test| [test, File.stat(test).size] }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.find_tests(root, options={})
|
152
|
+
if root.is_a?(Array)
|
153
|
+
root
|
154
|
+
else
|
155
|
+
# follow one symlink and direct children
|
156
|
+
# http://stackoverflow.com/questions/357754/can-i-traverse-symlinked-directories-in-ruby-with-a-glob
|
157
|
+
files = Dir["#{root}/**{,/*/**}/*#{test_suffix}"].uniq
|
158
|
+
files = files.map{|f| f.sub(root+'/','') }
|
159
|
+
files = files.grep(/#{options[:pattern]}/)
|
160
|
+
files.map{|f| "#{root}/#{f}" }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "/../parallel_tests/tasks")
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "parallelized_specs"
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jake Sorce, Bryan Madsen"]
|
12
|
+
s.date = "2012-04-17"
|
13
|
+
s.email = "jake@instructure.com"
|
14
|
+
s.executables = ["parallel_test", "parallel_spec"]
|
15
|
+
s.files = [
|
16
|
+
"Gemfile",
|
17
|
+
"Gemfile.lock",
|
18
|
+
"Rakefile",
|
19
|
+
"Readme.md",
|
20
|
+
"VERSION",
|
21
|
+
"bin/parallel_spec",
|
22
|
+
"bin/parallel_test",
|
23
|
+
"lib/parallel_specs.rb",
|
24
|
+
"lib/parallel_specs/spec_error_count_logger.rb",
|
25
|
+
"lib/parallel_specs/spec_error_logger.rb",
|
26
|
+
"lib/parallel_specs/spec_failures_logger.rb",
|
27
|
+
"lib/parallel_specs/spec_logger_base.rb",
|
28
|
+
"lib/parallel_specs/spec_runtime_logger.rb",
|
29
|
+
"lib/parallel_specs/spec_start_finish_logger.rb",
|
30
|
+
"lib/parallel_specs/spec_summary_logger.rb",
|
31
|
+
"lib/parallel_tests.rb",
|
32
|
+
"lib/parallel_tests/grouper.rb",
|
33
|
+
"lib/parallel_tests/railtie.rb",
|
34
|
+
"lib/parallel_tests/runtime_logger.rb",
|
35
|
+
"lib/parallel_tests/tasks.rb",
|
36
|
+
"lib/tasks/parallel_tests.rake",
|
37
|
+
"parallelized_specs.gemspec",
|
38
|
+
"spec/integration_spec.rb",
|
39
|
+
"spec/parallel_specs/spec_failure_logger_spec.rb",
|
40
|
+
"spec/parallel_specs/spec_runtime_logger_spec.rb",
|
41
|
+
"spec/parallel_specs/spec_summary_logger_spec.rb",
|
42
|
+
"spec/parallel_specs_spec.rb",
|
43
|
+
"spec/parallel_tests/runtime_logger_spec.rb",
|
44
|
+
"spec/parallel_tests_spec.rb",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
s.homepage = "http://github.com/jake/parallelized_specs"
|
48
|
+
s.require_paths = ["lib"]
|
49
|
+
s.rubygems_version = "1.8.22"
|
50
|
+
s.summary = "Run rspec tests in parallel"
|
51
|
+
|
52
|
+
if s.respond_to? :specification_version then
|
53
|
+
s.specification_version = 3
|
54
|
+
|
55
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_runtime_dependency(%q<parallel>, [">= 0"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<parallel>, [">= 0"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<parallel>, [">= 0"])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'CLI' do
|
4
|
+
before do
|
5
|
+
`rm -rf #{folder}`
|
6
|
+
end
|
7
|
+
|
8
|
+
after do
|
9
|
+
`rm -rf #{folder}`
|
10
|
+
end
|
11
|
+
|
12
|
+
def folder
|
13
|
+
"/tmp/parallel_tests_tests"
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(file, content)
|
17
|
+
path = "#{folder}/#{file}"
|
18
|
+
`mkdir -p #{File.dirname(path)}` unless File.exist?(File.dirname(path))
|
19
|
+
File.open(path, 'w'){|f| f.write content }
|
20
|
+
path
|
21
|
+
end
|
22
|
+
|
23
|
+
def bin_folder
|
24
|
+
"#{File.expand_path(File.dirname(__FILE__))}/../bin"
|
25
|
+
end
|
26
|
+
|
27
|
+
def executable
|
28
|
+
"#{bin_folder}/parallel_test"
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_tests(options={})
|
32
|
+
`cd #{folder} && #{executable} --chunk-timeout 999 -t #{options[:type] || 'spec'} -n #{options[:processes]||2} #{options[:add]} 2>&1`
|
33
|
+
end
|
34
|
+
|
35
|
+
it "runs tests in parallel" do
|
36
|
+
write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}'
|
37
|
+
write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){puts "TEST2"}}'
|
38
|
+
result = run_tests
|
39
|
+
|
40
|
+
# test ran and gave their puts
|
41
|
+
result.should include('TEST1')
|
42
|
+
result.should include('TEST2')
|
43
|
+
|
44
|
+
# all results present
|
45
|
+
result.scan('1 example, 0 failure').size.should == 2 # 2 results
|
46
|
+
result.scan('2 examples, 0 failures').size.should == 1 # 1 summary
|
47
|
+
result.scan(/Finished in \d+\.\d+ seconds/).size.should == 2
|
48
|
+
result.scan(/Took \d+\.\d+ seconds/).size.should == 1 # parallel summary
|
49
|
+
$?.success?.should == true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does not run any tests if there are none" do
|
53
|
+
write 'spec/xxx.rb', 'xxx'
|
54
|
+
result = run_tests
|
55
|
+
result.should include('No examples found')
|
56
|
+
result.should include('Took')
|
57
|
+
end
|
58
|
+
|
59
|
+
it "fails when tests fail" do
|
60
|
+
write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}'
|
61
|
+
write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}'
|
62
|
+
result = run_tests
|
63
|
+
|
64
|
+
result.scan('1 example, 1 failure').size.should == 1
|
65
|
+
result.scan('1 example, 0 failure').size.should == 1
|
66
|
+
result.scan('2 examples, 1 failure').size.should == 1
|
67
|
+
$?.success?.should == false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can exec given commands with ENV['TEST_ENV_NUM']" do
|
71
|
+
result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4`
|
72
|
+
result.gsub('"','').split('').sort.should == %w[0 2 3 4]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "can exec given command non-parallel" do
|
76
|
+
result = `#{executable} -e 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"' -n 4 --non-parallel`
|
77
|
+
result.split("\n").should == %w["" "2" "3" "4"]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "exists with success if all sub-processes returned success" do
|
81
|
+
system("#{executable} -e 'cat /dev/null' -n 4").should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "exists with failure if any sub-processes returned failure" do
|
85
|
+
system("#{executable} -e 'test -e xxxx' -n 4").should == false
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can run through parallel_spec / parallel_cucumber" do
|
89
|
+
version = `#{executable} -v`
|
90
|
+
`#{bin_folder}/parallel_spec -v`.should == version
|
91
|
+
`#{bin_folder}/parallel_cucumber -v`.should == version
|
92
|
+
end
|
93
|
+
|
94
|
+
it "runs faster with more processes" do
|
95
|
+
2.times{|i|
|
96
|
+
write "spec/xxx#{i}_spec.rb", 'describe("it"){it("should"){sleep 5}}; $stderr.puts ENV["TEST_ENV_NUMBER"]'
|
97
|
+
}
|
98
|
+
t = Time.now
|
99
|
+
run_tests(:processes => 2)
|
100
|
+
expected = 10
|
101
|
+
(Time.now - t).should <= expected
|
102
|
+
end
|
103
|
+
|
104
|
+
it "can can with given files" do
|
105
|
+
write "spec/x1_spec.rb", "puts '111'"
|
106
|
+
write "spec/x2_spec.rb", "puts '222'"
|
107
|
+
write "spec/x3_spec.rb", "puts '333'"
|
108
|
+
result = run_tests(:add => 'spec/x1_spec.rb spec/x3_spec.rb')
|
109
|
+
result.should include('111')
|
110
|
+
result.should include('333')
|
111
|
+
result.should_not include('222')
|
112
|
+
end
|
113
|
+
|
114
|
+
it "can run with test-options" do
|
115
|
+
write "spec/x1_spec.rb", ""
|
116
|
+
write "spec/x2_spec.rb", ""
|
117
|
+
result = run_tests(:add => "--test-options ' --version'", :processes => 2)
|
118
|
+
result.should =~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/m # prints version twice
|
119
|
+
end
|
120
|
+
|
121
|
+
it "runs with test::unit" do
|
122
|
+
write "test/x1_test.rb", "require 'test/unit'; class XTest < Test::Unit::TestCase; def test_xxx; end; end"
|
123
|
+
result = run_tests(:type => :test)
|
124
|
+
result.should include('1 test')
|
125
|
+
$?.success?.should == true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "passes test options to test::unit" do
|
129
|
+
write "test/x1_test.rb", "require 'test/unit'; class XTest < Test::Unit::TestCase; def test_xxx; end; end"
|
130
|
+
result = run_tests(:type => :test, :add => '--test-options "-v"')
|
131
|
+
result.should include('test_xxx') # verbose output of every test
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ParallelSpecs::SpecFailuresLogger do
|
4
|
+
def silence_warnings
|
5
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
6
|
+
yield
|
7
|
+
ensure
|
8
|
+
$VERBOSE = old_verbose
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
@output = OutputLogger.new([])
|
13
|
+
@example1 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example:123", :full_description => 'should do stuff', :description => 'd' )
|
14
|
+
@example2 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example2:456", :full_description => 'should do other stuff', :description => 'd')
|
15
|
+
@exception1 = mock( :to_s => 'exception', :backtrace => [ '/path/to/error/line:33' ] )
|
16
|
+
@failure1 = mock( 'example', :location => "#{Dir.pwd}/example:123", :header => 'header', :exception => @exception1 )
|
17
|
+
@logger = ParallelSpecs::SpecFailuresLogger.new( @output )
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
silence_warnings{ ParallelSpecs::SpecLoggerBase::RSPEC_1 = false }
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean_output
|
25
|
+
@output.output.join("\n").gsub(/\e\[\d+m/,'')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should produce a list of command lines for failing examples" do
|
29
|
+
@logger.example_failed @example1
|
30
|
+
@logger.example_failed @example2
|
31
|
+
|
32
|
+
@logger.dump_failures
|
33
|
+
@logger.dump_summary(1,2,3,4)
|
34
|
+
|
35
|
+
clean_output.should =~ /^rspec .*? should do stuff/
|
36
|
+
clean_output.should =~ /^rspec .*? should do other stuff/
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should invoke spec for rspec 1" do
|
40
|
+
silence_warnings{ ParallelSpecs::SpecLoggerBase::RSPEC_1 = true }
|
41
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
42
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
|
43
|
+
@logger.example_failed @example1
|
44
|
+
|
45
|
+
@logger.dump_failures
|
46
|
+
@logger.dump_summary(1,2,3,4)
|
47
|
+
|
48
|
+
clean_output.should =~ /^bundle exec spec/
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should invoke rspec for rspec 2" do
|
52
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
53
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
|
54
|
+
@logger.example_failed @example1
|
55
|
+
|
56
|
+
@logger.dump_failures
|
57
|
+
@logger.dump_summary(1,2,3,4)
|
58
|
+
|
59
|
+
clean_output.should =~ /^rspec/
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return relative paths" do
|
63
|
+
@logger.example_failed @example1
|
64
|
+
@logger.example_failed @example2
|
65
|
+
|
66
|
+
@logger.dump_failures
|
67
|
+
@logger.dump_summary(1,2,3,4)
|
68
|
+
|
69
|
+
clean_output.should =~ %r(\./spec/path/to/example:123)
|
70
|
+
clean_output.should =~ %r(\./spec/path/to/example2:456)
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# should not longer be a problem since its using native rspec methods
|
75
|
+
xit "should not log examples without location" do
|
76
|
+
example = mock('example', :location => 'bla', :full_description => 'before :all')
|
77
|
+
@logger.example_failed example
|
78
|
+
@logger.dump_failures
|
79
|
+
@logger.dump_summary(1,2,3,4)
|
80
|
+
clean_output.should == ''
|
81
|
+
end
|
82
|
+
end
|