gurke 2.1.0 → 2.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c12df541b21f5f76f5956d731764ec23b85e4ac
4
- data.tar.gz: 8397ac6205619fc8667afc0f0694beb0ce395a99
3
+ metadata.gz: d8c96ab204add1ca62ac31c38b6c375324ee89e3
4
+ data.tar.gz: 42ba448e6eaf2bdf6352df493d31036c0ab789cc
5
5
  SHA512:
6
- metadata.gz: e54e0281307bf79d2bea76bf7c0a9b3d84f677669810be1fc0e65a6a6c537700a2869a4969d0ab19fc6e34c5d3c3d3368a97f25136948884bc26a5f5a2aab8d7
7
- data.tar.gz: 490ad37a6ad2a9f3d15db99ec35eabf2694fd82ab5256578d4d1351d63ff9d6241e626dafead371309512b8633f080fdae5edf66604a108399488b846b1c84e6
6
+ metadata.gz: 350ced1ca8fac0b2279ceab141bccd3c16eb358a129de1aa7ed06c960c94a11e61706e4730cc53af2846e2c9e73493e1e29544a8c659b610d2ce7448c183cf36
7
+ data.tar.gz: 2b2831a82dea72c9c8c552e88187ac17574d9bcbce2e69deae41a94efe4e144ea3c5c13ae07052826244ca1a7f962d3e56ec27585e38689be58d1e84370fc713
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## 2.2.1
4
+
5
+ * BugFix (missing argument in cli.rb)
6
+ * BugFix in after_feature hook call (missing feature argument)
7
+
8
+ ## 2.2.0
9
+
10
+ + Support executing all features inside one directory
11
+ + Support reporter selection via cli
12
+ + Add TeamCityReporter (`gurke --formatter team_city`)
13
+ * Support string as step definitions correctly
14
+ * Smaller bugfix in improved exception formatting
15
+
16
+
17
+ ## 2.1.0
18
+
19
+ * Improve exception formating
20
+
21
+ ## 2.0.0
22
+
23
+ * Project start
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Gurke
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/gurke.svg)](http://badge.fury.io/rb/gurke) [![Build Status](http://img.shields.io/travis/jgraichen/gurke/master.svg)](https://travis-ci.org/jgraichen/gurke) [![Code Climate](http://img.shields.io/codeclimate/github/jgraichen/gurke.svg)](https://codeclimate.com/github/jgraichen/gurke) [![Dependency Status](http://img.shields.io/gemnasium/jgraichen/gurke.svg)](https://gemnasium.com/jgraichen/gurke) [![RubyDoc Documentation](http://img.shields.io/badge/rubydoc-here-blue.svg)](http://rubydoc.info/github/jgraichen/gurke/master/frames)
4
+
3
5
  **Gurke** is an experimental, alternative cucumber runner. It ~~steals~~ borrows ideas and concepts from [turnip](https://github.com/jnicklas/turnip), [rspec](http://rspec.info) and tries to avoid [cucumber](https://github.com/cucumber/cucumber/).
4
6
 
5
7
  That includes * Step definitions in modules * Before, After and Around hooks * Formatters * Partial step inclusion (via modules) * etc. Also new ideas like keyword depended step definitions are planned.
@@ -0,0 +1,35 @@
1
+ Feature: Other Reporter
2
+ As a developer
3
+ In order to adjust the output to my requirements (e.g. inside a CI)
4
+ I want to pass a command line argument to change the reporter
5
+
6
+ Background:
7
+ Given I am in a project using gurke
8
+ And a file "features/test.feature" with the following content exists
9
+ """
10
+ Feature: F
11
+ Scenario: Scenario A
12
+ Given this is a success
13
+
14
+ """
15
+ And a file "features/support/steps/test_steps.rb" with the following content exists
16
+ """
17
+ module TestSteps
18
+ step("This is a success") { }
19
+ end
20
+ Gurke.configure{|c| c.include TestSteps }
21
+ """
22
+
23
+ Scenario: Use the default reporter without addition arguments
24
+ When I execute "bundle exec gurke"
25
+ Then the program output should not include "##teamcity"
26
+
27
+ Scenario: Use specified reporter when run with --formatter
28
+ When I execute "bundle exec gurke --formatter team_city"
29
+ Then the program output should include "##teamcity[testStarted name='Scenario A']"
30
+ Then the program output should include "##teamcity[testFinished name='Scenario A']"
31
+
32
+ Scenario: Use specified reporter when run with -f
33
+ When I execute "bundle exec gurke -f team_city"
34
+ Then the program output should include "##teamcity[testStarted name='Scenario A']"
35
+ Then the program output should include "##teamcity[testFinished name='Scenario A']"
@@ -0,0 +1,62 @@
1
+ Feature: Run specific features or scenarios
2
+ In order to get faster test results
3
+ As a user
4
+ I want run only feature files from one directory
5
+
6
+ Background:
7
+ Given I am in a project using gurke
8
+ Given a file "features/odd/a.feature" with the following content exists
9
+ """
10
+ Feature: F
11
+ Bla blub, a longer description.
12
+
13
+ Scenario: Scenario A
14
+ Given I am successful
15
+ """
16
+ Given a file "features/odd/c.feature" with the following content exists
17
+ """
18
+ Feature: F
19
+ Bla blub, a longer description.
20
+
21
+ Scenario: Scenario C
22
+ Given I am successful
23
+ """
24
+ Given a file "features/even/b.feature" with the following content exists
25
+ """
26
+ Feature: F
27
+ Bla blub, a longer description.
28
+
29
+ Scenario: Scenario B
30
+ Given I am successful
31
+ """
32
+ Given a file "trash/b.f" with the following content exists
33
+ """
34
+ Feature: F
35
+ Bla blub, a longer description.
36
+
37
+ Scenario: Scenario B
38
+ Given I am successful
39
+ """
40
+ And a file "features/support/steps/test_steps.rb" with the following content exists
41
+ """
42
+ module TestSteps
43
+ Given("I am successful") { true }
44
+ end
45
+ Gurke.configure{|c| c.include TestSteps }
46
+ """
47
+
48
+ Scenario: Run all features from on directory
49
+ When I execute "bundle exec gurke features/odd"
50
+ And the program output should include "2 scenarios: 0 failing, 0 pending"
51
+
52
+ Scenario: Run all features from on directory (II)
53
+ When I execute "bundle exec gurke features/even"
54
+ And the program output should include "1 scenarios: 0 failing, 0 pending"
55
+
56
+ Scenario: Run all features from on directory (with subdirectories)
57
+ When I execute "bundle exec gurke features"
58
+ And the program output should include "3 scenarios: 0 failing, 0 pending"
59
+
60
+ Scenario: Run all features from on directory (based on feature pattern)
61
+ When I execute "bundle exec gurke trash"
62
+ And the program output should include "0 scenarios: 0 failing, 0 pending"
@@ -21,6 +21,7 @@ module Gurke
21
21
  module Reporters
22
22
  require 'gurke/reporters/null_reporter'
23
23
  require 'gurke/reporters/default_reporter'
24
+ require 'gurke/reporters/team_city_reporter'
24
25
  end
25
26
 
26
27
  class Error < StandardError; end
@@ -28,8 +28,7 @@ module Gurke
28
28
  Dir[r].each{|f| require File.expand_path(f) }
29
29
  end if options[:require].any?
30
30
 
31
- files = Dir[options[:pattern].to_s] if files.empty? && options[:pattern]
32
- files.map!{|f| File.expand_path(f) }
31
+ files = expand_files files, options
33
32
 
34
33
  runner = if options[:drb_server]
35
34
  Runner::DRbServer
@@ -58,6 +57,8 @@ module Gurke
58
57
  opt :help, 'Print this help.'
59
58
  opt :version, 'Show program version information.'
60
59
  opt :backtrace, 'Show full error backtraces.'
60
+ opt :formatter, 'Select a special formatter as reporter', \
61
+ default: 'default'
61
62
  opt :pattern, 'File pattern matching feature files to be run.',
62
63
  default: 'features/**/*.feature'
63
64
  opt :require, 'Files matching this pattern will be required after'\
@@ -73,5 +74,21 @@ module Gurke
73
74
  opt :drb, 'Run features on already started DRb server. (experimental)', short: :none
74
75
  end
75
76
  end
77
+
78
+ private
79
+ def expand_files(files, options)
80
+ files = Dir[options[:pattern].to_s] if files.empty? && options[:pattern]
81
+ files.inject([]) do |memo, input|
82
+ if File.directory? input
83
+ Dir[input + '/**/*'].each do |file_in_dir|
84
+ next if options[:pattern] && !File.fnmatch?(options[:pattern], file_in_dir)
85
+ memo << File.expand_path(file_in_dir)
86
+ end
87
+ else
88
+ memo << File.expand_path(input)
89
+ end
90
+ memo
91
+ end
92
+ end
76
93
  end
77
94
  end
@@ -83,7 +83,7 @@ module Gurke
83
83
  run_feature runner, reporter
84
84
  end
85
85
  ensure
86
- reporter.invoke :after_feature
86
+ reporter.invoke :after_feature, self
87
87
  end
88
88
 
89
89
  private
@@ -255,5 +255,32 @@ module Gurke
255
255
  rescue => e
256
256
  warn "Rescued in reporter: #{e}\n" + e.backtrace.join("\n")
257
257
  end
258
+
259
+
260
+ # @api private
261
+ #
262
+ protected
263
+ def format_exception(ex)
264
+ s = [ex.class.to_s + ': ' + ex.message.strip]
265
+ if ex.backtrace.nil?
266
+ s << ' <no backtrace available>'
267
+ elsif ex.backtrace.empty?
268
+ s << ' <backtrace empty>'
269
+ else
270
+ ex.backtrace.each do |bt|
271
+ s << ' ' + bt.strip
272
+ end
273
+ end
274
+
275
+ if ex.respond_to?(:cause) && ex.cause &&
276
+ ex.cause.respond_to?(:message) && ex.cause.respond_to?(:backtrace)
277
+
278
+ cause = format_exception(ex.cause)
279
+ s << 'caused by: ' + cause.shift
280
+ s += cause
281
+ end
282
+
283
+ s
284
+ end
258
285
  end
259
286
  end
@@ -90,29 +90,6 @@ module Gurke::Reporters
90
90
  io.puts exout.map{|s| red(" #{s}\n") }.join
91
91
  end
92
92
 
93
- def format_exception(ex)
94
- s = [ex.message.strip]
95
- if ex.backtrace.nil?
96
- s << ' <no backtrace available>'
97
- elsif ex.backtrace.empty?
98
- s << ' <backtrace empty>'
99
- else
100
- ex.backtrace.each do |bt|
101
- s << ' ' + bt.strip
102
- end
103
- end
104
-
105
- if ex.respond_to?(:cause) && ex.cause &&
106
- ex.cause.respond_to?(:message) && ex.cause.respond_to?(:backtrace)
107
-
108
- cause = format_exception(ex.cause)
109
- s << 'caused by: ' + cause.shift
110
- s += cause
111
- end
112
-
113
- s
114
- end
115
-
116
93
  [:black, :red, :green, :yellow, :blue,
117
94
  :magenta, :cyan, :white, :default, :light_black,
118
95
  :light_red, :light_green, :light_yellow, :light_blue,
@@ -0,0 +1,128 @@
1
+ module Gurke::Reporters
2
+ #
3
+ # The {TeamCityReporter} prints features, scenarios and
4
+ # steps in a format parseable by TeamCity CI.
5
+ #
6
+ class TeamCityReporter < NullReporter
7
+ attr_reader :io
8
+ def initialize(io = $stdout)
9
+ @io = io
10
+ end
11
+
12
+ def before_feature(feature)
13
+ publish :testSuiteStarted, name: feature.name
14
+ io.puts " #{feature.description.split("\n").join("\n ")}"
15
+ io.puts
16
+ end
17
+
18
+ def before_scenario(scenario)
19
+ @scenario = scenario
20
+ publish :testStarted, name: scenario.name
21
+ end
22
+
23
+ def start_background(*)
24
+ unless @background
25
+ io.puts ' Background:'
26
+ end
27
+
28
+ @background = true
29
+ end
30
+
31
+ def end_background(*)
32
+ @background = false
33
+ end
34
+
35
+ def before_step(step, *)
36
+ io.print ' ' if @background
37
+ io.print ' '
38
+ io.print step.keyword
39
+ io.print step.name
40
+ end
41
+
42
+ def after_step(step, *)
43
+ case step.state
44
+ when :pending then print_pending step
45
+ when :failed then print_failed step
46
+ when :success then print_braces 'success'
47
+ else print_braces 'skipped'
48
+ end
49
+ io.puts
50
+ io.flush
51
+ end
52
+
53
+ def after_scenario(scenario)
54
+ publish :testFinished, name: scenario.name
55
+ end
56
+
57
+ def after_feature(feature)
58
+ publish :testSuiteFinished, name: feature.name
59
+ end
60
+
61
+ def after_features(features)
62
+ scenarios = features.map(&:scenarios).flatten
63
+
64
+ example_count = scenarios.size
65
+ failure_count = scenarios.select(&:failed?).size
66
+ pending_count = scenarios.select(&:pending?).size
67
+
68
+ io.puts " #{example_count} scenarios: " \
69
+ "#{failure_count} failing, " \
70
+ "#{pending_count} pending"
71
+ io.puts
72
+ end
73
+
74
+ private
75
+
76
+ def print_braces(str)
77
+ io.print " (#{str})"
78
+ end
79
+
80
+ def print_pending(step)
81
+ return if @pending == @scenario # only once per scenario
82
+ publish :testPending,
83
+ name: @scenario.name,
84
+ message: 'Step definition missing'
85
+ @pending = @scenario
86
+ end
87
+
88
+ def print_failed(step)
89
+ publish :testFailed,
90
+ name: @scenario.name,
91
+ message: step.exception.inspect,
92
+ backtrace: step.exception.backtrace.join('\n')
93
+
94
+ print_braces 'failure'
95
+ io.puts
96
+
97
+ exout = format_exception(step.exception)
98
+ io.puts exout.map{|s| " #{s}\n" }.join
99
+ end
100
+
101
+
102
+ private
103
+ def publish(message_name, args)
104
+ args = [] << message_name.to_s << escaped_array_of(args)
105
+ args = args.flatten.reject(&:nil?)
106
+
107
+ io.puts "##teamcity[#{args.join(' ')}]"
108
+ end
109
+
110
+ def escape(string)
111
+ string.gsub(/(\||'|\r|\n|\u0085|\u2028|\u2029|\[|\])/, '|$1')
112
+ end
113
+
114
+ def escaped_array_of(args)
115
+ return [] if args.nil?
116
+
117
+ if args.is_a? Hash
118
+ args.map { |key, value| "#{key.to_s}='#{escape value.to_s}'" }
119
+ else
120
+ "'#{escape args}'"
121
+ end
122
+ end
123
+
124
+ def step_name(step)
125
+ step.keyword + step.name.gsub(/"(.*?)"/, '\0')
126
+ end
127
+ end
128
+ end
@@ -8,7 +8,10 @@ module Gurke
8
8
  end
9
9
 
10
10
  def reporter
11
- @reporter ||= Reporters::DefaultReporter.new
11
+ @reporter ||= begin
12
+ r = (options[:formatter] + '_reporter').split('_').map(&:capitalize).join
13
+ Reporters.const_get(r).new
14
+ end
12
15
  end
13
16
 
14
17
  def builder
@@ -16,10 +16,11 @@ module Gurke
16
16
  end
17
17
 
18
18
  def match(name, type = :any)
19
+ return if self.type != :any && self.type != type
20
+ return if pattern.is_a?(String) && name != pattern
19
21
  match = pattern.match(name)
20
22
 
21
23
  return unless match
22
- return if self.type != :any && self.type != type
23
24
 
24
25
  Match.new(method_name, match.to_a[1..-1])
25
26
  end
@@ -1,8 +1,8 @@
1
1
  module Gurke
2
2
  module VERSION
3
3
  MAJOR = 2
4
- MINOR = 1
5
- PATCH = 0
4
+ MINOR = 2
5
+ PATCH = 1
6
6
  STAGE = nil
7
7
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.').freeze
8
8
 
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Gurke::StepDefinition do
6
+ let(:pattern) { nil }
7
+ let(:step_definition) { described_class.new pattern }
8
+ subject { step_definition }
9
+
10
+ context '#match' do
11
+ context 'with regex' do
12
+ let(:pattern) { /dies ist (ein|zwei) regex/ }
13
+
14
+ it { expect(subject.match('dies ist ein regex')).to be_a(Gurke::StepDefinition::Match) }
15
+ it { expect(subject.match('dies ist zwei regex')).to be_a(Gurke::StepDefinition::Match) }
16
+ end
17
+
18
+ context 'with string' do
19
+ let(:pattern) { 'a string' }
20
+
21
+ it { expect(subject.match('a string')).to be_a(Gurke::StepDefinition::Match) }
22
+ it { expect(subject.match(' a string')).to be_nil }
23
+ it { expect(subject.match('a string ')).to be_nil }
24
+ it { expect(subject.match(' a string ')).to be_nil }
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gurke
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
@@ -74,6 +74,7 @@ executables:
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
76
  files:
77
+ - CHANGELOG.md
77
78
  - LICENSE.txt
78
79
  - README.md
79
80
  - bin/gurke
@@ -81,7 +82,9 @@ files:
81
82
  - features/gurke.rb
82
83
  - features/gurke/backtrace_filtering.feature
83
84
  - features/gurke/filter_by_tags.feature
85
+ - features/gurke/other_reporter.feature
84
86
  - features/gurke/pending_steps.feature
87
+ - features/gurke/run_specific_directories.feature
85
88
  - features/gurke/run_specific_scenarios.feature
86
89
  - features/gurke/step_specific_definitions.feature
87
90
  - features/support/steps/cli_steps.rb
@@ -99,6 +102,7 @@ files:
99
102
  - lib/gurke/reporter.rb
100
103
  - lib/gurke/reporters/default_reporter.rb
101
104
  - lib/gurke/reporters/null_reporter.rb
105
+ - lib/gurke/reporters/team_city_reporter.rb
102
106
  - lib/gurke/rspec.rb
103
107
  - lib/gurke/run_list.rb
104
108
  - lib/gurke/runner.rb
@@ -111,6 +115,7 @@ files:
111
115
  - spec/gurke/feature_list_spec.rb
112
116
  - spec/gurke/run_list_spec.rb
113
117
  - spec/gurke/scenario_spec.rb
118
+ - spec/gurke/step_definition_spec.rb
114
119
  - spec/spec_helper.rb
115
120
  homepage: https://github.com/jgraichen/gurke
116
121
  licenses:
@@ -141,7 +146,9 @@ test_files:
141
146
  - features/gurke.rb
142
147
  - features/gurke/backtrace_filtering.feature
143
148
  - features/gurke/filter_by_tags.feature
149
+ - features/gurke/other_reporter.feature
144
150
  - features/gurke/pending_steps.feature
151
+ - features/gurke/run_specific_directories.feature
145
152
  - features/gurke/run_specific_scenarios.feature
146
153
  - features/gurke/step_specific_definitions.feature
147
154
  - features/support/steps/cli_steps.rb
@@ -149,5 +156,6 @@ test_files:
149
156
  - spec/gurke/feature_list_spec.rb
150
157
  - spec/gurke/run_list_spec.rb
151
158
  - spec/gurke/scenario_spec.rb
159
+ - spec/gurke/step_definition_spec.rb
152
160
  - spec/spec_helper.rb
153
161
  has_rdoc: