aslakhellesoy-cucumber 0.3.3.4 → 0.3.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,13 @@
1
1
  == 0.3.4 (In Git)
2
2
 
3
- Hooray - speed improvements when using Rake!
3
+ A couple of great new features in this release. Running with Rake is faster than before,
4
+ and there is a brand new JUnit formatter - great for Continuous Integration reports!
4
5
 
5
6
  === Bugfixes
6
7
  * Problem with multiple terms in languages.yml (#321 Aslak Hellesøy)
7
8
 
8
9
  === New features
10
+ * New JUnit formatter (Gareth Jones)
9
11
  * Support for Vietnamese (Ngoc Dao)
10
12
  * Added aliases for Feature and But in Japanese (Leonard Chin)
11
13
  * Support for Catalan (Francesc Esplugas)
@@ -157,6 +157,9 @@ examples/java/features/step_definitons/hello_steps.rb
157
157
  examples/java/features/step_definitons/tree_steps.rb
158
158
  examples/java/features/tree.feature
159
159
  examples/java/src/cucumber/demo/Hello.java
160
+ examples/junit/features/one_passing_one_failing.feature
161
+ examples/junit/features/pending.feature
162
+ examples/junit/features/step_definitions/steps.rb
160
163
  examples/pure_java/README.textile
161
164
  examples/selenium/Rakefile
162
165
  examples/selenium/features/search.feature
@@ -241,6 +244,7 @@ features/cucumber_cli_diff_disabled.feature
241
244
  features/cucumber_cli_outlines.feature
242
245
  features/custom_formatter.feature
243
246
  features/exclude_files.feature
247
+ features/junit_formatter.feature
244
248
  features/multiline_names.feature
245
249
  features/rake_task.feature
246
250
  features/report_called_undefined_steps.feature
@@ -296,6 +300,7 @@ lib/cucumber/formatter/console.rb
296
300
  lib/cucumber/formatter/cucumber.css
297
301
  lib/cucumber/formatter/cucumber.sass
298
302
  lib/cucumber/formatter/html.rb
303
+ lib/cucumber/formatter/junit.rb
299
304
  lib/cucumber/formatter/pretty.rb
300
305
  lib/cucumber/formatter/profile.rb
301
306
  lib/cucumber/formatter/progress.rb
@@ -0,0 +1,8 @@
1
+ Feature: One passing scenario, one failing scenario
2
+
3
+ Scenario: Passing
4
+ Given a passing scenario
5
+
6
+ Scenario: Failing
7
+ Given a failing scenario
8
+
@@ -0,0 +1,5 @@
1
+ Feature: Pending step
2
+
3
+ Scenario: Pending
4
+ Given a pending step
5
+
@@ -0,0 +1,11 @@
1
+ Given /a passing scenario/ do
2
+ #does nothing
3
+ end
4
+
5
+ Given /a failing scenario/ do
6
+ fail
7
+ end
8
+
9
+ Given /a pending step/ do
10
+ pending
11
+ end
@@ -1,29 +1,29 @@
1
- Users want to know that nobody can masquerade as them. We want to extend trust
2
- only to visitors who present the appropriate credentials. Everyone wants this
3
- identity verification to be as secure and convenient as possible.
4
-
5
- Feature: Logging in
6
- As an anonymous user with an account
7
- I want to log in to my account
8
- So that I can be myself
9
-
10
- #
11
- # Log in: get form
12
- #
13
- Scenario: Anonymous user can get a login form.
14
- Given I am logged out
15
- When I go to "/login"
16
- Then I should be at the "sessions/new" page
17
-
18
- #
19
- # Log in successfully, but don't remember me
20
- #
21
- Scenario: Anonymous user can log in
22
- Given an "activated" user named "reggie" exists
23
- And I am logged out
24
- When I go to "/login"
25
- And I fill in "Login" with "reggie"
26
- And I fill in "Password" with "password"
27
- And I press "Log in"
28
- Then I should be at the "dashboard/index" page
29
-
1
+ Users want to know that nobody can masquerade as them. We want to extend trust
2
+ only to visitors who present the appropriate credentials. Everyone wants this
3
+ identity verification to be as secure and convenient as possible.
4
+
5
+ Feature: Logging in
6
+ As an anonymous user with an account
7
+ I want to log in to my account
8
+ So that I can be myself
9
+
10
+ #
11
+ # Log in: get form
12
+ #
13
+ Scenario: Anonymous user can get a login form.
14
+ Given I am logged out
15
+ When I go to "/login"
16
+ Then I should be at the "sessions/new" page
17
+
18
+ #
19
+ # Log in successfully, but don't remember me
20
+ #
21
+ Scenario: Anonymous user can log in
22
+ Given an "activated" user named "reggie" exists
23
+ And I am logged out
24
+ When I go to "/login"
25
+ And I fill in "Login" with "reggie"
26
+ And I fill in "Password" with "password"
27
+ And I press "Log in"
28
+ Then I should be at the "dashboard/index" page
29
+
@@ -1,21 +1,21 @@
1
- Visitors may create an account, but for those who are not already in the
2
- system an someone must activate the account for them before it can be used.
3
-
4
- Feature: Activating an account
5
- As a registered, but not yet activated, user
6
- I want to be able to activate my account
7
- So that I can log in to the site
8
-
9
- Scenario: Not-yet-activated user can activate her account
10
- Given a registered user named 'Reggie' # need to rewrite
11
- # And the user has activation_code: 'activate_me', activated_at: nil!
12
- # And we try hard to remember the user's updated_at, and created_at
13
- # When she goes to /activate/activate_me
14
- # Then she should be redirected to 'login'
15
- # When she follows that redirect!
16
- # Then she should see a notice message 'Signup complete!'
17
- # And a user with login: 'reggie' should exist
18
- # And the user should have login: 'reggie', and email: 'registered@example.com'
19
- # And the user's activation_code should be nil
20
- # And the user's activated_at should not be nil
1
+ Visitors may create an account, but for those who are not already in the
2
+ system an someone must activate the account for them before it can be used.
3
+
4
+ Feature: Activating an account
5
+ As a registered, but not yet activated, user
6
+ I want to be able to activate my account
7
+ So that I can log in to the site
8
+
9
+ Scenario: Not-yet-activated user can activate her account
10
+ Given a registered user named 'Reggie' # need to rewrite
11
+ # And the user has activation_code: 'activate_me', activated_at: nil!
12
+ # And we try hard to remember the user's updated_at, and created_at
13
+ # When she goes to /activate/activate_me
14
+ # Then she should be redirected to 'login'
15
+ # When she follows that redirect!
16
+ # Then she should see a notice message 'Signup complete!'
17
+ # And a user with login: 'reggie' should exist
18
+ # And the user should have login: 'reggie', and email: 'registered@example.com'
19
+ # And the user's activation_code should be nil
20
+ # And the user's activated_at should not be nil
21
21
  # And she should not be logged in
@@ -0,0 +1,59 @@
1
+ Feature: JUnit output formatter
2
+ In order for developers to create test reports with ant
3
+ Cucumber should be able to output JUnit xml files
4
+
5
+ Background:
6
+ Given I am in junit
7
+ And the tmp directory is empty
8
+
9
+ Scenario: one feature, one passing scenario, one failing scenario
10
+ When I run cucumber --format junit --out tmp/ features/one_passing_one_failing.feature
11
+ Then it should fail with
12
+ """
13
+
14
+ """
15
+ And "examples/junit/tmp/TEST-One_passing_scenario__one_failing_scenario.xml" should contain XML
16
+ """
17
+ <?xml version="1.0" encoding="UTF-8"?>
18
+ <testsuite errors="0" tests="2" name="One passing scenario, one failing scenario" failures="1">
19
+ <testcase name="Given a passing scenario" classname="One passing scenario, one failing scenario.Passing">
20
+ </testcase>
21
+ <testcase name="Given a failing scenario" classname="One passing scenario, one failing scenario.Failing">
22
+ <failure message="Given a failing scenario">
23
+ (RuntimeError)
24
+ ./features/step_definitions/steps.rb:6:in `/a failing scenario/'
25
+ features/one_passing_one_failing.feature:7:in `Given a failing scenario' </failure>
26
+ </testcase>
27
+ </testsuite>
28
+
29
+ """
30
+ Scenario: pending step
31
+ When I run cucumber --format junit --out tmp/ features/pending.feature
32
+ Then it should pass with
33
+ """
34
+
35
+ """
36
+ And "examples/junit/tmp/TEST-Pending_step.xml" should contain XML
37
+ """
38
+ <?xml version="1.0" encoding="UTF-8"?>
39
+ <testsuite errors="0" tests="1" name="Pending step" failures="1">
40
+ <testcase name="Given a pending step" classname="Pending step.Pending">
41
+ <failure message="Given a pending step">
42
+ TODO (Cucumber::Pending)
43
+ ./features/step_definitions/steps.rb:10:in `/a pending step/'
44
+ features/pending.feature:4:in `Given a pending step' </failure>
45
+ </testcase>
46
+ </testsuite>
47
+
48
+ """
49
+
50
+ Scenario: run all features
51
+ When I run cucumber --format junit --out tmp/ features
52
+ Then it should fail with
53
+ """
54
+
55
+ """
56
+ And "examples/junit/tmp/TEST-One_passing_scenario__one_failing_scenario.xml" should exist
57
+ And "examples/junit/tmp/TEST-Pending_step.xml" should exist
58
+
59
+
@@ -1,3 +1,5 @@
1
+ require 'tempfile'
2
+
1
3
  Given /^I am in (.*)$/ do |example_dir_relative_path|
2
4
  @current_dir = examples_dir(example_dir_relative_path)
3
5
  end
@@ -10,6 +12,13 @@ Given /^a standard Cucumber project directory structure$/ do
10
12
  end
11
13
  end
12
14
 
15
+ Given /^the (.*) directory is empty$/ do |directory|
16
+ in_current_dir do
17
+ FileUtils.remove_dir(directory) rescue nil
18
+ FileUtils.mkdir 'tmp'
19
+ end
20
+ end
21
+
13
22
  Given /^a file named "([^\"]*)"$/ do |file_name|
14
23
  create_file(file_name, '')
15
24
  end
@@ -53,6 +62,18 @@ Then /^the output should not contain$/ do |text|
53
62
  last_stdout.should_not include(text)
54
63
  end
55
64
 
65
+ # http://diffxml.sourceforge.net/
66
+ Then /^"(.*)" should contain XML$/ do |file, xml|
67
+ t = Tempfile.new('cucumber-junit')
68
+ t.write(xml)
69
+ t.flush
70
+ t.close
71
+ diff = `diffxml #{t.path} #{file}`
72
+ if diff =~ /<delta>/m
73
+ raise diff + "\nXML WAS:\n" + IO.read(file)
74
+ end
75
+ end
76
+
56
77
  Then /^"(.*)" should contain$/ do |file, text|
57
78
  IO.read(file).should == text
58
79
  end
@@ -3,7 +3,7 @@ module Cucumber
3
3
  class YmlLoadError < StandardError; end
4
4
 
5
5
  class Configuration
6
- FORMATS = %w{pretty profile progress rerun}
6
+ FORMATS = %w{pretty profile progress rerun junit}
7
7
  DEFAULT_FORMAT = 'pretty'
8
8
 
9
9
  attr_reader :paths
@@ -66,10 +66,11 @@ module Cucumber
66
66
  @options[:formats][v] = @out_stream
67
67
  @active_format = v
68
68
  end
69
- opts.on("-o", "--out FILE",
70
- "Write output to a file instead of STDOUT. This option",
69
+ opts.on("-o", "--out [FILE|DIR]",
70
+ "Write output to a file/directory instead of STDOUT. This option",
71
71
  "applies to the previously specified --format, or the",
72
- "default format if no format is specified.") do |v|
72
+ "default format if no format is specified. Check the specific",
73
+ "formatter's docs to see whether to pass a file or a dir.") do |v|
73
74
  @options[:formats][@active_format] = v
74
75
  end
75
76
  opts.on("-t TAGS", "--tags TAGS",
@@ -198,10 +199,12 @@ module Cucumber
198
199
  return Formatter::Pretty.new(step_mother, nil, @options) if @options[:autoformat]
199
200
  formatters = @options[:formats].map do |format, out|
200
201
  if String === out # file name
201
- out = File.open(out, Cucumber.file_mode('w'))
202
- at_exit do
203
- out.flush
204
- out.close
202
+ unless File.directory?(out)
203
+ out = File.open(out, Cucumber.file_mode('w'))
204
+ at_exit do
205
+ out.flush
206
+ out.close
207
+ end
205
208
  end
206
209
  end
207
210
 
@@ -209,7 +212,7 @@ module Cucumber
209
212
  formatter_class = formatter_class(format)
210
213
  formatter_class.new(step_mother, out, @options)
211
214
  rescue Exception => e
212
- e.message += "\nError creating formatter: #{format}"
215
+ e.message << "\nError creating formatter: #{format}"
213
216
  raise e
214
217
  end
215
218
  end
@@ -227,6 +230,7 @@ module Cucumber
227
230
  when 'progress' then Formatter::Progress
228
231
  when 'rerun' then Formatter::Rerun
229
232
  when 'usage' then Formatter::Usage
233
+ when 'junit' then Formatter::JUnit
230
234
  else
231
235
  constantize(format)
232
236
  end
@@ -1 +1 @@
1
- %w{color_io pretty progress profile rerun html usage}.each{|n| require "cucumber/formatter/#{n}"}
1
+ %w{color_io pretty progress profile rerun html usage junit}.each{|n| require "cucumber/formatter/#{n}"}
@@ -0,0 +1,78 @@
1
+ begin
2
+ require 'builder'
3
+ rescue LoadError
4
+ gem 'builder'
5
+ require 'builder'
6
+ end
7
+
8
+ module Cucumber
9
+ module Formatter
10
+ class JUnit < Cucumber::Ast::Visitor
11
+
12
+ def initialize(step_mother, io, options)
13
+ super(step_mother)
14
+ @reportdir = io
15
+ raise "You *must* specify --out DIR for the junit formatter" unless @reportdir
16
+ raise "Use --out DIR (not --out FILE) for the junit formatter" if File === @reportdir
17
+ end
18
+
19
+ def visit_feature(feature)
20
+ @failures = @errors = @tests = 0
21
+ @builder = Builder::XmlMarkup.new( :indent => 2 )
22
+ super
23
+
24
+ @testsuite = Builder::XmlMarkup.new( :indent => 2 )
25
+ @testsuite.instruct!
26
+ @testsuite.testsuite(
27
+ :failures => @failures,
28
+ :errors => @errors,
29
+ :tests => @tests,
30
+ :name => @feature_name ) do
31
+ @testsuite << @builder.target!
32
+ end
33
+
34
+ File.open(@feature_filename, 'w') { |file| file.write(@testsuite.target!) }
35
+ end
36
+
37
+ def visit_feature_name(name)
38
+ lines = name.split(/\r?\n/)
39
+ @feature_name = lines[0].sub(/Feature\:/, '').strip
40
+ @feature_filename = convert_to_file_name(@feature_name)
41
+ end
42
+
43
+ def visit_scenario_name(keyword, name, file_colon_line, source_indent)
44
+ @scenario = name
45
+ end
46
+
47
+ def visit_steps(steps)
48
+ @steps_failed = false
49
+ super
50
+ @failures += 1 if @steps_failed
51
+ @tests += 1
52
+ end
53
+
54
+ def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
55
+ step_name = keyword + " " + step_match.format_args(lambda{|param| "*#{param}*"})
56
+ @builder.testcase(:classname => "#{@feature_name}.#{@scenario}", :name => step_name) do
57
+ if status != :passed
58
+ @builder.failure(:message => step_name) do
59
+ @builder.text!(format_exception(exception)) if exception
60
+ end
61
+ @steps_failed = true
62
+ end
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def convert_to_file_name(feature_name)
69
+ @reportdir + "TEST-" + feature_name.gsub(/[^\w_\.]/, '_') + ".xml"
70
+ end
71
+
72
+ def format_exception(exception)
73
+ (["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -481,15 +481,19 @@ module Cucumber
481
481
  end
482
482
 
483
483
  module Background1
484
-
485
484
  def matches_name?(regexp_to_match)
486
485
  name.build =~ regexp_to_match
487
486
  end
488
487
 
489
- def has_tags?(tag_names)
490
- feature_tags = self.parent.tags
491
- feature_tags.has_tags?(tag_names)
492
- end
488
+ def at_line?(line)
489
+ background_keyword.line == line ||
490
+ steps.at_line?(line)
491
+ end
492
+
493
+ def has_tags?(tag_names)
494
+ feature_tags = self.parent.tags
495
+ feature_tags.has_tags?(tag_names)
496
+ end
493
497
 
494
498
  def build
495
499
  Ast::Background.new(
@@ -499,7 +503,7 @@ module Cucumber
499
503
  name.build,
500
504
  steps.build
501
505
  )
502
- end
506
+ end
503
507
  end
504
508
 
505
509
  def _nt_background
@@ -76,27 +76,31 @@ module Cucumber
76
76
  end
77
77
 
78
78
  rule background
79
- comment white background_keyword space* name:lines_to_keyword? (eol+ / eof) steps {
79
+ comment white background_keyword space* name:lines_to_keyword? (eol+ / eof) steps {
80
+ def matches_name?(regexp_to_match)
81
+ name.build =~ regexp_to_match
82
+ end
80
83
 
81
- def matches_name?(regexp_to_match)
82
- name.build =~ regexp_to_match
83
- end
84
+ def at_line?(line)
85
+ background_keyword.line == line ||
86
+ steps.at_line?(line)
87
+ end
84
88
 
85
89
  def has_tags?(tag_names)
86
90
  feature_tags = self.parent.tags
87
91
  feature_tags.has_tags?(tag_names)
88
92
  end
89
93
 
90
- def build
91
- Ast::Background.new(
92
- comment.build,
93
- background_keyword.line,
94
- background_keyword.text_value,
95
- name.build,
96
- steps.build
97
- )
98
- end
99
- }
94
+ def build
95
+ Ast::Background.new(
96
+ comment.build,
97
+ background_keyword.line,
98
+ background_keyword.text_value,
99
+ name.build,
100
+ steps.build
101
+ )
102
+ end
103
+ }
100
104
  end
101
105
 
102
106
  rule feature_elements
@@ -3,7 +3,7 @@ module Cucumber #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
5
  TINY = 3
6
- PATCH = 4 # Set to nil for official release
6
+ PATCH = 5 # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aslakhellesoy-cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3.4
4
+ version: 0.3.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Aslak Helles\xC3\xB8y"
@@ -234,6 +234,9 @@ files:
234
234
  - examples/java/features/step_definitons/tree_steps.rb
235
235
  - examples/java/features/tree.feature
236
236
  - examples/java/src/cucumber/demo/Hello.java
237
+ - examples/junit/features/one_passing_one_failing.feature
238
+ - examples/junit/features/pending.feature
239
+ - examples/junit/features/step_definitions/steps.rb
237
240
  - examples/pure_java/README.textile
238
241
  - examples/selenium/Rakefile
239
242
  - examples/selenium/features/search.feature
@@ -318,6 +321,7 @@ files:
318
321
  - features/cucumber_cli_outlines.feature
319
322
  - features/custom_formatter.feature
320
323
  - features/exclude_files.feature
324
+ - features/junit_formatter.feature
321
325
  - features/multiline_names.feature
322
326
  - features/rake_task.feature
323
327
  - features/report_called_undefined_steps.feature
@@ -373,6 +377,7 @@ files:
373
377
  - lib/cucumber/formatter/cucumber.css
374
378
  - lib/cucumber/formatter/cucumber.sass
375
379
  - lib/cucumber/formatter/html.rb
380
+ - lib/cucumber/formatter/junit.rb
376
381
  - lib/cucumber/formatter/pretty.rb
377
382
  - lib/cucumber/formatter/profile.rb
378
383
  - lib/cucumber/formatter/progress.rb