pdd 0.8 → 0.9

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/Rakefile CHANGED
@@ -26,8 +26,6 @@ require 'rake'
26
26
  require 'rdoc'
27
27
  require 'rake/clean'
28
28
 
29
- CLEAN = FileList['coverage', 'rdoc']
30
-
31
29
  def name
32
30
  @name ||= File.basename(Dir['*.gemspec'].first, '.*')
33
31
  end
@@ -41,6 +39,7 @@ task default: [:clean, :test, :features, :rubocop]
41
39
  require 'rake/testtask'
42
40
  desc 'Run all unit tests'
43
41
  Rake::TestTask.new(:test) do |test|
42
+ Rake::Cleaner.cleanup_files(['coverage'])
44
43
  test.libs << 'lib' << 'test'
45
44
  test.pattern = 'test/**/test_*.rb'
46
45
  test.verbose = false
@@ -64,6 +63,7 @@ end
64
63
 
65
64
  require 'cucumber/rake/task'
66
65
  Cucumber::Rake::Task.new(:features) do |t|
66
+ Rake::Cleaner.cleanup_files(['coverage'])
67
67
  t.profile = 'travis'
68
68
  end
69
69
  Cucumber::Rake::Task.new(:"features:html") do |t|
data/bin/pdd CHANGED
@@ -37,6 +37,7 @@ opts = Slop.parse(ARGV, strict: true, help: true) do
37
37
  on 'f', 'file', 'File to save XML into', argument: :required
38
38
  on 'e', 'exclude', 'Glob pattern to exclude', as: Array, argument: :required
39
39
  on 't', 'format', 'Format to use (xml|html)', argument: :required
40
+ on 'r', 'rule', 'Format to use (xml|html)', argument: :required, as: Array
40
41
  end
41
42
 
42
43
  fail '-f is mandatory when using -v' if opts.verbose? && !opts.file?
@@ -0,0 +1,22 @@
1
+ Feature: Applies Post-Parsing Rules
2
+ As a source code writer I want to be sure that
3
+ certain post-parsing rules are applied
4
+
5
+ Scenario: Throwing exception on invalid estimate
6
+ Given I have a "Sample.java" file with content:
7
+ """
8
+ @todo #13:180m This puzzle has too big estimate
9
+ """
10
+ When I run bin/pdd with "--rule=max-estimate:90"
11
+ Then Exit code is not zero
12
+ Then Stdout contains "bigger than 90 minutes"
13
+
14
+ Scenario: Throwing exception on invalid estimate
15
+ Given I have a "Sample.java" file with content:
16
+ """
17
+ @todo #13:15min This puzzle has too small estimate
18
+ """
19
+ When I run bin/pdd with "--rule=min-estimate:30"
20
+ Then Exit code is not zero
21
+ Then Stdout contains "lower than 30 minutes"
22
+
@@ -72,7 +72,7 @@ end
72
72
 
73
73
  When(/^I run bin\/pdd with "([^"]*)"$/) do |arg|
74
74
  home = File.join(File.dirname(__FILE__), '../..')
75
- @stdout = `ruby -I#{home}/lib #{home}/bin/pdd #{arg}`
75
+ @stdout = `ruby -I#{home}/lib #{home}/bin/pdd #{arg} 2>&1`
76
76
  @exitstatus = $CHILD_STATUS.exitstatus
77
77
  end
78
78
 
data/lib/pdd.rb CHANGED
@@ -23,6 +23,8 @@
23
23
 
24
24
  require 'pdd/sources'
25
25
  require 'pdd/version'
26
+ require 'pdd/rule/estimates'
27
+ require 'pdd/rule/text'
26
28
  require 'nokogiri'
27
29
  require 'logger'
28
30
  require 'time'
@@ -40,6 +42,12 @@ module PDD
40
42
  class SchemaError < Error
41
43
  end
42
44
 
45
+ RULES = {
46
+ 'min-estimate' => PDD::Rule::Estimate::Min,
47
+ 'max-estimate' => PDD::Rule::Estimate::Max,
48
+ 'min-words' => PDD::Rule::Text::MinWords
49
+ }
50
+
43
51
  # Get logger.
44
52
  def self.log
45
53
  unless @log
@@ -74,20 +82,22 @@ module PDD
74
82
  sources = sources.exclude(p)
75
83
  PDD.log.info "excluding #{p}"
76
84
  end unless @opts[:exclude].nil?
77
- sanitize(
78
- Nokogiri::XML::Builder.new do |xml|
79
- xml << "<?xml-stylesheet type='text/xsl' href='#{xsl}'?>"
80
- xml.puzzles(attrs) do
81
- sources.fetch.each do |source|
82
- source.puzzles.each do |puzzle|
83
- PDD.log.info "puzzle #{puzzle.props[:ticket]}:" \
84
- "#{puzzle.props[:estimate]}/#{puzzle.props[:role]}" \
85
- " at #{puzzle.props[:file]}"
86
- render puzzle, xml
85
+ rules(
86
+ sanitize(
87
+ Nokogiri::XML::Builder.new do |xml|
88
+ xml << "<?xml-stylesheet type='text/xsl' href='#{xsl}'?>"
89
+ xml.puzzles(attrs) do
90
+ sources.fetch.each do |source|
91
+ source.puzzles.each do |puzzle|
92
+ PDD.log.info "puzzle #{puzzle.props[:ticket]}:" \
93
+ "#{puzzle.props[:estimate]}/#{puzzle.props[:role]}" \
94
+ " at #{puzzle.props[:file]}"
95
+ render puzzle, xml
96
+ end
87
97
  end
88
98
  end
89
- end
90
- end.to_xml
99
+ end.to_xml
100
+ )
91
101
  )
92
102
  end
93
103
 
@@ -119,6 +129,23 @@ module PDD
119
129
  end
120
130
  end
121
131
 
132
+ def rules(xml)
133
+ doc = Nokogiri::XML(xml)
134
+ total = 0
135
+ @opts[:rule].map do |r|
136
+ name, value = r.split(':')
137
+ rule = RULES[name]
138
+ fail "rule '#{name}' doesn't exist" if rule.nil?
139
+ rule.new(doc, value.to_i).errors.each do |e|
140
+ puts e
141
+ PDD.log.error e
142
+ total += 1
143
+ end
144
+ end unless @opts[:rule].nil?
145
+ fail "#{total} errors, see log above" unless total == 0
146
+ xml
147
+ end
148
+
122
149
  def sanitize(xml)
123
150
  xsd = Nokogiri::XML::Schema(
124
151
  File.read(File.join(File.dirname(__FILE__), '../assets/puzzles.xsd'))
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2014 TechnoPark Corp.
4
+ # Copyright (c) 2014 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ module PDD
25
+ module Rule
26
+ module Estimate
27
+ # Rule for min estimate.
28
+ class Min
29
+ # Ctor.
30
+ # +xml+:: XML with puzzles
31
+ def initialize(xml, min)
32
+ @xml = xml
33
+ @min = min
34
+ end
35
+
36
+ def errors
37
+ @xml.xpath("//puzzle[number(estimate) < #{@min}]").map do |p|
38
+ "puzzle #{p.xpath('file/text()')}:#{p.xpath('lines/text()')}"\
39
+ " has an estimate of #{p.xpath('estimate/text()')} minutes,"\
40
+ " which is lower than #{@min} minutes"
41
+ end
42
+ end
43
+ end
44
+
45
+ # Rule for max estimate.
46
+ class Max
47
+ # Ctor.
48
+ # +xml+:: XML with puzzles
49
+ def initialize(xml, min)
50
+ @xml = xml
51
+ @min = min
52
+ end
53
+
54
+ def errors
55
+ @xml.xpath("//puzzle[number(estimate) > #{@min}]").map do |p|
56
+ "puzzle #{p.xpath('file/text()')}:#{p.xpath('lines/text()')}"\
57
+ " has an estimate of #{p.xpath('estimate/text()')} minutes,"\
58
+ " which is bigger than #{@min} minutes"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2014 TechnoPark Corp.
4
+ # Copyright (c) 2014 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ module PDD
25
+ module Rule
26
+ module Text
27
+ # Rule for minimum length of description.
28
+ class MinWords
29
+ # Ctor.
30
+ # +xml+:: XML with puzzles
31
+ def initialize(xml, min)
32
+ @xml = xml
33
+ @min = min
34
+ end
35
+
36
+ def errors
37
+ @xml.xpath('//puzzle').map do |p|
38
+ words = p.xpath('body/text()').to_s.split.size
39
+ next nil if words >= @min
40
+ "puzzle #{p.xpath('file/text()')}:#{p.xpath('lines/text()')}"\
41
+ " has a very short description of just #{words} words while"\
42
+ " a minimum of #{@min} is required"
43
+ end.compact
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -75,7 +75,7 @@ module PDD
75
75
  rescue Error => ex
76
76
  raise Error, "#{ex.message} in line ##{idx}"
77
77
  end
78
- body = (match[3] + ' ' + tail.join(' ')).gsub(/\s+/, ' ').strip
78
+ body = (match[3] + ' ' + tail.join(' ')).gsub(/[\s\n\t]+/, ' ').strip
79
79
  Puzzle.new(
80
80
  marker(match[2]).merge(
81
81
  lines: "#{idx + 1}-#{idx + tail.size + 1}",
@@ -26,5 +26,5 @@
26
26
  # Copyright:: Copyright (c) 2014 Yegor Bugayenko
27
27
  # License:: MIT
28
28
  module PDD
29
- VERSION = '0.8'
29
+ VERSION = '0.9'
30
30
  end
@@ -23,3 +23,4 @@
23
23
 
24
24
  require 'simplecov'
25
25
  require 'pdd'
26
+ require 'minitest/autorun'
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2014 TechnoPark Corp.
4
+ # Copyright (c) 2014 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require 'nokogiri'
26
+ require 'pdd/rule/estimates'
27
+
28
+ # PDD::Rule::Estimate module tests.
29
+ # Author:: Yegor Bugayenko (yegor@teamed.io)
30
+ # Copyright:: Copyright (c) 2014 Yegor Bugayenko
31
+ # License:: MIT
32
+ class TestEstimates < Minitest::Test
33
+ def test_min
34
+ rule = PDD::Rule::Estimate::Min.new(
35
+ Nokogiri::XML::Document.parse(
36
+ '<puzzles><puzzle><estimate>15</estimate></puzzle></puzzles>'
37
+ ), 30
38
+ )
39
+ assert !rule.errors.empty?, 'why it is empty?'
40
+ end
41
+
42
+ def test_max
43
+ rule = PDD::Rule::Estimate::Max.new(
44
+ Nokogiri::XML::Document.parse(
45
+ '<puzzles><puzzle><estimate>30</estimate></puzzle></puzzles>'
46
+ ), 15
47
+ )
48
+ assert !rule.errors.empty?, 'why it is empty?'
49
+ end
50
+ end
@@ -34,11 +34,7 @@ require 'slop'
34
34
  class TestPDD < Minitest::Test
35
35
  def test_basic
36
36
  Dir.mktmpdir 'test' do |dir|
37
- opts = Slop.parse ['-v', '-s', dir, '-e', '**/*.png'] do
38
- on 'v', 'verbose'
39
- on 's', 'source', argument: :required
40
- on 'e', 'exclude', as: Array, argument: :required
41
- end
37
+ opts = opts(['-v', '-s', dir, '-e', '**/*.png', '-r', 'max-estimate:15'])
42
38
  File.write(File.join(dir, 'a.txt'), '@todo #55 hello!')
43
39
  matches(
44
40
  Nokogiri::XML::Document.parse(PDD::Base.new(opts).xml),
@@ -53,6 +49,25 @@ class TestPDD < Minitest::Test
53
49
  end
54
50
  end
55
51
 
52
+ def test_rules_failure
53
+ Dir.mktmpdir 'test' do |dir|
54
+ opts = opts(['-v', '-s', dir, '-e', '**/*.png', '-r', 'min-estimate:30'])
55
+ File.write(File.join(dir, 'a.txt'), '@todo #90 hello!')
56
+ assert_raises RuntimeError do
57
+ PDD::Base.new(opts).xml
58
+ end
59
+ end
60
+ end
61
+
62
+ def opts(args)
63
+ Slop.parse args do
64
+ on 'v', 'verbose'
65
+ on 's', 'source', argument: :required
66
+ on 'e', 'exclude', as: Array, argument: :required
67
+ on 'r', 'rule', as: Array, argument: :required
68
+ end
69
+ end
70
+
56
71
  def matches(xml, xpaths)
57
72
  xpaths.each do |xpath|
58
73
  fail "doesn't match '#{xpath}': #{xml}" unless xml.xpath(xpath).size == 1
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2014 TechnoPark Corp.
4
+ # Copyright (c) 2014 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require 'nokogiri'
26
+ require 'pdd/rule/text'
27
+
28
+ # PDD::Rule::Text module tests.
29
+ # Author:: Yegor Bugayenko (yegor@teamed.io)
30
+ # Copyright:: Copyright (c) 2014 Yegor Bugayenko
31
+ # License:: MIT
32
+ class TestText < Minitest::Test
33
+ def test_min_words
34
+ rule = PDD::Rule::Text::MinWords.new(
35
+ Nokogiri::XML::Document.parse(
36
+ '<puzzles><puzzle><body>short text</body></puzzle>
37
+ <puzzle><body>body with four words</body></puzzle></puzzles>'
38
+ ), 4
39
+ )
40
+ assert rule.errors.size == 1
41
+ end
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdd
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.8'
4
+ version: '0.9'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-02 00:00:00.000000000 Z
12
+ date: 2014-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -210,6 +210,7 @@ files:
210
210
  - assets/puzzles.xsl
211
211
  - bin/pdd
212
212
  - cucumber.yml
213
+ - features/applies_rules.feature
213
214
  - features/avoiding_duplicates.feature
214
215
  - features/catches_broken_puzzles.feature
215
216
  - features/cli.feature
@@ -221,14 +222,18 @@ files:
221
222
  - features/unicode.feature
222
223
  - lib/pdd.rb
223
224
  - lib/pdd/puzzle.rb
225
+ - lib/pdd/rule/estimates.rb
226
+ - lib/pdd/rule/text.rb
224
227
  - lib/pdd/source.rb
225
228
  - lib/pdd/sources.rb
226
229
  - lib/pdd/version.rb
227
230
  - pdd.gemspec
228
- - test/test_helper.rb
231
+ - test/test__helper.rb
232
+ - test/test_estimates.rb
229
233
  - test/test_pdd.rb
230
234
  - test/test_source.rb
231
235
  - test/test_sources.rb
236
+ - test/test_text.rb
232
237
  homepage: http://github.com/teamed/pdd
233
238
  licenses:
234
239
  - MIT
@@ -256,6 +261,7 @@ signing_key:
256
261
  specification_version: 2
257
262
  summary: Puzzle Driven Development collector
258
263
  test_files:
264
+ - features/applies_rules.feature
259
265
  - features/avoiding_duplicates.feature
260
266
  - features/catches_broken_puzzles.feature
261
267
  - features/cli.feature
@@ -265,7 +271,9 @@ test_files:
265
271
  - features/step_definitions/steps.rb
266
272
  - features/support/env.rb
267
273
  - features/unicode.feature
268
- - test/test_helper.rb
274
+ - test/test__helper.rb
275
+ - test/test_estimates.rb
269
276
  - test/test_pdd.rb
270
277
  - test/test_source.rb
271
278
  - test/test_sources.rb
279
+ - test/test_text.rb