cucumber-core 4.0.0 → 5.0.0

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.
@@ -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