bumps 0.0.4 → 0.1.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.
- data/History.txt +6 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +10 -3
- data/Rakefile +2 -4
- data/TODO +3 -0
- data/examples/feature_server +12 -10
- data/features/push_feature_results.feature +1 -1
- data/features/steps/feature_server.rb +4 -4
- data/features/support/env.rb +10 -2
- data/lib/bumps/configuration.rb +1 -1
- data/lib/bumps/feature.rb +10 -4
- data/lib/bumps/json_formatter.rb +71 -0
- data/lib/bumps/remote_feature.rb +7 -10
- data/lib/bumps_core.rb +2 -1
- data/spec/bumps/configuration_spec.rb +2 -2
- data/spec/bumps/feature_spec.rb +10 -2
- data/spec/bumps/json_formatter_spec.rb +116 -0
- data/spec/bumps/remote_feature_spec.rb +57 -52
- data/test_features/json_formatter_spec/describing_a_feature.feature +8 -0
- data/test_features/json_formatter_spec/describing_a_scenario.feature +4 -0
- data/test_features/json_formatter_spec/describing_a_step.feature +5 -0
- data/test_features/json_formatter_spec/propagating_status_from_step_to_scenario.feature +20 -0
- data/test_features/json_formatter_spec/steps/steps.rb +10 -0
- data/test_features/json_formatter_spec/support/env.rb +1 -0
- metadata +89 -31
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.1.0 2010-06-30
|
2
|
+
|
3
|
+
* Change feature pull format to JSON
|
4
|
+
* Insert ID and version tags into each feature so that information can be pushed back to server
|
5
|
+
* Add JSONFormatter as default formatter - reads ID and version tags and formats push message as JSON
|
6
|
+
|
1
7
|
== 0.0.4 2009-10-13
|
2
8
|
|
3
9
|
* Handle missing connection to push server more gracefully
|
data/Manifest.txt
CHANGED
@@ -17,6 +17,7 @@ lib/bumps.rb
|
|
17
17
|
lib/bumps/configuration.rb
|
18
18
|
lib/bumps/cucumber_config.rb
|
19
19
|
lib/bumps/feature.rb
|
20
|
+
lib/bumps/json_formatter.rb
|
20
21
|
lib/bumps/remote_feature.rb
|
21
22
|
lib/bumps/results_push_formatter.rb
|
22
23
|
lib/bumps_core.rb
|
@@ -26,6 +27,7 @@ script/generate
|
|
26
27
|
spec/bumps/configuration_spec.rb
|
27
28
|
spec/bumps/cucumber_config_spec.rb
|
28
29
|
spec/bumps/feature_spec.rb
|
30
|
+
spec/bumps/json_formatter_spec.rb
|
29
31
|
spec/bumps/remote_feature_spec.rb
|
30
32
|
spec/bumps/results_push_formatter_spec.rb
|
31
33
|
spec/bumps_spec.rb
|
@@ -33,5 +35,11 @@ spec/spec.opts
|
|
33
35
|
spec/spec_helper.rb
|
34
36
|
tasks/rspec.rake
|
35
37
|
tasks/setup.rake
|
38
|
+
test_features/json_formatter_spec/describing_a_feature.feature
|
39
|
+
test_features/json_formatter_spec/describing_a_scenario.feature
|
40
|
+
test_features/json_formatter_spec/describing_a_step.feature
|
41
|
+
test_features/json_formatter_spec/propagating_status_from_step_to_scenario.feature
|
42
|
+
test_features/json_formatter_spec/steps/steps.rb
|
43
|
+
test_features/json_formatter_spec/support/env.rb
|
36
44
|
test_features/remote_content/destroy_dr_thaddeus_venture.feature
|
37
45
|
test_features/requires/support/env.rb
|
data/README.rdoc
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
= Bumps
|
2
2
|
|
3
3
|
* http://github.com/brentsnook/bumps
|
4
|
+
* http://github.com/brentsnook/bumpybot
|
4
5
|
* http://groups.google.com/group/bumps-for-cucumber
|
5
6
|
* http://fuglylogic.com/2009/07/20/bumps-remote-features-for-cucumber/
|
6
7
|
|
@@ -10,6 +11,8 @@ Remote feature management for Cucumber.
|
|
10
11
|
|
11
12
|
Bumps extends {Cucumber}[http://cukes.info] by allowing you to pull feature content and push run results to and from a remote server. This means that your feature files no longer need to live with your steps and other code. This also means that you can publish the results of a Cucumber run to another system.
|
12
13
|
|
14
|
+
Bumps has been designed to work with {Bumpybot}[http://github.com/brentsnook/bumpybot] (a Google Wave robot) but it can be used with any server that meets the {push/pull contract}[http://wiki.github.com/brentsnook/bumps/push-pull-contract].
|
15
|
+
|
13
16
|
See the {wiki}[http://wiki.github.com/brentsnook/bumps] for more details.
|
14
17
|
|
15
18
|
== Installation
|
@@ -24,6 +27,10 @@ Or grab the code from Github and build yourself:
|
|
24
27
|
|
25
28
|
== Synopsis
|
26
29
|
|
30
|
+
To use with Bumpybot, {see the directions}[http://github.com/brentsnook/bumpybot].
|
31
|
+
|
32
|
+
You can also use Bumps with any other compliant server.
|
33
|
+
|
27
34
|
First, start up a server that meets the {push/pull contract}[http://wiki.github.com/brentsnook/bumps/push-pull-contract].
|
28
35
|
|
29
36
|
Secondly, bung this inside of your <b>support/env.rb</b> (or equivalent, just make sure it is under a directory named <b>support</b> under the feature directory):
|
@@ -33,15 +40,15 @@ Secondly, bung this inside of your <b>support/env.rb</b> (or equivalent, just ma
|
|
33
40
|
|
34
41
|
Lastly, just run Cukes as normal.
|
35
42
|
|
36
|
-
cucumber
|
43
|
+
cucumber
|
37
44
|
|
38
|
-
Bumps will pull feature files into the
|
45
|
+
Bumps will pull feature files into the feature directory, run Cukes and then push the results back to the server.
|
39
46
|
|
40
47
|
== License
|
41
48
|
|
42
49
|
(The MIT License)
|
43
50
|
|
44
|
-
Copyright (c) 2009 Brent Snook http://fuglylogic.com
|
51
|
+
Copyright (c) 2009, 2010 Brent Snook http://fuglylogic.com
|
45
52
|
|
46
53
|
Permission is hereby granted, free of charge, to any person obtaining
|
47
54
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -11,8 +11,8 @@ Hoe.spec 'bumps' do
|
|
11
11
|
self.rsync_args = '-av --delete --ignore-errors' # is this needed?
|
12
12
|
|
13
13
|
self.extra_deps = [
|
14
|
-
['cucumber',
|
15
|
-
['
|
14
|
+
['cucumber', '>= 0.3.104'],
|
15
|
+
['json', '>=1.4.3']
|
16
16
|
]
|
17
17
|
|
18
18
|
self.extra_dev_deps = [
|
@@ -31,6 +31,4 @@ task :features => :create_tmp
|
|
31
31
|
require 'newgem/tasks' # load /tasks/*.rake
|
32
32
|
Dir['tasks/**/*.rake'].each { |t| load t }
|
33
33
|
|
34
|
-
# IS THIS NEEDED?
|
35
|
-
Rake::Task[:default].clear_prerequisites # clear out test-unit
|
36
34
|
task :default => [:spec, :features]
|
data/TODO
CHANGED
data/examples/feature_server
CHANGED
@@ -1,27 +1,29 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'sinatra'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
FEATURE_DIR, RESULTS_FILE = ARGV[0..1]
|
5
6
|
|
6
7
|
set :port, 1981
|
7
8
|
|
8
9
|
def feature_content
|
9
|
-
|
10
|
-
content.puts '<?xml version="1.0"?>'
|
11
|
-
content.puts '<features>'
|
10
|
+
features = {}
|
12
11
|
|
13
|
-
Dir.glob(features_pattern).
|
14
|
-
|
12
|
+
Dir.glob(features_pattern).each_with_index do |file, index|
|
13
|
+
features[index] = feature_within(file) if File.file?(file)
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
content.string
|
16
|
+
JSON.generate({'features' => features})
|
20
17
|
end
|
21
18
|
|
22
19
|
def feature_within file
|
23
20
|
relative_path = file[(FEATURE_DIR.length)..-1]
|
24
|
-
|
21
|
+
content = IO.read(file)
|
22
|
+
{
|
23
|
+
'name' => content.match(/Feature: (.*)$/)[1],
|
24
|
+
'version' => '1',
|
25
|
+
'content' => content
|
26
|
+
}
|
25
27
|
end
|
26
28
|
|
27
29
|
def features_pattern
|
@@ -29,7 +31,7 @@ def features_pattern
|
|
29
31
|
end
|
30
32
|
|
31
33
|
get '/features/content' do
|
32
|
-
content_type '
|
34
|
+
content_type 'application/json'
|
33
35
|
feature_content
|
34
36
|
end
|
35
37
|
|
@@ -7,7 +7,7 @@ Feature: Serve feature results
|
|
7
7
|
Scenario: Push all feature results after a run
|
8
8
|
Given that a feature server is running
|
9
9
|
When a cucumber run is performed
|
10
|
-
Then
|
10
|
+
Then JSON formatted feature results will be sent to the server
|
11
11
|
|
12
12
|
Scenario: Feature server not reachable
|
13
13
|
Given that a feature server is not running
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
Given /^that a feature server is running$/ do
|
2
4
|
ScenarioProcess.run feature_server_command, 'feature_server'
|
3
5
|
end
|
@@ -6,9 +8,7 @@ Given /^that a feature server is not running$/ do
|
|
6
8
|
ScenarioProcess.kill feature_server_command
|
7
9
|
end
|
8
10
|
|
9
|
-
Then /^
|
10
|
-
|
11
|
-
push_request.should match(/#{feature}/)
|
12
|
-
end
|
11
|
+
Then /^JSON formatted feature results will be sent to the server$/ do
|
12
|
+
JSON.parse(push_request)['features'].size.should == all_features.size
|
13
13
|
end
|
14
14
|
|
data/features/support/env.rb
CHANGED
@@ -19,7 +19,7 @@ module CucumberWorld
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def push_request_file
|
22
|
-
File.expand_path File.join(ENV['BUMPS_TEMP'], '
|
22
|
+
File.expand_path File.join(ENV['BUMPS_TEMP'], 'pushed_results.txt')
|
23
23
|
end
|
24
24
|
|
25
25
|
def push_request
|
@@ -38,13 +38,21 @@ module CucumberWorld
|
|
38
38
|
"ruby #{feature_server_script} #{remote_features_directory} #{push_request_file}"
|
39
39
|
end
|
40
40
|
|
41
|
+
def all_features
|
42
|
+
Dir.glob("#{remote_features_directory}/**/*")
|
43
|
+
end
|
44
|
+
|
41
45
|
def each_feature
|
42
|
-
|
46
|
+
all_features.each do |feature_file|
|
43
47
|
content = IO.read(feature_file).strip
|
44
48
|
yield content.split("\n").first.strip
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
52
|
+
def feature_count
|
53
|
+
Dir.glob("#{remote_features_directory}/**/*").size
|
54
|
+
end
|
55
|
+
|
48
56
|
def clean
|
49
57
|
FileUtils.remove_entry_secure test_features_directory
|
50
58
|
FileUtils.mkdir test_features_directory
|
data/lib/bumps/configuration.rb
CHANGED
data/lib/bumps/feature.rb
CHANGED
@@ -3,9 +3,9 @@ module Bumps
|
|
3
3
|
|
4
4
|
attr_accessor :name, :content
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
@name =
|
8
|
-
@content =
|
6
|
+
def initialize name, content
|
7
|
+
@name = name
|
8
|
+
@content = content
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.pull
|
@@ -34,7 +34,7 @@ module Bumps
|
|
34
34
|
|
35
35
|
def absolute_path_under directory
|
36
36
|
expanded_directory = File.expand_path directory
|
37
|
-
file_path = File.expand_path(File.join(directory,
|
37
|
+
file_path = File.expand_path(File.join(directory, file_name))
|
38
38
|
unless file_path =~ /^#{expanded_directory}/
|
39
39
|
raise "Could not write feature to path #{file_path}, path is not below #{expanded_directory}"
|
40
40
|
end
|
@@ -50,5 +50,11 @@ module Bumps
|
|
50
50
|
|
51
51
|
true
|
52
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def file_name
|
57
|
+
"#{name.downcase.strip.gsub(' ', '_')}.feature"
|
58
|
+
end
|
53
59
|
end
|
54
60
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Bumps
|
5
|
+
|
6
|
+
class JSONFormatter
|
7
|
+
|
8
|
+
def self.now
|
9
|
+
Time.now
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize step_mother, io, options
|
13
|
+
@io = io
|
14
|
+
@features = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
# required to keep cukes happy
|
18
|
+
def before_features(*args);end
|
19
|
+
|
20
|
+
def tag_name tag
|
21
|
+
name, value = tag.split(":", 2)
|
22
|
+
instance_variable_set(name, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def before_feature(feature)
|
26
|
+
@feature = {
|
27
|
+
'started' => JSONFormatter.now.iso8601,
|
28
|
+
'scenarios' => []
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def scenario_name(keyword, name, file_colon_line, source_indent)
|
33
|
+
@scenario = {
|
34
|
+
'line' => line(file_colon_line),
|
35
|
+
'steps' => []
|
36
|
+
}
|
37
|
+
@feature['scenarios'] << @scenario
|
38
|
+
end
|
39
|
+
|
40
|
+
def after_step(step)
|
41
|
+
@step = {
|
42
|
+
'status' => step.status,
|
43
|
+
'line' => line(step.file_colon_line)
|
44
|
+
}
|
45
|
+
@scenario['steps'] << @step
|
46
|
+
@scenario['status'] = step.status unless step.status == :skipped
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def after_feature(feature)
|
51
|
+
@feature.merge!({'finished' => JSONFormatter.now.iso8601, 'version' => @version})
|
52
|
+
@features[@id] = @feature
|
53
|
+
end
|
54
|
+
|
55
|
+
def after_features(*args)
|
56
|
+
document = {
|
57
|
+
'features' => @features
|
58
|
+
}
|
59
|
+
|
60
|
+
@io.print(document.to_json)
|
61
|
+
@io.flush
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def line(file_colon_line)
|
67
|
+
# ignore first line containing id and version tags
|
68
|
+
file_colon_line.split(':')[1].to_i - 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/bumps/remote_feature.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'nokogiri'
|
2
1
|
require 'open-uri'
|
2
|
+
require 'json'
|
3
3
|
|
4
4
|
module Bumps
|
5
5
|
|
@@ -9,15 +9,12 @@ module Bumps
|
|
9
9
|
parse(open(location){|f| f.read})
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.parse
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
feature.name = feature_element.attribute('name').to_s
|
18
|
-
feature
|
19
|
-
end
|
12
|
+
def self.parse json
|
13
|
+
JSON.parse(json)['features'].collect do |id, feature|
|
14
|
+
content = "@id:#{id} @version:#{feature['version']}\n#{feature['content']}"
|
15
|
+
Feature.new(feature['name'], content)
|
16
|
+
end
|
20
17
|
end
|
21
18
|
|
22
19
|
end
|
23
|
-
end
|
20
|
+
end
|
data/lib/bumps_core.rb
CHANGED
@@ -8,13 +8,14 @@ require 'cucumber'
|
|
8
8
|
'remote_feature',
|
9
9
|
'feature',
|
10
10
|
'configuration',
|
11
|
+
'json_formatter',
|
11
12
|
'results_push_formatter',
|
12
13
|
'cucumber_config'
|
13
14
|
].each {|file| require "bumps/#{file}"}
|
14
15
|
|
15
16
|
module Bumps
|
16
17
|
|
17
|
-
VERSION = '0.0
|
18
|
+
VERSION = '0.1.0'
|
18
19
|
|
19
20
|
def self.configure &block
|
20
21
|
Configuration.configure(&block)
|
@@ -62,8 +62,8 @@ describe Bumps::Configuration do
|
|
62
62
|
subject.results_formatter.should == formatter_class
|
63
63
|
end
|
64
64
|
|
65
|
-
it 'defaults the results formatter to
|
66
|
-
subject.results_formatter.should ==
|
65
|
+
it 'defaults the results formatter to the Bumps JSON formatter' do
|
66
|
+
subject.results_formatter.should == Bumps::JSONFormatter
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'can have only one instance' do
|
data/spec/bumps/feature_spec.rb
CHANGED
@@ -61,6 +61,8 @@ describe Bumps::Feature do
|
|
61
61
|
|
62
62
|
describe 'writing to file' do
|
63
63
|
|
64
|
+
subject {Bumps::Feature.new('', '')}
|
65
|
+
|
64
66
|
it 'uses absolute path' do
|
65
67
|
subject.stub(:absolute_path_under).with('directory').and_return 'path'
|
66
68
|
|
@@ -72,14 +74,20 @@ describe Bumps::Feature do
|
|
72
74
|
it 'uses expanded directory and feature name' do
|
73
75
|
subject.stub!(:name).and_return 'name'
|
74
76
|
|
75
|
-
subject.absolute_path_under('/a/b/c/..').should
|
77
|
+
subject.absolute_path_under('/a/b/c/..').should match(%r{^/a/b/name})
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'creates a file name using feature name' do
|
81
|
+
subject.stub!(:name).and_return ' Do some stuff '
|
82
|
+
|
83
|
+
subject.absolute_path_under('/').should == '/do_some_stuff.feature'
|
76
84
|
end
|
77
85
|
|
78
86
|
it 'fails if given path does not resolve to one below the feature directory' do
|
79
87
|
subject.stub!(:name).and_return '../../etc/bashrc'
|
80
88
|
File.stub! :open # just in case
|
81
89
|
|
82
|
-
lambda {subject.absolute_path_under '/stuff/features'}.should raise_error('Could not write feature to path /etc/bashrc, path is not below /stuff/features')
|
90
|
+
lambda {subject.absolute_path_under '/stuff/features'}.should raise_error('Could not write feature to path /etc/bashrc.feature, path is not below /stuff/features')
|
83
91
|
end
|
84
92
|
|
85
93
|
it 'overwrites existing files' do
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
require 'cucumber/cli/main'
|
5
|
+
|
6
|
+
describe Bumps::JSONFormatter do
|
7
|
+
|
8
|
+
FEATURES_DIR = File.expand_path File.join(File.dirname(__FILE__), '..', '..', 'test_features', 'json_formatter_spec')
|
9
|
+
|
10
|
+
before(:all) { run_cucumber }
|
11
|
+
|
12
|
+
it 'includes all features mapped by id' do
|
13
|
+
[
|
14
|
+
'describing_a_feature',
|
15
|
+
'describing_a_scenario',
|
16
|
+
'describing_a_step',
|
17
|
+
'propagating_status_from_step_to_scenario'
|
18
|
+
].each do |id|
|
19
|
+
@all_features.keys.should include(id)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'propagating status from step to scenario' do
|
24
|
+
before(:all) do
|
25
|
+
@scenarios = @all_features['propagating_status_from_step_to_scenario']['scenarios']
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'propagates passed, failed, pending and undefined statuses' do
|
29
|
+
['passed', 'failed', 'pending', 'undefined'].each_with_index do |status, index|
|
30
|
+
@scenarios[index]['status'].should == status
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "doesn't propagate a skipped status" do
|
35
|
+
@scenarios.last['status'].should == 'failed'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'describing a feature' do
|
40
|
+
|
41
|
+
before(:all) do
|
42
|
+
@feature = @all_features['describing_a_feature']
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'includes version' do
|
46
|
+
@feature['version'].should == '456'
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'timing' do
|
50
|
+
|
51
|
+
before(:all) do
|
52
|
+
start = Time.now
|
53
|
+
finish = start + 10
|
54
|
+
Bumps::JSONFormatter.stub!(:now).and_return start, finish
|
55
|
+
|
56
|
+
run_cucumber
|
57
|
+
|
58
|
+
@feature = @all_features['describing_a_feature']
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'includes the time it started and stopped running in ISO8601 format' do
|
62
|
+
iso8601_format = /[\d]{4}-[\d]{2}-[\d]{2}T[\d]{2}:[\d]{2}:[\d]{2}[+-][\d]{2}:[\d]{2}/
|
63
|
+
@feature['started'].should match(iso8601_format)
|
64
|
+
@feature['finished'].should match(iso8601_format)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should include a finish time equal or greater than the start time' do
|
68
|
+
# may be equal due to second only precision
|
69
|
+
Time.parse(@feature['started']).should be <= Time.parse(@feature['finished'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'includes all scenarios' do
|
74
|
+
@feature['scenarios'].size.should == 3
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'describing a scenario' do
|
79
|
+
|
80
|
+
before(:all) do
|
81
|
+
@scenario = @all_features['describing_a_scenario']['scenarios'].first
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'includes the line that it starts on (ignoring the first tag)' do
|
85
|
+
@scenario['line'] = 3
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'includes all steps' do
|
89
|
+
@scenario['steps'].size == 3
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'describing a step' do
|
95
|
+
|
96
|
+
before(:all) do
|
97
|
+
@step = @all_features['describing_a_step']['scenarios'].first['steps'].first
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'includes the feature file line (ignoring the first tag) but not the step file line' do
|
101
|
+
@step['line'].should == 4
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'includes the status' do
|
105
|
+
@step['status'].should == 'passed'
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
def run_cucumber
|
111
|
+
args = ['-f', 'Bumps::JSONFormatter', FEATURES_DIR]
|
112
|
+
output = `cucumber #{args.join(' ')}`
|
113
|
+
@all_features = JSON.parse(output)['features']
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
describe Bumps::RemoteFeature do
|
4
5
|
|
5
6
|
subject {Bumps::RemoteFeature}
|
6
7
|
|
7
|
-
describe '
|
8
|
+
describe 'fetch' do
|
8
9
|
it 'uses the given location' do
|
9
10
|
subject.should_receive(:open).with('location')
|
10
11
|
subject.stub! :parse
|
@@ -21,63 +22,67 @@ describe Bumps::RemoteFeature do
|
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
describe '
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
<?xml version="1.0"?>
|
35
|
-
<features>
|
36
|
-
<feature name="feature 0">I am the content for feature 0</feature>
|
37
|
-
<feature name="feature 1">I am the content for feature 1</feature>
|
38
|
-
</features>
|
39
|
-
XML
|
25
|
+
describe 'parse' do
|
26
|
+
|
27
|
+
it 'reads the name of a feature' do
|
28
|
+
document = { "features" => {
|
29
|
+
"" => {
|
30
|
+
"content" => "Feature: do stuff",
|
31
|
+
"version" => "",
|
32
|
+
"name" => "Feature name"
|
33
|
+
}
|
34
|
+
}}
|
40
35
|
|
41
|
-
subject.parse(
|
42
|
-
end
|
36
|
+
subject.parse(json_from(document)).first.name.should == 'Feature name'
|
37
|
+
end
|
43
38
|
|
44
|
-
it '
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
</feature>
|
54
|
-
</features>
|
55
|
-
XML
|
39
|
+
it 'reads the content of a feature' do
|
40
|
+
document = { "features" => {
|
41
|
+
"" => {
|
42
|
+
"content" => "Feature: do stuff",
|
43
|
+
"version" => "",
|
44
|
+
"name" => "feature 0"
|
45
|
+
}
|
46
|
+
}}
|
56
47
|
|
57
|
-
subject.parse(
|
58
|
-
end
|
48
|
+
subject.parse(json_from(document)).first.content.should match(/Feature: do stuff/)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'reads all features' do
|
52
|
+
document = { "features" => {
|
53
|
+
"0" => {
|
54
|
+
"content" => "Feature: 0\nI am the content for feature 0",
|
55
|
+
"version" => "3",
|
56
|
+
"name" => "feature 0"
|
57
|
+
},
|
58
|
+
"1" => {
|
59
|
+
"content" => "Feature: 1\nI am the content for feature 1",
|
60
|
+
"version" => "3",
|
61
|
+
"name" => "feature 1"
|
62
|
+
}
|
63
|
+
}}
|
64
|
+
|
65
|
+
subject.parse(json_from(document)).size.should == 2
|
66
|
+
end
|
59
67
|
|
60
|
-
it 'returns an empty list when no features
|
61
|
-
|
62
|
-
<?xml version="1.0"?>
|
63
|
-
<features>
|
64
|
-
</features>
|
65
|
-
XML
|
66
|
-
subject.parse(xml).should eql([])
|
68
|
+
it 'returns an empty list when no features are found' do
|
69
|
+
subject.parse(json_from({ "features" => {}})).size.should == 0
|
67
70
|
end
|
71
|
+
|
72
|
+
it 'embeds metadata about a feature within its content' do
|
73
|
+
document = { "features" => {
|
74
|
+
"123" => {
|
75
|
+
"content" => "Feature: do stuff",
|
76
|
+
"version" => "3",
|
77
|
+
"name" => "feature 0"
|
78
|
+
}
|
79
|
+
}}
|
68
80
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
<![CDATA[content contains <b>CDATA</b> & it should be preserved]]>
|
75
|
-
</feature>
|
76
|
-
</features>
|
77
|
-
XML
|
78
|
-
|
79
|
-
subject.parse(xml).first.content.should match(%r{content contains <b>CDATA</b> & it should be preserved})
|
81
|
+
subject.parse(json_from(document)).first.content.should == "@id:123 @version:3\nFeature: do stuff"
|
82
|
+
end
|
83
|
+
|
84
|
+
def json_from document
|
85
|
+
JSON.generate document
|
80
86
|
end
|
81
|
-
|
82
87
|
end
|
83
88
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
@id:propagating_status_from_step_to_scenario
|
2
|
+
Feature: Feature
|
3
|
+
|
4
|
+
Scenario: passed
|
5
|
+
Given I passed
|
6
|
+
|
7
|
+
Scenario: failed
|
8
|
+
Given I failed
|
9
|
+
And I passed
|
10
|
+
|
11
|
+
Scenario: pending
|
12
|
+
Given I am pending
|
13
|
+
|
14
|
+
Scenario: undefined
|
15
|
+
Given I am undefined
|
16
|
+
|
17
|
+
Scenario: skipped
|
18
|
+
Given I failed
|
19
|
+
And I passed
|
20
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'bumps', 'json_formatter')
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bumps
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Brent Snook
|
@@ -9,74 +15,112 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2010-06-30 00:00:00 +10:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: cucumber
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 195
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 3
|
33
|
+
- 104
|
23
34
|
version: 0.3.104
|
24
|
-
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: nokogiri
|
27
35
|
type: :runtime
|
28
|
-
|
29
|
-
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: json
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
30
42
|
requirements:
|
31
43
|
- - ">="
|
32
44
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
45
|
+
hash: 1
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 4
|
49
|
+
- 3
|
50
|
+
version: 1.4.3
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
35
53
|
- !ruby/object:Gem::Dependency
|
36
54
|
name: rspec
|
37
|
-
|
38
|
-
|
39
|
-
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
40
58
|
requirements:
|
41
59
|
- - ">="
|
42
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 2
|
65
|
+
- 8
|
43
66
|
version: 1.2.8
|
44
|
-
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
45
69
|
- !ruby/object:Gem::Dependency
|
46
70
|
name: newgem
|
47
|
-
|
48
|
-
|
49
|
-
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
50
74
|
requirements:
|
51
75
|
- - ">="
|
52
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 7
|
78
|
+
segments:
|
79
|
+
- 1
|
80
|
+
- 5
|
81
|
+
- 2
|
53
82
|
version: 1.5.2
|
54
|
-
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id004
|
55
85
|
- !ruby/object:Gem::Dependency
|
56
86
|
name: sinatra
|
57
|
-
|
58
|
-
|
59
|
-
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
60
90
|
requirements:
|
61
91
|
- - ">="
|
62
92
|
- !ruby/object:Gem::Version
|
93
|
+
hash: 51
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 9
|
97
|
+
- 4
|
63
98
|
version: 0.9.4
|
64
|
-
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
65
101
|
- !ruby/object:Gem::Dependency
|
66
102
|
name: hoe
|
67
|
-
|
68
|
-
|
69
|
-
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
70
106
|
requirements:
|
71
107
|
- - ">="
|
72
108
|
- !ruby/object:Gem::Version
|
109
|
+
hash: 5
|
110
|
+
segments:
|
111
|
+
- 2
|
112
|
+
- 3
|
113
|
+
- 3
|
73
114
|
version: 2.3.3
|
74
|
-
|
115
|
+
type: :development
|
116
|
+
version_requirements: *id006
|
75
117
|
description: |-
|
76
118
|
Remote feature management for Cucumber.
|
77
119
|
|
78
120
|
Bumps extends {Cucumber}[http://cukes.info] by allowing you to pull feature content and push run results to and from a remote server. This means that your feature files no longer need to live with your steps and other code. This also means that you can publish the results of a Cucumber run to another system.
|
79
121
|
|
122
|
+
Bumps has been designed to work with {Bumpybot}[http://github.com/brentsnook/bumpybot] (a Google Wave robot) but it can be used with any server that meets the {push/pull contract}[http://wiki.github.com/brentsnook/bumps/push-pull-contract].
|
123
|
+
|
80
124
|
See the {wiki}[http://wiki.github.com/brentsnook/bumps] for more details.
|
81
125
|
email:
|
82
126
|
- brent@fuglylogic.com
|
@@ -107,6 +151,7 @@ files:
|
|
107
151
|
- lib/bumps/configuration.rb
|
108
152
|
- lib/bumps/cucumber_config.rb
|
109
153
|
- lib/bumps/feature.rb
|
154
|
+
- lib/bumps/json_formatter.rb
|
110
155
|
- lib/bumps/remote_feature.rb
|
111
156
|
- lib/bumps/results_push_formatter.rb
|
112
157
|
- lib/bumps_core.rb
|
@@ -116,6 +161,7 @@ files:
|
|
116
161
|
- spec/bumps/configuration_spec.rb
|
117
162
|
- spec/bumps/cucumber_config_spec.rb
|
118
163
|
- spec/bumps/feature_spec.rb
|
164
|
+
- spec/bumps/json_formatter_spec.rb
|
119
165
|
- spec/bumps/remote_feature_spec.rb
|
120
166
|
- spec/bumps/results_push_formatter_spec.rb
|
121
167
|
- spec/bumps_spec.rb
|
@@ -123,6 +169,12 @@ files:
|
|
123
169
|
- spec/spec_helper.rb
|
124
170
|
- tasks/rspec.rake
|
125
171
|
- tasks/setup.rake
|
172
|
+
- test_features/json_formatter_spec/describing_a_feature.feature
|
173
|
+
- test_features/json_formatter_spec/describing_a_scenario.feature
|
174
|
+
- test_features/json_formatter_spec/describing_a_step.feature
|
175
|
+
- test_features/json_formatter_spec/propagating_status_from_step_to_scenario.feature
|
176
|
+
- test_features/json_formatter_spec/steps/steps.rb
|
177
|
+
- test_features/json_formatter_spec/support/env.rb
|
126
178
|
- test_features/remote_content/destroy_dr_thaddeus_venture.feature
|
127
179
|
- test_features/requires/support/env.rb
|
128
180
|
has_rdoc: true
|
@@ -136,21 +188,27 @@ rdoc_options:
|
|
136
188
|
require_paths:
|
137
189
|
- lib
|
138
190
|
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
none: false
|
139
192
|
requirements:
|
140
193
|
- - ">="
|
141
194
|
- !ruby/object:Gem::Version
|
195
|
+
hash: 3
|
196
|
+
segments:
|
197
|
+
- 0
|
142
198
|
version: "0"
|
143
|
-
version:
|
144
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
none: false
|
145
201
|
requirements:
|
146
202
|
- - ">="
|
147
203
|
- !ruby/object:Gem::Version
|
204
|
+
hash: 3
|
205
|
+
segments:
|
206
|
+
- 0
|
148
207
|
version: "0"
|
149
|
-
version:
|
150
208
|
requirements: []
|
151
209
|
|
152
210
|
rubyforge_project: bumps
|
153
|
-
rubygems_version: 1.3.
|
211
|
+
rubygems_version: 1.3.7
|
154
212
|
signing_key:
|
155
213
|
specification_version: 3
|
156
214
|
summary: Remote feature management for Cucumber
|