saga 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/.kick CHANGED
@@ -1,12 +1,20 @@
1
1
  recipe :ignore
2
2
  ignore(/(^tmp|\.DS_Store)$/)
3
3
 
4
+ process do |files|
5
+ if files.delete('stories.txt')
6
+ system "./bin/saga planning stories.txt"
7
+ end
8
+ end
9
+
4
10
  recipe :ruby
5
11
  process do |files|
6
12
  Ruby.run_tests(files.take_and_map do |file|
7
13
  case file
8
14
  when %r{^lib/(.+)\.rb$}
9
15
  "test/#{$1.gsub('/', '_')}_spec.rb"
16
+ when %r{^templates}
17
+ "test/saga_formatter_spec.rb"
10
18
  when %r{^test/(.+)_spec\.rb$}
11
19
  file
12
20
  when %r{^test/cases}
data/README.rdoc CHANGED
@@ -59,6 +59,7 @@ The document ends with a list of definitions. Here we define words used througho
59
59
  convert <filename> - convert the stories to HTML
60
60
  inspect <filename> - print the internals of the document
61
61
  autofill <filename> - adds an id to stories without one
62
+ planning <filename> - shows the planning of stories in iterations
62
63
 
63
64
  Options:
64
65
  -h, --help Show help
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.5.1
data/lib/saga.rb CHANGED
@@ -7,6 +7,7 @@ module Saga
7
7
  autoload :Document, 'saga/document'
8
8
  autoload :Formatter, 'saga/formatter'
9
9
  autoload :Parser, 'saga/parser'
10
+ autoload :Planning, 'saga/planning'
10
11
  autoload :Runner, 'saga/runner'
11
12
  autoload :Tokenizer, 'saga/tokenizer'
12
13
 
data/lib/saga/document.rb CHANGED
@@ -33,6 +33,10 @@ module Saga
33
33
  stories.inject(0) { |total, (_, stories)| total + stories.length }
34
34
  end
35
35
 
36
+ def empty?
37
+ length == 0
38
+ end
39
+
36
40
  def autofill_ids
37
41
  unused_ids = unused_ids(length - used_ids.length)
38
42
  stories.each do |_, stories|
@@ -0,0 +1,65 @@
1
+ module Saga
2
+ class Planning
3
+ BLANK_ITERATION = {:story_count => 0, :estimate_total_in_hours => 0}
4
+
5
+ def initialize(document)
6
+ @document = document
7
+ end
8
+
9
+ def iterations
10
+ @document.stories.values.flatten.inject({}) do |properties, story|
11
+ if story[:estimate]
12
+ iteration = story[:iteration] || -1
13
+ properties[iteration] ||= BLANK_ITERATION.dup
14
+ properties[iteration][:story_count] += 1
15
+ properties[iteration][:estimate_total_in_hours] += self.class.estimate_to_hours(story[:estimate])
16
+ end
17
+ properties
18
+ end
19
+ end
20
+
21
+ def total
22
+ total = BLANK_ITERATION.dup
23
+ iterations.each do |iteration, properties|
24
+ total[:story_count] += properties[:story_count]
25
+ total[:estimate_total_in_hours] += properties[:estimate_total_in_hours]
26
+ end
27
+ total
28
+ end
29
+
30
+ def to_s
31
+ if @document.empty?
32
+ "There are no stories yet."
33
+ else
34
+ parts = iterations.keys.sort.map do |iteration|
35
+ self.class.format_properties(iteration, iterations[iteration])
36
+ end
37
+ formatted_totals = self.class.format_properties(false, total)
38
+ parts << '-'*formatted_totals.length
39
+ parts << formatted_totals
40
+ parts.join("\n")
41
+ end
42
+ end
43
+
44
+ def self.estimate_to_hours(estimate)
45
+ case estimate[1]
46
+ when :days
47
+ estimate[0] * 8
48
+ when :weeks
49
+ estimate[0] * 40
50
+ else
51
+ estimate[0]
52
+ end
53
+ end
54
+
55
+ def self.format_properties(iteration, properties)
56
+ if iteration
57
+ label = (iteration == -1) ? "Unplanned" : "Iteration #{iteration}"
58
+ else
59
+ label = 'Total'
60
+ end
61
+ story_column = (properties[:story_count] == 1) ? "#{properties[:story_count]} story" : "#{properties[:story_count]} stories"
62
+ "#{label.ljust(14)}: #{properties[:estimate_total_in_hours]} (#{story_column})"
63
+ end
64
+ end
65
+ end
data/lib/saga/runner.rb CHANGED
@@ -16,6 +16,7 @@ module Saga
16
16
  opts.separator " convert <filename> - convert the stories to HTML"
17
17
  opts.separator " inspect <filename> - print the internals of the document"
18
18
  opts.separator " autofill <filename> - adds an id to stories without one"
19
+ opts.separator " planning <filename> - shows the planning of stories in iterations"
19
20
  opts.separator ""
20
21
  opts.separator "Options:"
21
22
  opts.on("-h", "--help", "Show help") do
@@ -62,6 +63,9 @@ module Saga
62
63
  Saga::Formatter.format(document, :template => 'saga')
63
64
  end
64
65
 
66
+ def planning(filename)
67
+ Saga::Planning.new(Saga::Parser.parse(File.read(filename))).to_s
68
+ end
65
69
 
66
70
  def run_command(command, options)
67
71
  case command
@@ -73,6 +77,8 @@ module Saga
73
77
  write_parsed_document(File.expand_path(@argv[1]))
74
78
  when 'autofill'
75
79
  puts autofill(File.expand_path(@argv[1]))
80
+ when 'planning'
81
+ puts planning(File.expand_path(@argv[1]))
76
82
  else
77
83
  puts convert(File.expand_path(command))
78
84
  end
data/saga.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{saga}
8
- s.version = "0.5.0"
8
+ s.version = "0.5.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Manfred Stienstra"]
12
- s.date = %q{2010-04-02}
12
+ s.date = %q{2010-06-21}
13
13
  s.default_executable = %q{saga}
14
14
  s.description = %q{Saga is a tool to convert stories syntax to a nicely formatted document.}
15
15
  s.email = %q{manfred@fngtps.com}
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
30
30
  "lib/saga/document.rb",
31
31
  "lib/saga/formatter.rb",
32
32
  "lib/saga/parser.rb",
33
+ "lib/saga/planning.rb",
33
34
  "lib/saga/runner.rb",
34
35
  "lib/saga/tokenizer.rb",
35
36
  "saga.gemspec",
@@ -45,6 +46,7 @@ Gem::Specification.new do |s|
45
46
  "test/saga_document_spec.rb",
46
47
  "test/saga_formatter_spec.rb",
47
48
  "test/saga_parser_spec.rb",
49
+ "test/saga_planning_spec.rb",
48
50
  "test/saga_runner_spec.rb",
49
51
  "test/saga_tokenizer_spec.rb",
50
52
  "test/spec_helper.rb"
@@ -52,12 +54,13 @@ Gem::Specification.new do |s|
52
54
  s.homepage = %q{http://fingertips.github.com}
53
55
  s.rdoc_options = ["--charset=UTF-8"]
54
56
  s.require_paths = ["lib"]
55
- s.rubygems_version = %q{1.3.5}
57
+ s.rubygems_version = %q{1.3.7}
56
58
  s.summary = %q{Saga is a tool to convert stories syntax to a nicely formatted document.}
57
59
  s.test_files = [
58
60
  "test/saga_document_spec.rb",
59
61
  "test/saga_formatter_spec.rb",
60
62
  "test/saga_parser_spec.rb",
63
+ "test/saga_planning_spec.rb",
61
64
  "test/saga_runner_spec.rb",
62
65
  "test/saga_tokenizer_spec.rb",
63
66
  "test/spec_helper.rb"
@@ -67,7 +70,7 @@ Gem::Specification.new do |s|
67
70
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
68
71
  s.specification_version = 3
69
72
 
70
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
71
74
  s.add_runtime_dependency(%q<erubis>, [">= 2.6"])
72
75
  s.add_runtime_dependency(%q<activesupport>, [">= 2.3"])
73
76
  s.add_development_dependency(%q<mocha-on-bacon>, [">= 0"])
@@ -29,6 +29,10 @@
29
29
  <p class="author"><%= format_author(author) %></p>
30
30
  <% end %>
31
31
 
32
+ <% introduction.each do |paragraph| %>
33
+ <p><%= paragraph %></p>
34
+ <% end %>
35
+
32
36
  <% unless stories.empty? %>
33
37
  <h2>User stories</h2>
34
38
  <% stories.each do |header, stories| %>
@@ -7,6 +7,10 @@ Requirements <%= title %>
7
7
  <% end -%>
8
8
  <% end -%>
9
9
 
10
+ <% introduction.each do |paragraph| %>
11
+ <%= paragraph %>
12
+
13
+ <% end %>
10
14
  USER STORIES
11
15
  <% stories.each do |header, stories| -%>
12
16
  <% if header.strip == '' %>
@@ -26,7 +26,26 @@ describe "A Document" do
26
26
  document.definitions.keys.should == sections
27
27
  end
28
28
 
29
- it "should return a list of used IDs" do
29
+ it "returns the number of stories as its length" do
30
+ document = Saga::Document.new
31
+ document.length == 0
32
+
33
+ document.stories[''] = [{}, {}]
34
+ document.length.should == 2
35
+
36
+ document.stories['Non-functional'] = [{}]
37
+ document.length.should == 3
38
+ end
39
+
40
+ it "know whether the document does or does not have stories" do
41
+ document = Saga::Document.new
42
+ document.should.be.empty
43
+
44
+ document.stories[''] = [{},{}]
45
+ document.should.not.be.empty
46
+ end
47
+
48
+ it "returns a list of used IDs" do
30
49
  document = Saga::Document.new
31
50
  document.used_ids.should == []
32
51
 
@@ -42,7 +61,7 @@ describe "A Document" do
42
61
  document.used_ids.should == [2, 12, 3]
43
62
  end
44
63
 
45
- it "should return a list of unused IDs" do
64
+ it "returns a list of unused IDs" do
46
65
  document = Saga::Document.new
47
66
  document.unused_ids(0).should == []
48
67
  document.unused_ids(3).should == [1,2,3]
@@ -62,7 +81,7 @@ describe "A Document" do
62
81
  document.unused_ids(4).should == [1,3,7,8]
63
82
  end
64
83
 
65
- it "should autofills ids" do
84
+ it "autofills ids" do
66
85
  document = Saga::Document.new
67
86
  document.autofill_ids
68
87
 
@@ -4,6 +4,18 @@ describe "Formatter" do
4
4
  before do
5
5
  @document = Saga::Document.new
6
6
  @document.title = 'Requirements API'
7
+ @document.authors = [
8
+ {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'},
9
+ {:name => 'Manfred Stienstra', :email => 'manfred@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'}
10
+ ]
11
+ @document.introduction = [
12
+ 'A web service for interfacing with the service.', 'Exposes a public API to the application.'
13
+ ]
14
+ @document.stories = [
15
+ ['General', [
16
+ {:description => 'As a consumer I would like to use TLS (SSL) so that my connection with the API is secure', :id => 4, :status => 'todo' }
17
+ ]]
18
+ ]
7
19
  end
8
20
 
9
21
  it "formats a saga document to HTML" do
@@ -0,0 +1,47 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe "An empty Planning" do
4
+ before do
5
+ @document = Saga::Document.new
6
+ @planning = Saga::Planning.new(@document)
7
+ end
8
+
9
+ it "shows an empty planning message" do
10
+ @planning.to_s.should == 'There are no stories yet.'
11
+ end
12
+ end
13
+
14
+ describe "A simple Planning" do
15
+ before do
16
+ @document = Saga::Document.new
17
+ @document.stories[''] = [{:estimate => [12, :hours]}]
18
+ @planning = Saga::Planning.new(@document)
19
+ end
20
+
21
+ it "shows a planning" do
22
+ @planning.to_s.should ==
23
+ "Unplanned : 12 (1 story)\n"+
24
+ "----------------------------\n"+
25
+ "Total : 12 (1 story)"
26
+ end
27
+ end
28
+
29
+ describe "A complicated Planning" do
30
+ before do
31
+ @document = Saga::Document.new
32
+ @document.stories[''] = [{:estimate => [12, :hours], :iteration => 1}, {:estimate => [8, :hours]}]
33
+ @document.stories['Developer'] = [{:estimate => [1, :weeks], :iteration => 2}, {:estimate => [1, :hours], :iteration => 2}]
34
+ @document.stories['Writer'] = [{:estimate => [5, :hours], :iteration => 1}, {:estimate => [2, :hours], :iteration => 3}]
35
+ @planning = Saga::Planning.new(@document)
36
+ end
37
+
38
+ it "shows a planning" do
39
+ @planning.to_s.should ==
40
+ "Unplanned : 8 (1 story)\n"+
41
+ "Iteration 1 : 17 (2 stories)\n"+
42
+ "Iteration 2 : 41 (2 stories)\n"+
43
+ "Iteration 3 : 2 (1 story)\n"+
44
+ "------------------------------\n"+
45
+ "Total : 68 (6 stories)"
46
+ end
47
+ end
@@ -88,4 +88,12 @@ describe "A Runner" do
88
88
  runner.run
89
89
  end.should == "output\n"
90
90
  end
91
+
92
+ it "shows an overview of the time planned in the different iterations" do
93
+ runner = Saga::Runner.new(%w(planning requirements.txt))
94
+ runner.expects(:planning).with(File.expand_path('requirements.txt')).returns('output')
95
+ collect_stdout do
96
+ runner.run
97
+ end.should == "output\n"
98
+ end
91
99
  end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saga
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 1
10
+ version: 0.5.1
5
11
  platform: ruby
6
12
  authors:
7
13
  - Manfred Stienstra
@@ -9,39 +15,53 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-04-02 00:00:00 +02:00
18
+ date: 2010-06-21 00:00:00 +02:00
13
19
  default_executable: saga
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: erubis
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
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: 15
30
+ segments:
31
+ - 2
32
+ - 6
23
33
  version: "2.6"
24
- version:
34
+ type: :runtime
35
+ version_requirements: *id001
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: activesupport
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
30
41
  requirements:
31
42
  - - ">="
32
43
  - !ruby/object:Gem::Version
44
+ hash: 5
45
+ segments:
46
+ - 2
47
+ - 3
33
48
  version: "2.3"
34
- version:
49
+ type: :runtime
50
+ version_requirements: *id002
35
51
  - !ruby/object:Gem::Dependency
36
52
  name: mocha-on-bacon
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
40
56
  requirements:
41
57
  - - ">="
42
58
  - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
43
62
  version: "0"
44
- version:
63
+ type: :development
64
+ version_requirements: *id003
45
65
  description: Saga is a tool to convert stories syntax to a nicely formatted document.
46
66
  email: manfred@fngtps.com
47
67
  executables:
@@ -63,6 +83,7 @@ files:
63
83
  - lib/saga/document.rb
64
84
  - lib/saga/formatter.rb
65
85
  - lib/saga/parser.rb
86
+ - lib/saga/planning.rb
66
87
  - lib/saga/runner.rb
67
88
  - lib/saga/tokenizer.rb
68
89
  - saga.gemspec
@@ -78,6 +99,7 @@ files:
78
99
  - test/saga_document_spec.rb
79
100
  - test/saga_formatter_spec.rb
80
101
  - test/saga_parser_spec.rb
102
+ - test/saga_planning_spec.rb
81
103
  - test/saga_runner_spec.rb
82
104
  - test/saga_tokenizer_spec.rb
83
105
  - test/spec_helper.rb
@@ -91,21 +113,27 @@ rdoc_options:
91
113
  require_paths:
92
114
  - lib
93
115
  required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
94
117
  requirements:
95
118
  - - ">="
96
119
  - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
97
123
  version: "0"
98
- version:
99
124
  required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
100
126
  requirements:
101
127
  - - ">="
102
128
  - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
103
132
  version: "0"
104
- version:
105
133
  requirements: []
106
134
 
107
135
  rubyforge_project:
108
- rubygems_version: 1.3.5
136
+ rubygems_version: 1.3.7
109
137
  signing_key:
110
138
  specification_version: 3
111
139
  summary: Saga is a tool to convert stories syntax to a nicely formatted document.
@@ -113,6 +141,7 @@ test_files:
113
141
  - test/saga_document_spec.rb
114
142
  - test/saga_formatter_spec.rb
115
143
  - test/saga_parser_spec.rb
144
+ - test/saga_planning_spec.rb
116
145
  - test/saga_runner_spec.rb
117
146
  - test/saga_tokenizer_spec.rb
118
147
  - test/spec_helper.rb