cucumber-core 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,167 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'cucumber/core/event_bus'
3
+ require 'cucumber/core/events'
4
+ require 'cucumber/core/report/summary'
5
+ require 'cucumber/core/test/result'
6
+
7
+ module Cucumber::Core::Report
8
+ describe Summary do
9
+ let(:event_bus) { ::Cucumber::Core::EventBus.new(registry) }
10
+ let(:registry) { ::Cucumber::Core::Events.registry }
11
+ let(:passed_result) { ::Cucumber::Core::Test::Result::Passed.new(duration) }
12
+ let(:failed_result) { ::Cucumber::Core::Test::Result::Failed.new(duration, exception) }
13
+ let(:pending_result) { ::Cucumber::Core::Test::Result::Pending.new(duration) }
14
+ let(:skipped_result) { ::Cucumber::Core::Test::Result::Skipped.new(duration) }
15
+ let(:undefined_result) { ::Cucumber::Core::Test::Result::Undefined.new(duration) }
16
+ let(:duration) { double }
17
+ let(:exception) { double }
18
+
19
+ before(:each) { @summary = Summary.new(event_bus) }
20
+
21
+ context "test case summary" do
22
+ let(:test_case) { double }
23
+
24
+ it "counts passed test cases" do
25
+ event_bus.send(:test_case_finished, test_case, passed_result)
26
+
27
+ expect( @summary.test_cases.total(:passed) ).to eq(1)
28
+ expect( @summary.test_cases.total ).to eq(1)
29
+ end
30
+
31
+ it "counts failed test cases" do
32
+ event_bus.send(:test_case_finished, test_case, failed_result)
33
+
34
+ expect( @summary.test_cases.total(:failed) ).to eq(1)
35
+ expect( @summary.test_cases.total ).to eq(1)
36
+ end
37
+
38
+ it "counts pending test cases" do
39
+ event_bus.send(:test_case_finished, test_case, pending_result)
40
+
41
+ expect( @summary.test_cases.total(:pending) ).to eq(1)
42
+ expect( @summary.test_cases.total ).to eq(1)
43
+ end
44
+
45
+ it "counts skipped test cases" do
46
+ event_bus.send(:test_case_finished, test_case, skipped_result)
47
+
48
+ expect( @summary.test_cases.total(:skipped) ).to eq(1)
49
+ expect( @summary.test_cases.total ).to eq(1)
50
+ end
51
+
52
+ it "counts undefined test cases" do
53
+ event_bus.send(:test_case_finished, test_case, undefined_result)
54
+
55
+ expect( @summary.test_cases.total(:undefined) ).to eq(1)
56
+ expect( @summary.test_cases.total ).to eq(1)
57
+ end
58
+
59
+ it "handles flaky test cases" do
60
+ allow(test_case).to receive(:==).and_return(false, true)
61
+ event_bus.send(:test_case_finished, test_case, failed_result)
62
+ event_bus.send(:test_case_finished, test_case, passed_result)
63
+
64
+ expect( @summary.test_cases.total(:failed) ).to eq(0)
65
+ expect( @summary.test_cases.total(:flaky) ).to eq(1)
66
+ expect( @summary.test_cases.total ).to eq(1)
67
+ end
68
+ end
69
+
70
+ context "test step summary" do
71
+ context "with test steps from gherkin steps" do
72
+ let(:test_step) { double }
73
+
74
+ before(:each) do
75
+ expect( test_step ).to receive(:hook?).and_return(false)
76
+ end
77
+
78
+ it "counts passed test steps" do
79
+ event_bus.send(:test_step_finished, test_step, passed_result)
80
+
81
+ expect( @summary.test_steps.total(:passed) ).to eq(1)
82
+ expect( @summary.test_steps.total ).to eq(1)
83
+ end
84
+
85
+ it "counts failed test cases" do
86
+ event_bus.send(:test_step_finished, test_step, failed_result)
87
+
88
+ expect( @summary.test_steps.total(:failed) ).to eq(1)
89
+ expect( @summary.test_steps.total ).to eq(1)
90
+ end
91
+
92
+ it "counts pending test cases" do
93
+ event_bus.send(:test_step_finished, test_step, pending_result)
94
+
95
+ expect( @summary.test_steps.total(:pending) ).to eq(1)
96
+ expect( @summary.test_steps.total ).to eq(1)
97
+ end
98
+
99
+ it "counts skipped test cases" do
100
+ event_bus.send(:test_step_finished, test_step, skipped_result)
101
+
102
+ expect( @summary.test_steps.total(:skipped) ).to eq(1)
103
+ expect( @summary.test_steps.total ).to eq(1)
104
+ end
105
+
106
+ it "counts undefined test cases" do
107
+ event_bus.send(:test_step_finished, test_step, undefined_result)
108
+
109
+ expect( @summary.test_steps.total(:undefined) ).to eq(1)
110
+ expect( @summary.test_steps.total ).to eq(1)
111
+ end
112
+ end
113
+
114
+ context "with test steps not from gherkin steps" do
115
+ let(:test_step) { double }
116
+
117
+ before(:each) do
118
+ expect( test_step ).to receive(:hook?).and_return(true)
119
+ end
120
+
121
+ it "ignores test steps not defined by gherkin steps" do
122
+ event_bus.send(:test_step_finished, test_step, passed_result)
123
+
124
+ expect( @summary.test_steps.total ).to eq(0)
125
+ end
126
+ end
127
+ end
128
+
129
+ context "ok? result" do
130
+ let(:test_case) { double }
131
+
132
+ it "passed test case is ok" do
133
+ event_bus.send(:test_case_finished, test_case, passed_result)
134
+
135
+ expect( @summary.ok? ).to eq true
136
+ end
137
+
138
+ it "skipped test case is ok" do
139
+ event_bus.send(:test_case_finished, test_case, skipped_result)
140
+
141
+ expect( @summary.ok? ).to eq true
142
+ end
143
+
144
+ it "failed test case is not ok" do
145
+ event_bus.send(:test_case_finished, test_case, failed_result)
146
+
147
+ expect( @summary.ok? ).to eq false
148
+ end
149
+
150
+ it "pending test case is ok if not strict" do
151
+ event_bus.send(:test_case_finished, test_case, pending_result)
152
+
153
+ expect( @summary.ok? ).to eq true
154
+ be_strict = ::Cucumber::Core::Test::Result::StrictConfiguration.new([:pending])
155
+ expect( @summary.ok?(be_strict) ).to eq false
156
+ end
157
+
158
+ it "undefined test case is ok if not strict" do
159
+ event_bus.send(:test_case_finished, test_case, undefined_result)
160
+
161
+ expect( @summary.ok? ).to eq true
162
+ be_strict = ::Cucumber::Core::Test::Result::StrictConfiguration.new([:undefined])
163
+ expect( @summary.ok?(be_strict) ).to eq false
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+ require 'cucumber/core/test/action'
3
+ require 'cucumber/core/test/duration_matcher'
4
+
5
+ module Cucumber
6
+ module Core
7
+ module Test
8
+
9
+ describe Action do
10
+
11
+ context "constructed without a block" do
12
+ it "raises an error" do
13
+ expect { Action.new }.to raise_error(ArgumentError)
14
+ end
15
+ end
16
+
17
+ context "location" do
18
+
19
+ context "with location passed to the constructor" do
20
+ let(:location) { double }
21
+
22
+ it "returns the location passed to the constructor" do
23
+ action = Action.new(location) {}
24
+ expect( action.location ).to be location
25
+ end
26
+ end
27
+
28
+ context "without location passed to the constructor" do
29
+ let(:block) { proc {} }
30
+
31
+ it "returns the location of the block passed to the constructor" do
32
+ action = Action.new(&block)
33
+ expect( action.location ).to eq Test::Location.new(*block.source_location)
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ context "executing" do
40
+ it "executes the block passed to the constructor" do
41
+ executed = false
42
+ action = Action.new { executed = true }
43
+ action.execute
44
+ expect( executed ).to be_truthy
45
+ end
46
+
47
+ it "returns a passed result if the block doesn't fail" do
48
+ action = Action.new {}
49
+ expect( action.execute ).to be_passed
50
+ end
51
+
52
+ it "returns a failed result when the block raises an error" do
53
+ exception = StandardError.new
54
+ action = Action.new { raise exception }
55
+ result = action.execute
56
+ expect( result ).to be_failed
57
+ expect( result.exception ).to eq exception
58
+ end
59
+
60
+ it "yields the args passed to #execute to the block" do
61
+ args = [double, double]
62
+ args_spy = nil
63
+ action = Action.new { |arg1, arg2| args_spy = [arg1, arg2] }
64
+ action.execute(*args)
65
+ expect(args_spy).to eq args
66
+ end
67
+
68
+ it "returns a pending result if a Result::Pending error is raised" do
69
+ exception = Result::Pending.new("TODO")
70
+ action = Action.new { raise exception }
71
+ result = action.execute
72
+ expect( result ).to be_pending
73
+ expect( result.message ).to eq "TODO"
74
+ end
75
+
76
+ it "returns a skipped result if a Result::Skipped error is raised" do
77
+ exception = Result::Skipped.new("Not working right now")
78
+ action = Action.new { raise exception }
79
+ result = action.execute
80
+ expect( result ).to be_skipped
81
+ expect( result.message ).to eq "Not working right now"
82
+ end
83
+
84
+ it "returns an undefined result if a Result::Undefined error is raised" do
85
+ exception = Result::Undefined.new("new step")
86
+ action = Action.new { raise exception }
87
+ result = action.execute
88
+ expect( result ).to be_undefined
89
+ expect( result.message ).to eq "new step"
90
+ end
91
+
92
+ context "recording the duration" do
93
+ before do
94
+ allow( Timer::MonotonicTime ).to receive(:time_in_nanoseconds).and_return(525702744080000, 525702744080001)
95
+ end
96
+
97
+ it "records the nanoseconds duration of the execution on the result" do
98
+ action = Action.new { }
99
+ duration = action.execute.duration
100
+ expect( duration ).to be_duration 1
101
+ end
102
+
103
+ it "records the duration of a failed execution" do
104
+ action = Action.new { raise StandardError }
105
+ duration = action.execute.duration
106
+ expect( duration ).to be_duration 1
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ context "skipping" do
113
+ it "does not execute the block" do
114
+ executed = false
115
+ action = Action.new { executed = true }
116
+ action.skip
117
+ expect( executed ).to be_falsey
118
+ end
119
+
120
+ it "returns a skipped result" do
121
+ action = Action.new {}
122
+ expect( action.skip ).to be_skipped
123
+ end
124
+ end
125
+ end
126
+
127
+ describe UndefinedAction do
128
+ let(:location) { double }
129
+ let(:action) { UndefinedAction.new(location) }
130
+ let(:test_step) { double }
131
+
132
+ context "location" do
133
+ it "returns the location passed to the constructor" do
134
+ expect( action.location ).to be location
135
+ end
136
+ end
137
+
138
+ context "executing" do
139
+ it "returns an undefined result" do
140
+ expect( action.execute ).to be_undefined
141
+ end
142
+ end
143
+
144
+ context "skipping" do
145
+ it "returns an undefined result" do
146
+ expect( action.skip ).to be_undefined
147
+ end
148
+ end
149
+ end
150
+
151
+ end
152
+ end
153
+ end
154
+
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+ # -*- coding: utf-8 -*-
3
+ require 'cucumber/core'
4
+ require 'cucumber/core/gherkin/writer'
5
+ require 'cucumber/core/platform'
6
+ require 'cucumber/core/test/case'
7
+ require 'unindent'
8
+
9
+ module Cucumber
10
+ module Core
11
+ module Test
12
+ describe Case do
13
+ include Core
14
+ include Core::Gherkin::Writer
15
+
16
+ let(:name) { double }
17
+ let(:location) { double }
18
+ let(:tags) { double }
19
+ let(:language) { double }
20
+ let(:test_case) { Test::Case.new(name, test_steps, location, tags, language) }
21
+ let(:test_steps) { [double, double] }
22
+
23
+ context 'describing itself' do
24
+ it "describes itself to a visitor" do
25
+ visitor = double
26
+ args = double
27
+ expect( visitor ).to receive(:test_case).with(test_case, args)
28
+ test_case.describe_to(visitor, args)
29
+ end
30
+
31
+ it "asks each test_step to describe themselves to the visitor" do
32
+ visitor = double
33
+ args = double
34
+ test_steps.each do |test_step|
35
+ expect( test_step ).to receive(:describe_to).with(visitor, args)
36
+ end
37
+ allow( visitor ).to receive(:test_case).and_yield(visitor)
38
+ test_case.describe_to(visitor, args)
39
+ end
40
+
41
+ it "describes around hooks in order" do
42
+ visitor = double
43
+ allow( visitor ).to receive(:test_case).and_yield(visitor)
44
+ first_hook, second_hook = double, double
45
+ expect( first_hook ).to receive(:describe_to).ordered.and_yield
46
+ expect( second_hook ).to receive(:describe_to).ordered.and_yield
47
+ around_hooks = [first_hook, second_hook]
48
+ Test::Case.new(name, [], location, tags, language, around_hooks).describe_to(visitor, double)
49
+ end
50
+
51
+ end
52
+
53
+ describe "#name" do
54
+ it "the name is passed when creating the test case" do
55
+ expect( test_case.name ).to eq(name)
56
+ end
57
+ end
58
+
59
+ describe "#location" do
60
+ it "the location is passed when creating the test case" do
61
+ expect( test_case.location ).to eq(location)
62
+ end
63
+ end
64
+
65
+ describe "#tags" do
66
+ it "the tags are passed when creating the test case" do
67
+ expect( test_case.tags ).to eq(tags)
68
+ end
69
+ end
70
+
71
+ describe "matching tags" do
72
+ let(:tags) { ['@a', '@b', '@c'].map { |value| Tag.new(location, value) } }
73
+ it "matches tags using tag expressions" do
74
+ expect( test_case.match_tags?(['@a and @b']) ).to be_truthy
75
+ expect( test_case.match_tags?(['@a or @d']) ).to be_truthy
76
+ expect( test_case.match_tags?(['not @d']) ).to be_truthy
77
+ expect( test_case.match_tags?(['@a and @d']) ).to be_falsy
78
+ end
79
+
80
+ it "matches handles multiple expressions" do
81
+ expect( test_case.match_tags?(['@a and @b', 'not @d']) ).to be_truthy
82
+ expect( test_case.match_tags?(['@a and @b', 'not @c']) ).to be_falsy
83
+ end
84
+ end
85
+
86
+ describe "matching names" do
87
+ let(:name) { 'scenario' }
88
+ it "matches names against regexp" do
89
+ expect( test_case.match_name?(/scenario/) ).to be_truthy
90
+ end
91
+ end
92
+
93
+ describe "#language" do
94
+ let(:language) { 'en-pirate' }
95
+ it "the language is passed when creating the test case" do
96
+ expect( test_case.language ).to eq 'en-pirate'
97
+ end
98
+ end
99
+
100
+ describe "equality" do
101
+ it "is equal to another test case at the same location" do
102
+ gherkin = gherkin('features/foo.feature') do
103
+ feature do
104
+ scenario do
105
+ step 'text'
106
+ end
107
+ end
108
+ end
109
+ test_case_instances = []
110
+ receiver = double.as_null_object
111
+ allow(receiver).to receive(:test_case) do |test_case|
112
+ test_case_instances << test_case
113
+ end
114
+ 2.times { compile([gherkin], receiver) }
115
+ expect(test_case_instances.length).to eq 2
116
+ expect(test_case_instances.uniq.length).to eq 1
117
+ expect(test_case_instances[0]).to be_eql test_case_instances[1]
118
+ expect(test_case_instances[0]).to eq test_case_instances[1]
119
+ expect(test_case_instances[0]).not_to equal test_case_instances[1]
120
+ end
121
+ end
122
+
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'cucumber/core/test/data_table'
4
+
5
+ module Cucumber
6
+ module Core
7
+ module Test
8
+ describe DataTable do
9
+ let(:location) { Test::Location.new('foo.feature', 9..12) }
10
+
11
+ before do
12
+ @table = DataTable.new([
13
+ %w{one four seven},
14
+ %w{4444 55555 666666}
15
+ ], location)
16
+ end
17
+
18
+ describe "equality" do
19
+ it "is equal to another table with the same data" do
20
+ expect( DataTable.new([[1,2],[3,4]], location) ).to eq DataTable.new([[1,2],[3,4]], location)
21
+ end
22
+
23
+ it "is not equal to another table with different data" do
24
+ expect( DataTable.new([[1,2],[3,4]], location) ).not_to eq DataTable.new([[1,2]], location)
25
+ end
26
+
27
+ it "is not equal to a non table" do
28
+ expect( DataTable.new([[1,2],[3,4]], location) ).not_to eq Object.new
29
+ end
30
+ end
31
+
32
+ describe "#data_table?" do
33
+ let(:table) { DataTable.new([[1,2],[3,4]], location) }
34
+
35
+ it "returns true" do
36
+ expect(table).to be_data_table
37
+ end
38
+ end
39
+
40
+ describe "#doc_string" do
41
+ let(:table) { DataTable.new([[1,2],[3,4]], location) }
42
+
43
+ it "returns false" do
44
+ expect(table).not_to be_doc_string
45
+ end
46
+ end
47
+
48
+ describe "#map" do
49
+ let(:table) { DataTable.new([ %w{foo bar}, %w{1 2} ], location) }
50
+
51
+ it 'yields the contents of each cell to the block' do
52
+
53
+ expect { |b| table.map(&b) }.to yield_successive_args('foo', 'bar', '1', '2')
54
+ end
55
+
56
+ it 'returns a new table with the cells modified by the block' do
57
+ expect( table.map { |cell| "*#{cell}*" } ).to eq DataTable.new([%w{*foo* *bar*}, %w{*1* *2*}], location)
58
+ end
59
+ end
60
+
61
+ describe "#transpose" do
62
+ before(:each) do
63
+ @table = DataTable.new([
64
+ %w{one 1111},
65
+ %w{two 22222}
66
+ ], location)
67
+ end
68
+
69
+ it "should transpose the table" do
70
+ transposed = DataTable.new([
71
+ %w{one two},
72
+ %w{1111 22222}
73
+ ], location)
74
+ expect( @table.transpose ).to eq( transposed )
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end