torkify 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'torkify/conductor'
3
+ require 'torkify/observer_set'
4
+
5
+ module Torkify
6
+ describe Conductor do
7
+ before do
8
+ @reader = double
9
+ @observers = Torkify::ObserverSet.new
10
+ @conductor = Conductor.new @observers
11
+ end
12
+
13
+ subject { @conductor }
14
+
15
+ it { should respond_to :observers }
16
+ it { should respond_to :start }
17
+
18
+ its(:observers) { should equal @observers }
19
+
20
+ context "when an observer is added" do
21
+ before do
22
+ @observer = Object.new
23
+ @conductor.observers.add @observer
24
+ end
25
+
26
+ subject { @conductor.observers.first }
27
+
28
+ it { should equal @observer }
29
+ end
30
+
31
+ context "when start is called" do
32
+ before do
33
+ @conductor.observers += [double, double]
34
+ @conductor.observers.each do |o|
35
+ o.should_receive(:on_startup)
36
+ o.should_receive(:on_shutdown)
37
+ end
38
+ end
39
+
40
+ it "should call startup and shutdown on each observer and each_line on reader" do
41
+ @reader.should_receive(:each_line)
42
+ @conductor.start @reader
43
+ end
44
+ end
45
+
46
+ context "when start is called with dummy input" do
47
+ before do
48
+ line = '["test","spec/status_change_event_spec.rb",[],"spec/status_change_event_spec.rb.log",0]'
49
+ @reader.should_receive(:each_line).and_yield(line)
50
+ @conductor.observers += [double, double]
51
+ end
52
+
53
+ it "should notify each observer about the test event" do
54
+ @conductor.observers.each do |o|
55
+ o.should_receive(:on_startup)
56
+ o.should_receive(:on_test)
57
+ o.should_receive(:on_shutdown)
58
+ end
59
+ @conductor.start @reader
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+ require 'torkify/event_parser'
3
+
4
+ module Torkify
5
+ describe EventParser do
6
+ before { @parser = EventParser.new }
7
+
8
+ context "when calling parse on a test event line with no numbers" do
9
+ before do
10
+ line = '["test","spec/reader_spec.rb",[],"spec/reader_spec.rb.log",3]'
11
+ @event = @parser.parse line
12
+ end
13
+
14
+ subject { @event }
15
+
16
+ it { should be_a TestEvent }
17
+
18
+ its(:file) { should == 'spec/reader_spec.rb' }
19
+ its(:lines) { should == [] }
20
+ its(:log_file) { should == 'spec/reader_spec.rb.log' }
21
+ its(:worker) { should == 3 }
22
+ end
23
+
24
+ context "when calling parse on a test event line with numbers" do
25
+ before do
26
+ line = '["test","spec/another_spec.rb",[20, 32, 41],"spec/another_spec.rb.log",6]'
27
+ @event = @parser.parse line
28
+ end
29
+
30
+ subject { @event }
31
+
32
+ it { should be_a TestEvent }
33
+
34
+ its(:file) { should == 'spec/another_spec.rb' }
35
+ its(:lines) { should == [20, 32, 41] }
36
+ its(:log_file) { should == 'spec/another_spec.rb.log' }
37
+ its(:worker) { should == 6 }
38
+ end
39
+
40
+ context "when calling parse on a pass event line" do
41
+ before do
42
+ line = '["pass","spec/pass_spec.rb",[27],"spec/pass_spec.rb.log",1,0,"#<Process::Status: pid 27490 exit 0>"]'
43
+ @event = @parser.parse line
44
+ end
45
+
46
+ subject { @event }
47
+
48
+ it { should be_a PassOrFailEvent }
49
+ its(:type) { should == 'pass' }
50
+ its(:file) { should == 'spec/pass_spec.rb' }
51
+ its(:lines) { should == [27] }
52
+ its(:log_file) { should == 'spec/pass_spec.rb.log' }
53
+ its(:worker) { should == 1 }
54
+ its(:exit_code) { should == 0 }
55
+ its(:pid) { should == 27490 }
56
+ end
57
+
58
+ context "when calling parse on a fail event line" do
59
+ before do
60
+
61
+ line = '["fail","spec/fail_spec.rb",[],"spec/fail_spec.rb.log",1,256,"#<Process::Status: pid 23318 exit 1>"]'
62
+ @event = @parser.parse line
63
+ end
64
+
65
+ subject { @event }
66
+
67
+ it { should be_a PassOrFailEvent }
68
+ its(:type) { should == 'fail' }
69
+ its(:file) { should == 'spec/fail_spec.rb' }
70
+ its(:lines) { should == [] }
71
+ its(:log_file) { should == 'spec/fail_spec.rb.log' }
72
+ its(:worker) { should == 1 }
73
+ its(:exit_code) { should == 256 }
74
+ its(:pid) { should == 23318 }
75
+ end
76
+
77
+ context "when calling parse on an absorb event line" do
78
+ before do
79
+ line = '["absorb"]'
80
+ @event = @parser.parse line
81
+ end
82
+
83
+ subject { @event }
84
+
85
+ it { should be_an Event }
86
+ its(:type) { should == 'absorb' }
87
+ end
88
+
89
+ context "when calling parse on an unknown event type" do
90
+ before do
91
+ line = '["random"]'
92
+ @event = @parser.parse line
93
+ end
94
+
95
+ subject { @event }
96
+
97
+ it { should be_an Event }
98
+ its(:type) { should == 'random' }
99
+ end
100
+
101
+ context "when calling parse on a pass now fail event line" do
102
+ before do
103
+ line = '["pass_now_fail","spec/status_change_spec.rb",["fail","spec/status_change_spec.rb",[68],"spec/status_change_spec.rb.log",2,256,"#<Process::Status: pid 23819 exit 1>"]]'
104
+ @event = @parser.parse line
105
+ end
106
+
107
+ subject { @event }
108
+
109
+ it { should be_a StatusChangeEvent }
110
+ its(:type) { should == 'pass_now_fail' }
111
+ its(:file) { should == 'spec/status_change_spec.rb' }
112
+ its(:event) { should be_a PassOrFailEvent }
113
+
114
+ context "and getting the inner event" do
115
+ subject { @event.event }
116
+
117
+ its(:type) { should == 'fail' }
118
+ its(:file) { should == 'spec/status_change_spec.rb' }
119
+ its(:log_file) { should == 'spec/status_change_spec.rb.log' }
120
+ its(:lines) { should == [68] }
121
+ its(:worker) { should == 2 }
122
+ its(:exit_code) { should == 256 }
123
+ its(:pid) { should == 23819 }
124
+ end
125
+ end
126
+
127
+ context "when calling parse on a fail now pass event line" do
128
+ before do
129
+ line = '["fail_now_pass","spec/status_change_spec.rb",["pass","spec/status_change_spec.rb",[],"spec/status_change_spec.rb.log",1,0,"#<Process::Status: pid 677 exit 0>"]]'
130
+ @event = @parser.parse line
131
+ end
132
+
133
+ subject { @event }
134
+
135
+ it { should be_a StatusChangeEvent }
136
+ its(:type) { should == 'fail_now_pass' }
137
+ its(:file) { should == 'spec/status_change_spec.rb' }
138
+ its(:event) { should be_a PassOrFailEvent }
139
+
140
+ context "and getting the inner event" do
141
+ subject { @event.event }
142
+
143
+ its(:type) { should == 'pass' }
144
+ its(:file) { should == 'spec/status_change_spec.rb' }
145
+ its(:log_file) { should == 'spec/status_change_spec.rb.log' }
146
+ its(:lines) { should == [] }
147
+ its(:worker) { should == 1 }
148
+ its(:exit_code) { should == 0 }
149
+ its(:pid) { should == 677 }
150
+ end
151
+ end
152
+
153
+ end
154
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'torkify/events/event'
3
+
4
+ module Torkify
5
+ describe Event do
6
+ context "when type is absorb" do
7
+ before do
8
+ @event = Event.new('absorb')
9
+ end
10
+
11
+ subject { @event }
12
+
13
+ its(:type) { should == 'absorb' }
14
+ its(:to_s) { should == 'absorb' }
15
+ its(:message) { should == :on_absorb }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'torkify/listener'
3
+
4
+ module Torkify
5
+ describe Listener do
6
+ before do
7
+ Torkify::Reader.stub(:new)
8
+ Torkify::Conductor.any_instance.stub(:start)
9
+ end
10
+
11
+ context "with default command and directory" do
12
+ before do
13
+ @command = 'tork-remote tork-engine'
14
+ @dir = Dir.pwd
15
+ end
16
+ subject { Listener.new @command, @dir }
17
+
18
+ it "should create a reader with those defaults" do
19
+ Torkify::Reader.should_receive(:new).with @command, @dir
20
+ subject.start
21
+ end
22
+ end
23
+
24
+ context "with alternative command and directory" do
25
+ before do
26
+ @command = 'the command'
27
+ @dir = 'the dir'
28
+ end
29
+
30
+ subject { Listener.new @command, @dir }
31
+
32
+ it "should create a reader with the given parameters" do
33
+ Torkify::Reader.should_receive(:new).with @command, @dir
34
+ subject.start
35
+ end
36
+ end
37
+
38
+ it { should respond_to :add_observer }
39
+
40
+ context "after adding an observer" do
41
+ before do
42
+ @listener = Listener.new
43
+ end
44
+
45
+ subject { @listener.add_observer double }
46
+
47
+ it { should be @listener }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+ require 'torkify/observer_set'
3
+ require 'torkify/events/test_event'
4
+ require 'torkify/events/pass_or_fail_event'
5
+
6
+ module Torkify
7
+ describe ObserverSet do
8
+ before { @set = ObserverSet.new }
9
+ subject { @set }
10
+
11
+ it { should respond_to :length }
12
+ it { should respond_to :add }
13
+ it { should respond_to :<< }
14
+ it { should respond_to :| }
15
+
16
+ context "when empty" do
17
+ its(:length) { should == 0 }
18
+ end
19
+
20
+ context "when calling union with an array" do
21
+ before { @set |= [1, 3] }
22
+
23
+ it { should be_a ObserverSet }
24
+ its(:length) { should == 2 }
25
+ its(:to_a) { should == [1, 3] }
26
+ end
27
+
28
+ context "when adding an array" do
29
+ before { @set += [1, 3, 10] }
30
+
31
+ it { should be_a ObserverSet }
32
+ its(:length) { should == 3 }
33
+ end
34
+
35
+ context "when it contains one observer" do
36
+ before do
37
+ @observer = Object.new
38
+ @set.add @observer
39
+ end
40
+
41
+ its(:length) { should == 1 }
42
+
43
+ context "with a pass event" do
44
+ before { @event = Torkify::PassOrFailEvent.new 'pass', 1, [], 3, 4, 5, 6 }
45
+ it "should call the pass method on the observer with dispatch" do
46
+ @observer.should_receive(:on_pass).with(@event)
47
+ @set.dispatch(@event)
48
+ end
49
+ end
50
+
51
+ context "with a fail event" do
52
+ before do
53
+ @event = Torkify::PassOrFailEvent.new 'fail', 1, [], 3, 4, 5, 6
54
+ end
55
+
56
+ it "should call the fail method on the observer with dispatch" do
57
+ @observer.should_receive(:on_fail).with(@event)
58
+ @set.dispatch(@event)
59
+ end
60
+
61
+ it "should not raise an error on dispatch with unknown method" do
62
+ expect { @set.dispatch(@event) }.not_to raise_error
63
+ end
64
+
65
+ it "should not raise an error on dispatch to method with wrong number of parameters" do
66
+ def @observer.on_fail; end
67
+ expect { @set.dispatch(@event) }.not_to raise_error
68
+ end
69
+
70
+ it "should not raise an error on dispatch to method that raises an exception" do
71
+ @observer.should_receive(:on_fail).and_raise(RuntimeError)
72
+ expect { @set.dispatch(@event) }.not_to raise_error
73
+ end
74
+ end
75
+ end
76
+
77
+ context "when it contains multiple observers" do
78
+ before { @set += [double, double, double] }
79
+
80
+ its(:length) { should == 3 }
81
+
82
+ it "should call the pass method on every observer with dispatch" do
83
+ event = Torkify::PassOrFailEvent.new 'pass', 1, [], 3, 4, 5, 6
84
+ @set.each { |o| o.should_receive(:on_pass).with(event) }
85
+ @set.dispatch(event)
86
+ end
87
+
88
+ end
89
+
90
+ context "when trying to add the same object twice" do
91
+ before do
92
+ object = double
93
+ @set.add object
94
+ @set.add object
95
+ end
96
+
97
+ its(:length) { should == 1 }
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'torkify/events/pass_or_fail_event'
3
+
4
+ module Torkify
5
+ describe PassOrFailEvent do
6
+
7
+ context "with pass data" do
8
+ before do
9
+ @type = 'pass'
10
+ @file = 'file'
11
+ @lines = []
12
+ @log_file = 'log_file'
13
+ @worker = 1
14
+ @exit_code = 0
15
+ @exit_info = 'exit info'
16
+ end
17
+
18
+ subject { @event = PassOrFailEvent.new @type,
19
+ @file,
20
+ @lines,
21
+ @log_file,
22
+ @worker,
23
+ @exit_code,
24
+ @exit_info }
25
+
26
+ its(:type) { should == @type }
27
+ its(:file) { should == @file }
28
+ its(:lines) { should == @lines }
29
+ its(:log_file) { should == @log_file }
30
+ its(:worker) { should == @worker }
31
+ its(:exit_code) { should == @exit_code }
32
+ its(:exit_info) { should == @exit_info }
33
+ its(:to_s) { should == "PASS file" }
34
+ its(:message) { should == :on_pass }
35
+
36
+ context "and line numbers" do
37
+ before do
38
+ @lines = [1, 14, 23]
39
+ end
40
+
41
+ its(:to_s) { should == "PASS file (lines 1, 14, 23)" }
42
+ end
43
+ end
44
+
45
+ context "with fail data" do
46
+ before do
47
+ @type = 'fail'
48
+ @file = 'file'
49
+ @lines = []
50
+ @log_file = 'log_file'
51
+ @worker = 0
52
+ @exit_code = 1
53
+ @exit_info = 'exit info'
54
+ end
55
+
56
+ subject { @event = PassOrFailEvent.new @type,
57
+ @file,
58
+ @lines,
59
+ @log_file,
60
+ @worker,
61
+ @exit_code,
62
+ @exit_info }
63
+
64
+ its(:type) { should == @type }
65
+ its(:file) { should == @file }
66
+ its(:lines) { should == @lines }
67
+ its(:log_file) { should == @log_file }
68
+ its(:worker) { should == @worker }
69
+ its(:exit_code) { should == @exit_code }
70
+ its(:exit_info) { should == @exit_info }
71
+ its(:to_s) { should == "FAIL file" }
72
+ its(:message) { should == :on_fail }
73
+
74
+ context "and line numbers" do
75
+ before do
76
+ @lines = [1, 14, 23]
77
+ end
78
+
79
+ its(:to_s) { should == "FAIL file (lines 1, 14, 23)" }
80
+ end
81
+ end
82
+
83
+ context "with a process status string" do
84
+ before do
85
+ @event = PassOrFailEvent.new(*(1..6),
86
+ '#<Process::Status: pid 18228 exit 0>')
87
+ end
88
+
89
+ subject { @event.pid }
90
+
91
+ it { should == 18228 }
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'torkify/reader'
3
+
4
+ module Torkify
5
+ describe Reader do
6
+ context "with dummy command" do
7
+ before { @reader = Reader.new 'echo' }
8
+ subject { @reader}
9
+
10
+ it { should respond_to :readline }
11
+ it { should respond_to :each_line }
12
+ it { should respond_to :pos }
13
+ end
14
+
15
+ context "with echo command" do
16
+ before { @reader = Reader.new 'echo "Line 1\nLine 2"' }
17
+
18
+ context "first line" do
19
+ subject { @reader.readline.strip }
20
+ it { should == "Line 1" }
21
+ end
22
+
23
+ context "second line" do
24
+ before { @reader.readline }
25
+ subject { @reader.readline.strip }
26
+
27
+ it { should == "Line 2" }
28
+ end
29
+
30
+ context "each over line" do
31
+ before do
32
+ @output = []
33
+ @reader.each_line { |line| @output << line.strip }
34
+ end
35
+
36
+ subject { @output }
37
+
38
+ it { should == ["Line 1", "Line 2"] }
39
+ end
40
+ end
41
+
42
+ context "with command that writes to standard error" do
43
+ it "should raise TorkError" do
44
+ err = 'Command error'
45
+ expect { Reader.new "echo '#{err}' >&2" }.to raise_exception(TorkError, err)
46
+ end
47
+ end
48
+
49
+ context "with a working directory" do
50
+ before do
51
+ @reader = Reader.new 'echo $PWD', '/usr'
52
+ end
53
+ subject { @reader.read.strip }
54
+
55
+ it { should == '/usr' }
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'torkify'
3
+ Torkify.logger.level = Log4r::FATAL
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'torkify/events/status_change_event'
3
+ require 'torkify/events/pass_or_fail_event'
4
+
5
+ module Torkify
6
+ describe StatusChangeEvent do
7
+
8
+ context "with a pass_now_fail event" do
9
+ before do
10
+ @type = 'pass_now_fail'
11
+ @file = 'file'
12
+ @inner_event = PassOrFailEvent.new(*(1..7))
13
+ @event = StatusChangeEvent.new(@type, @file, @inner_event)
14
+ end
15
+
16
+ subject { @event }
17
+
18
+ its(:type) { should == @type }
19
+ its(:file) { should == @file }
20
+ its(:event) { should == @inner_event }
21
+ its(:to_s) { should == 'PASS NOW FAIL file' }
22
+ its(:message) { should == :on_pass_now_fail }
23
+ end
24
+
25
+ context "with a fail_now_pass event" do
26
+ before do
27
+ @type = 'fail_now_pass'
28
+ @file = 'file'
29
+ @inner_event = PassOrFailEvent.new(*(1..7))
30
+ @event = StatusChangeEvent.new(@type, @file, @inner_event)
31
+ end
32
+
33
+ subject { @event }
34
+
35
+ its(:type) { should == @type }
36
+ its(:file) { should == @file }
37
+ its(:event) { should == @inner_event }
38
+ its(:to_s) { should == 'FAIL NOW PASS file' }
39
+ its(:message) { should == :on_fail_now_pass }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'torkify/events/test_event'
3
+
4
+ module Torkify
5
+ describe TestEvent do
6
+
7
+ context "with typical seed data" do
8
+ before do
9
+ @type = 'test'
10
+ @file = 'file'
11
+ @lines = []
12
+ @log_file = 'log_file'
13
+ @worker = 1
14
+ end
15
+
16
+ subject { TestEvent.new(@type, @file, @lines, @log_file, @worker) }
17
+
18
+ its(:type) { should == @type }
19
+ its(:file) { should == @file }
20
+ its(:lines) { should == @lines }
21
+ its(:log_file) { should == @log_file }
22
+ its(:worker) { should == @worker }
23
+ its(:to_s) { should == 'TEST file' }
24
+ its(:message) { should == :on_test }
25
+
26
+ context "with line numbers" do
27
+ before { @lines = [1, 5, 12] }
28
+ its(:to_s) { should == 'TEST file (lines 1, 5, 12)' }
29
+ end
30
+ end
31
+ end
32
+ end
data/torkify.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'torkify/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "torkify"
8
+ gem.version = Torkify::VERSION
9
+ gem.authors = ["Jon Cairns"]
10
+ gem.email = ["jon@joncairns.com"]
11
+ gem.description = %q{Easily create callbacks for automated testing with tork}
12
+ gem.summary = %q{Torkify allows you to execute code after tests run, when using the tork gem for automated testing. You can create listeners which are called when tests are run, and when they fail or pass. This allows you to easily execute code and call system programs.}
13
+ gem.homepage = "https://github.com/joonty/torkify"
14
+
15
+ gem.add_dependency 'json', '~> 1.7.7'
16
+ gem.add_dependency 'log4r', '~> 1.1.10'
17
+ gem.add_dependency 'tork', '~> 19.2.1'
18
+
19
+ gem.add_development_dependency 'rspec', '~> 2.13.0'
20
+ gem.add_development_dependency 'rake', '~> 10.0.3'
21
+
22
+ gem.files = `git ls-files`.split($/)
23
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
24
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
25
+ gem.require_paths = ["lib"]
26
+ end