cucumber 0.3.102 → 0.3.103
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/History.txt +18 -0
- data/Manifest.txt +6 -2
- data/examples/java/README.textile +3 -3
- data/examples/self_test/features/sample.feature +1 -1
- data/examples/self_test/features/search_sample.feature +1 -1
- data/features/custom_formatter.feature +4 -4
- data/features/steps_formatter.feature +2 -1
- data/lib/cucumber/ast.rb +1 -0
- data/lib/cucumber/ast/table.rb +4 -4
- data/lib/cucumber/ast/tree_walker.rb +185 -0
- data/lib/cucumber/ast/visitor.rb +2 -106
- data/lib/cucumber/cli/configuration.rb +28 -28
- data/lib/cucumber/cli/language_help_formatter.rb +5 -7
- data/lib/cucumber/cli/main.rb +3 -3
- data/lib/cucumber/core_ext/string.rb +0 -22
- data/lib/cucumber/formatter/html.rb +203 -113
- data/lib/cucumber/formatter/junit.rb +29 -23
- data/lib/cucumber/formatter/pdf.rb +74 -69
- data/lib/cucumber/formatter/pretty.rb +93 -78
- data/lib/cucumber/formatter/profile.rb +2 -2
- data/lib/cucumber/formatter/progress.rb +16 -10
- data/lib/cucumber/formatter/rerun.rb +4 -5
- data/lib/cucumber/formatter/steps.rb +6 -7
- data/lib/cucumber/formatter/tag_cloud.rb +7 -6
- data/lib/cucumber/formatter/usage.rb +7 -10
- data/lib/cucumber/language_support/step_definition_methods.rb +4 -4
- data/lib/cucumber/rails/action_controller.rb +1 -1
- data/lib/cucumber/rails/active_record.rb +27 -14
- data/lib/cucumber/rb_support/rb_language.rb +5 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +9 -16
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +21 -0
- data/lib/cucumber/step_argument.rb +9 -0
- data/lib/cucumber/step_match.rb +24 -5
- data/lib/cucumber/version.rb +1 -1
- data/rails_generators/cucumber/templates/env.rb +14 -0
- data/spec/cucumber/ast/background_spec.rb +1 -2
- data/spec/cucumber/ast/scenario_outline_spec.rb +3 -2
- data/spec/cucumber/ast/scenario_spec.rb +1 -1
- data/spec/cucumber/ast/tree_walker_spec.rb +18 -0
- data/spec/cucumber/formatter/html_spec.rb +221 -2
- data/spec/cucumber/formatter/progress_spec.rb +9 -4
- data/spec/cucumber/parser/feature_parser_spec.rb +31 -27
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +18 -0
- data/spec/cucumber/step_match_spec.rb +40 -0
- metadata +8 -4
- data/lib/cucumber/rb_support/rb_group.rb +0 -11
- data/spec/cucumber/core_ext/string_spec.rb +0 -41
@@ -12,13 +12,13 @@ module Cucumber
|
|
12
12
|
@step_definition_durations = Hash.new { |h,step_definition| h[step_definition] = [] }
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def step(step)
|
16
16
|
@step_duration = Time.now
|
17
17
|
@step = step
|
18
18
|
super
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
22
22
|
duration = Time.now - @step_duration
|
23
23
|
super
|
24
24
|
|
@@ -3,33 +3,39 @@ require 'cucumber/formatter/console'
|
|
3
3
|
module Cucumber
|
4
4
|
module Formatter
|
5
5
|
# The formatter used for <tt>--format progress</tt>
|
6
|
-
class Progress
|
6
|
+
class Progress
|
7
7
|
include Console
|
8
|
+
attr_reader :step_mother
|
8
9
|
|
9
10
|
def initialize(step_mother, io, options)
|
10
|
-
|
11
|
-
@io = io
|
12
|
-
@options = options
|
11
|
+
@step_mother, @io, @options = step_mother, io, options
|
13
12
|
end
|
14
13
|
|
15
|
-
def
|
16
|
-
super
|
14
|
+
def after_features(features)
|
17
15
|
@io.puts
|
18
16
|
@io.puts
|
19
17
|
print_summary(features)
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
20
|
+
def before_feature_element(feature_element)
|
23
21
|
record_tag_occurrences(feature_element, @options)
|
24
|
-
super
|
25
22
|
end
|
26
23
|
|
27
|
-
def
|
24
|
+
def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
28
25
|
progress(status)
|
29
26
|
@status = status
|
30
27
|
end
|
28
|
+
|
29
|
+
def before_outline_table(outline_table)
|
30
|
+
@outline_table = outline_table
|
31
|
+
end
|
32
|
+
|
33
|
+
def after_outline_table(outline_table)
|
34
|
+
@outline_table = nil
|
35
|
+
end
|
31
36
|
|
32
|
-
def
|
37
|
+
def table_cell_value(value, status)
|
38
|
+
return unless @outline_table
|
33
39
|
status ||= @status
|
34
40
|
progress(status) unless table_header_cell?(status)
|
35
41
|
end
|
@@ -10,16 +10,15 @@ module Cucumber
|
|
10
10
|
# This formatter is used by AutoTest - it will use the output to decide what
|
11
11
|
# to run the next time, simply passing the output string on the command line.
|
12
12
|
#
|
13
|
-
class Rerun
|
13
|
+
class Rerun
|
14
14
|
def initialize(step_mother, io, options)
|
15
|
-
super(step_mother)
|
16
15
|
@io = io
|
17
16
|
@options = options
|
18
17
|
@file_names = []
|
19
18
|
@file_colon_lines = Hash.new{|h,k| h[k] = []}
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
21
|
+
def features(features)
|
23
22
|
super
|
24
23
|
files = @file_names.uniq.map do |file|
|
25
24
|
lines = @file_colon_lines[file]
|
@@ -28,7 +27,7 @@ module Cucumber
|
|
28
27
|
@io.puts files.join(' ')
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
30
|
+
def feature_element(feature_element)
|
32
31
|
@rerun = false
|
33
32
|
super
|
34
33
|
if @rerun
|
@@ -38,7 +37,7 @@ module Cucumber
|
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
41
|
-
def
|
40
|
+
def step_name(keyword, step_match, status, source_indent, background)
|
42
41
|
@rerun = true if [:failed].index(status)
|
43
42
|
end
|
44
43
|
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
module Cucumber
|
2
2
|
module Formatter
|
3
3
|
# The formatter used for <tt>--format steps</tt>
|
4
|
-
class Steps
|
4
|
+
class Steps
|
5
5
|
|
6
6
|
def initialize(step_mother, io, options)
|
7
|
-
super(step_mother)
|
8
7
|
@io = io
|
9
8
|
@options = options
|
10
9
|
@step_definition_files = collect_steps(step_mother)
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
12
|
+
def after_features(features)
|
14
13
|
print_summary
|
15
14
|
end
|
16
15
|
|
@@ -23,9 +22,9 @@ module Cucumber
|
|
23
22
|
|
24
23
|
sources = @step_definition_files[step_definition_file]
|
25
24
|
source_indent = source_indent(sources)
|
26
|
-
sources.sort.each do |file_colon_line,
|
27
|
-
@io.print
|
28
|
-
@io.print " # #{file_colon_line}".indent(source_indent -
|
25
|
+
sources.sort.each do |file_colon_line, regexp_source|
|
26
|
+
@io.print regexp_source.indent(2)
|
27
|
+
@io.print " # #{file_colon_line}".indent(source_indent - regexp_source.jlength)
|
29
28
|
@io.puts
|
30
29
|
end
|
31
30
|
@io.puts
|
@@ -37,7 +36,7 @@ module Cucumber
|
|
37
36
|
def collect_steps(step_mother)
|
38
37
|
step_mother.step_definitions.inject({}) do |step_definitions, step_definition|
|
39
38
|
step_definitions[step_definition.file] ||= []
|
40
|
-
step_definitions[step_definition.file] << [ step_definition.file_colon_line, step_definition.
|
39
|
+
step_definitions[step_definition.file] << [ step_definition.file_colon_line, step_definition.regexp_source ]
|
41
40
|
step_definitions
|
42
41
|
end
|
43
42
|
end
|
@@ -2,27 +2,28 @@ module Cucumber
|
|
2
2
|
module Formatter
|
3
3
|
# The formatter used for <tt>--format tag_cloud</tt>
|
4
4
|
# Custom formatter that prints a tag cloud as a table.
|
5
|
-
class TagCloud
|
5
|
+
class TagCloud
|
6
6
|
def initialize(step_mother, io, options)
|
7
|
-
super(step_mother)
|
8
7
|
@io = io
|
9
8
|
@options = options
|
10
9
|
@counts = Hash.new{|h,k| h[k] = 0}
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
14
|
-
super
|
12
|
+
def after_features(features)
|
15
13
|
print_summary(features)
|
16
14
|
end
|
17
15
|
|
18
|
-
def
|
16
|
+
def tag_name(tag_name)
|
19
17
|
@counts[tag_name] += 1
|
20
18
|
end
|
19
|
+
|
20
|
+
private
|
21
21
|
|
22
22
|
def print_summary(features)
|
23
23
|
matrix = @counts.to_a.sort{|paira, pairb| paira[0] <=> pairb[0]}.transpose
|
24
24
|
table = Cucumber::Ast::Table.new(matrix)
|
25
|
-
Cucumber::Formatter::Pretty.new(@step_mother, @io, {})
|
25
|
+
formatter = Cucumber::Formatter::Pretty.new(@step_mother, @io, {})
|
26
|
+
Cucumber::Ast::TreeWalker.new(@step_mother, [formatter], {}).visit_multiline_arg(table)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -3,11 +3,10 @@ require 'cucumber/formatter/progress'
|
|
3
3
|
module Cucumber
|
4
4
|
module Formatter
|
5
5
|
# The formatter used for <tt>--format usage</tt>
|
6
|
-
class Usage
|
6
|
+
class Usage
|
7
7
|
include Console
|
8
8
|
|
9
9
|
def initialize(step_mother, io, options)
|
10
|
-
super(step_mother)
|
11
10
|
@io = io
|
12
11
|
@options = options
|
13
12
|
@step_definitions = Hash.new { |h,step_definition| h[step_definition] = [] }
|
@@ -15,17 +14,15 @@ module Cucumber
|
|
15
14
|
@locations = []
|
16
15
|
end
|
17
16
|
|
18
|
-
def
|
19
|
-
super
|
17
|
+
def after_features(features)
|
20
18
|
print_summary(features)
|
21
19
|
end
|
22
20
|
|
23
|
-
def
|
21
|
+
def before_step(step)
|
24
22
|
@step = step
|
25
|
-
super
|
26
23
|
end
|
27
24
|
|
28
|
-
def
|
25
|
+
def step_name(keyword, step_match, status, source_indent, background)
|
29
26
|
if step_match.step_definition
|
30
27
|
location = @step.file_colon_line
|
31
28
|
return if @locations.index(location)
|
@@ -44,7 +41,7 @@ module Cucumber
|
|
44
41
|
sorted_defs.each do |step_definition|
|
45
42
|
step_matches_and_descriptions = @step_definitions[step_definition].sort_by do |step_match_and_description|
|
46
43
|
step_match = step_match_and_description[0]
|
47
|
-
step_match.step_definition.
|
44
|
+
step_match.step_definition.regexp_source
|
48
45
|
end
|
49
46
|
|
50
47
|
step_matches = step_matches_and_descriptions.map{|step_match_and_description| step_match_and_description[0]}
|
@@ -55,7 +52,7 @@ module Cucumber
|
|
55
52
|
lengths << step_definition.text_length
|
56
53
|
max_length = lengths.max
|
57
54
|
|
58
|
-
@io.print step_definition.
|
55
|
+
@io.print step_definition.regexp_source
|
59
56
|
@io.puts format_string(" # #{step_definition.file_colon_line}".indent(max_length - step_definition.text_length), :comment)
|
60
57
|
da = step_matches_and_descriptions.map do |step_match_and_description|
|
61
58
|
step_match = step_match_and_description[0]
|
@@ -76,7 +73,7 @@ module Cucumber
|
|
76
73
|
|
77
74
|
@io.puts format_string("(::) UNUSED (::)", :failed)
|
78
75
|
@all_step_definitions.each do |step_definition|
|
79
|
-
@io.print format_string(step_definition.
|
76
|
+
@io.print format_string(step_definition.regexp_source, :failed)
|
80
77
|
@io.puts format_string(" # #{step_definition.file_colon_line}".indent(max_length - step_definition.text_length), :comment)
|
81
78
|
end
|
82
79
|
end
|
@@ -4,19 +4,19 @@ module Cucumber
|
|
4
4
|
module LanguageSupport
|
5
5
|
module StepDefinitionMethods
|
6
6
|
def step_match(name_to_match, name_to_report)
|
7
|
-
if(
|
8
|
-
StepMatch.new(self, name_to_match, name_to_report,
|
7
|
+
if(arguments = arguments_from(name_to_match))
|
8
|
+
StepMatch.new(self, name_to_match, name_to_report, arguments)
|
9
9
|
else
|
10
10
|
nil
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
def backtrace_line
|
15
|
-
"#{file_colon_line}:in `#{
|
15
|
+
"#{file_colon_line}:in `#{regexp_source}'"
|
16
16
|
end
|
17
17
|
|
18
18
|
def text_length
|
19
|
-
|
19
|
+
regexp_source.jlength
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -1,24 +1,37 @@
|
|
1
1
|
if defined?(ActiveRecord::Base)
|
2
|
-
|
3
|
-
|
2
|
+
Before('~@no-txn') do
|
3
|
+
@__cucumber_use_txn = Cucumber::Rails::World.use_transactional_fixtures
|
4
|
+
Cucumber::Rails::World.use_transactional_fixtures = true
|
5
|
+
end
|
6
|
+
|
7
|
+
Before('@no-txn') do
|
8
|
+
@__cucumber_use_txn = Cucumber::Rails::World.use_transactional_fixtures
|
9
|
+
Cucumber::Rails::World.use_transactional_fixtures = false
|
10
|
+
end
|
11
|
+
|
4
12
|
Before do
|
5
|
-
|
6
|
-
|
7
|
-
@__cucumber_ar_connection.increment_open_transactions
|
8
|
-
|
9
|
-
|
13
|
+
if Cucumber::Rails::World.use_transactional_fixtures
|
14
|
+
@__cucumber_ar_connection = ActiveRecord::Base.connection
|
15
|
+
if @__cucumber_ar_connection.respond_to?(:increment_open_transactions)
|
16
|
+
@__cucumber_ar_connection.increment_open_transactions
|
17
|
+
else
|
18
|
+
ActiveRecord::Base.__send__(:increment_open_transactions)
|
19
|
+
end
|
20
|
+
@__cucumber_ar_connection.begin_db_transaction
|
10
21
|
end
|
11
|
-
@__cucumber_ar_connection.begin_db_transaction
|
12
22
|
ActionMailer::Base.deliveries = [] if defined?(ActionMailer::Base)
|
13
23
|
end
|
14
|
-
|
24
|
+
|
15
25
|
After do
|
16
|
-
|
17
|
-
|
18
|
-
@__cucumber_ar_connection.decrement_open_transactions
|
19
|
-
|
20
|
-
|
26
|
+
if Cucumber::Rails::World.use_transactional_fixtures
|
27
|
+
@__cucumber_ar_connection.rollback_db_transaction
|
28
|
+
if @__cucumber_ar_connection.respond_to?(:decrement_open_transactions)
|
29
|
+
@__cucumber_ar_connection.decrement_open_transactions
|
30
|
+
else
|
31
|
+
ActiveRecord::Base.__send__(:decrement_open_transactions)
|
32
|
+
end
|
21
33
|
end
|
34
|
+
Cucumber::Rails::World.use_transactional_fixtures = @__cucumber_use_txn
|
22
35
|
end
|
23
36
|
else
|
24
37
|
module Cucumber::Rails
|
@@ -3,6 +3,7 @@ require 'cucumber/rb_support/rb_world'
|
|
3
3
|
require 'cucumber/rb_support/rb_step_definition'
|
4
4
|
require 'cucumber/rb_support/rb_hook'
|
5
5
|
require 'cucumber/rb_support/rb_transform'
|
6
|
+
require 'cucumber/rb_support/regexp_argument_matcher'
|
6
7
|
|
7
8
|
module Cucumber
|
8
9
|
module RbSupport
|
@@ -55,6 +56,10 @@ module Cucumber
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
59
|
+
def arguments_from(regexp, step_name)
|
60
|
+
@regexp_argument_matcher.arguments_from(regexp, step_name)
|
61
|
+
end
|
62
|
+
|
58
63
|
def snippet_text(step_keyword, step_name, multiline_arg_class = nil)
|
59
64
|
escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
|
60
65
|
escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'cucumber/step_match'
|
2
2
|
require 'cucumber/core_ext/string'
|
3
3
|
require 'cucumber/core_ext/proc'
|
4
|
-
require 'cucumber/rb_support/
|
4
|
+
require 'cucumber/rb_support/regexp_argument_matcher'
|
5
5
|
|
6
6
|
module Cucumber
|
7
7
|
module RbSupport
|
@@ -24,8 +24,6 @@ module Cucumber
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
attr_reader :proc, :regexp
|
28
|
-
|
29
27
|
def initialize(rb_language, regexp, proc)
|
30
28
|
raise MissingProc if proc.nil?
|
31
29
|
if String === regexp
|
@@ -35,28 +33,23 @@ module Cucumber
|
|
35
33
|
@rb_language, @regexp, @proc = rb_language, regexp, proc
|
36
34
|
end
|
37
35
|
|
36
|
+
def regexp_source
|
37
|
+
@regexp.inspect
|
38
|
+
end
|
39
|
+
|
38
40
|
def ==(step_definition)
|
39
|
-
|
41
|
+
regexp_source == step_definition.regexp_source
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
43
|
-
|
44
|
-
if match
|
45
|
-
n = 0
|
46
|
-
match.captures.map do |val|
|
47
|
-
n += 1
|
48
|
-
RbGroup.new(val, match.offset(n)[0])
|
49
|
-
end
|
50
|
-
else
|
51
|
-
nil
|
52
|
-
end
|
44
|
+
def arguments_from(step_name)
|
45
|
+
RegexpArgumentMatcher.arguments_from(@regexp, step_name)
|
53
46
|
end
|
54
47
|
|
55
48
|
def invoke(args)
|
56
49
|
args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg}
|
57
50
|
begin
|
58
51
|
args = @rb_language.execute_transforms(args)
|
59
|
-
@rb_language.current_world.cucumber_instance_exec(true,
|
52
|
+
@rb_language.current_world.cucumber_instance_exec(true, regexp_source, *args, &@proc)
|
60
53
|
rescue Cucumber::ArityMismatchError => e
|
61
54
|
e.backtrace.unshift(self.backtrace_line)
|
62
55
|
raise e
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cucumber/step_argument'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module RbSupport
|
5
|
+
class RegexpArgumentMatcher
|
6
|
+
def self.arguments_from(regexp, step_name)
|
7
|
+
match = regexp.match(step_name)
|
8
|
+
if match
|
9
|
+
n = 0
|
10
|
+
match.captures.map do |val|
|
11
|
+
n += 1
|
12
|
+
start = match.offset(n)[0]
|
13
|
+
StepArgument.new(val, start)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cucumber/step_match.rb
CHANGED
@@ -2,12 +2,12 @@ module Cucumber
|
|
2
2
|
class StepMatch #:nodoc:
|
3
3
|
attr_reader :step_definition
|
4
4
|
|
5
|
-
def initialize(step_definition, step_name, formatted_step_name,
|
6
|
-
@step_definition, @step_name, @formatted_step_name, @
|
5
|
+
def initialize(step_definition, step_name, formatted_step_name, step_arguments)
|
6
|
+
@step_definition, @step_name, @formatted_step_name, @step_arguments = step_definition, step_name, formatted_step_name, step_arguments
|
7
7
|
end
|
8
8
|
|
9
9
|
def args
|
10
|
-
@
|
10
|
+
@step_arguments.map{|g| g.val}
|
11
11
|
end
|
12
12
|
|
13
13
|
def name
|
@@ -35,8 +35,8 @@ module Cucumber
|
|
35
35
|
#
|
36
36
|
# lambda { |param| "[#{param}]" }
|
37
37
|
#
|
38
|
-
def format_args(format = lambda{|a| a})
|
39
|
-
@formatted_step_name || @step_name
|
38
|
+
def format_args(format = lambda{|a| a}, &proc)
|
39
|
+
@formatted_step_name || replace_arguments(@step_name, @step_arguments, format, &proc)
|
40
40
|
end
|
41
41
|
|
42
42
|
def file_colon_line
|
@@ -50,6 +50,25 @@ module Cucumber
|
|
50
50
|
def text_length
|
51
51
|
@step_definition.text_length
|
52
52
|
end
|
53
|
+
|
54
|
+
def replace_arguments(string, step_arguments, format, &proc)
|
55
|
+
s = string.dup
|
56
|
+
offset = 0
|
57
|
+
step_arguments.each do |step_argument|
|
58
|
+
next if step_argument.pos.nil?
|
59
|
+
replacement = if block_given?
|
60
|
+
proc.call(step_argument.val)
|
61
|
+
elsif Proc === format
|
62
|
+
format.call(step_argument.val)
|
63
|
+
else
|
64
|
+
format % step_argument.val
|
65
|
+
end
|
66
|
+
|
67
|
+
s[step_argument.pos + offset, step_argument.val.jlength] = replacement
|
68
|
+
offset += replacement.length - step_argument.val.jlength
|
69
|
+
end
|
70
|
+
s
|
71
|
+
end
|
53
72
|
end
|
54
73
|
|
55
74
|
class NoStepMatch #:nodoc:
|