pdd 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
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