pdd 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.coveralls.yml +2 -0
- data/.gitignore +1 -0
- data/.simplecov +34 -0
- data/README.md +25 -0
- data/asserts/puzzles.xsd +82 -0
- data/asserts/puzzles.xsl +80 -0
- data/bin/pdd +15 -1
- data/features/avoiding_duplicates.feature +18 -0
- data/features/cli.feature +24 -0
- data/features/parsing.feature +2 -2
- data/features/step_definitions/steps.rb +42 -1
- data/features/support/env.rb +27 -0
- data/lib/pdd.rb +48 -10
- data/lib/pdd/source.rb +1 -1
- data/pdd.gemspec +4 -1
- data/test/test_helper.rb +27 -0
- data/test/test_pdd.rb +7 -2
- metadata +69 -1
data/.coveralls.yml
ADDED
data/.gitignore
CHANGED
data/.simplecov
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: 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 'coveralls'
|
25
|
+
|
26
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
27
|
+
SimpleCov::Formatter::HTMLFormatter,
|
28
|
+
Coveralls::SimpleCov::Formatter
|
29
|
+
]
|
30
|
+
SimpleCov.start do
|
31
|
+
add_filter "/test/"
|
32
|
+
add_filter "/features/"
|
33
|
+
minimum_coverage 100
|
34
|
+
end
|
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
[![Build Status](http://img.teamed.io/btn/125x25.svg)](http://www.teamed.io)
|
2
|
+
|
1
3
|
[![Build Status](https://travis-ci.org/teamed/pdd.svg)](https://travis-ci.org/teamed/pdd)
|
2
4
|
[![Gem Version](https://badge.fury.io/rb/pdd.svg)](http://badge.fury.io/rb/pdd)
|
3
5
|
[![Dependency Status](https://gemnasium.com/teamed/pdd.svg)](https://gemnasium.com/teamed/pdd)
|
4
6
|
[![Code Climate](http://img.shields.io/codeclimate/github/teamed/pdd.svg)](https://codeclimate.com/github/teamed/pdd)
|
7
|
+
[![Coverage Status](https://img.shields.io/coveralls/teamed/pdd.svg)](https://coveralls.io/r/teamed/pdd)
|
5
8
|
|
6
9
|
Install it first:
|
7
10
|
|
@@ -14,3 +17,25 @@ Run it locally:
|
|
14
17
|
```bash
|
15
18
|
pdd
|
16
19
|
```
|
20
|
+
|
21
|
+
Every puzzle has to be formatted like this:
|
22
|
+
|
23
|
+
```java
|
24
|
+
/**
|
25
|
+
* @todo #234:15m/DEV This is something to do later
|
26
|
+
* in one of the next releases
|
27
|
+
*/
|
28
|
+
```
|
29
|
+
|
30
|
+
It starts with `@todo`, followed by a space and a puzzle marker.
|
31
|
+
Possible formats of puzzle markers:
|
32
|
+
|
33
|
+
```
|
34
|
+
#224
|
35
|
+
#TEST-13
|
36
|
+
#55:45min
|
37
|
+
#67/DES
|
38
|
+
```
|
39
|
+
|
40
|
+
Read this article about
|
41
|
+
[Puzzle Drive Development](http://www.xdsd.org/2009/03/04/pdd.html).
|
data/asserts/puzzles.xsd
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
<?xml version="1.0"?>
|
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
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
25
|
+
<xs:complexType name="puzzle">
|
26
|
+
<xs:all>
|
27
|
+
<xs:element name="ticket">
|
28
|
+
<xs:simpleType>
|
29
|
+
<xs:restriction base="xs:string">
|
30
|
+
<xs:minLength value="1"/>
|
31
|
+
</xs:restriction>
|
32
|
+
</xs:simpleType>
|
33
|
+
</xs:element>
|
34
|
+
<xs:element name="body">
|
35
|
+
<xs:simpleType>
|
36
|
+
<xs:restriction base="xs:string">
|
37
|
+
<xs:minLength value="1"/>
|
38
|
+
</xs:restriction>
|
39
|
+
</xs:simpleType>
|
40
|
+
</xs:element>
|
41
|
+
<xs:element name="estimate">
|
42
|
+
<xs:simpleType>
|
43
|
+
<xs:restriction base="xs:integer">
|
44
|
+
<xs:minInclusive value="0"/>
|
45
|
+
</xs:restriction>
|
46
|
+
</xs:simpleType>
|
47
|
+
</xs:element>
|
48
|
+
<xs:element name="file">
|
49
|
+
<xs:simpleType>
|
50
|
+
<xs:restriction base="xs:string">
|
51
|
+
<xs:minLength value="1"/>
|
52
|
+
</xs:restriction>
|
53
|
+
</xs:simpleType>
|
54
|
+
</xs:element>
|
55
|
+
<xs:element name="lines">
|
56
|
+
<xs:simpleType>
|
57
|
+
<xs:restriction base="xs:string">
|
58
|
+
<xs:pattern value="[0-9]+-[0-9]+"/>
|
59
|
+
</xs:restriction>
|
60
|
+
</xs:simpleType>
|
61
|
+
</xs:element>
|
62
|
+
<xs:element name="role">
|
63
|
+
<xs:simpleType>
|
64
|
+
<xs:restriction base="xs:string">
|
65
|
+
<xs:pattern value="[A-Z]+"/>
|
66
|
+
</xs:restriction>
|
67
|
+
</xs:simpleType>
|
68
|
+
</xs:element>
|
69
|
+
</xs:all>
|
70
|
+
</xs:complexType>
|
71
|
+
<xs:element name="puzzles">
|
72
|
+
<xs:complexType>
|
73
|
+
<xs:sequence>
|
74
|
+
<xs:element name="puzzle" type="puzzle" minOccurs="0" maxOccurs="unbounded" />
|
75
|
+
</xs:sequence>
|
76
|
+
</xs:complexType>
|
77
|
+
<xs:unique name="puzzleBody">
|
78
|
+
<xs:selector xpath="./puzzle" />
|
79
|
+
<xs:field xpath="body" />
|
80
|
+
</xs:unique>
|
81
|
+
</xs:element>
|
82
|
+
</xs:schema>
|
data/asserts/puzzles.xsl
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
<?xml version="1.0"?>
|
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
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
25
|
+
version="1.0" xmlns="http://www.w3.org/1999/xhtml">
|
26
|
+
<xsl:template match="/">
|
27
|
+
<xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text>
|
28
|
+
<html lang="en">
|
29
|
+
<head>
|
30
|
+
<meta charset="UTF-8"/>
|
31
|
+
<meta name="description" content="PDD puzzles"/>
|
32
|
+
<meta name="keywords" content="puzzle driven development"/>
|
33
|
+
<meta name="author" content="teamed.io"/>
|
34
|
+
<title><xsl:text>PDD Summary Report</xsl:text></title>
|
35
|
+
</head>
|
36
|
+
<body>
|
37
|
+
<div>
|
38
|
+
<h1>Puzzle Driven Development (PDD) Summary Report</h1>
|
39
|
+
<table>
|
40
|
+
<colgroup>
|
41
|
+
<col/>
|
42
|
+
<col/>
|
43
|
+
<col/>
|
44
|
+
<col/>
|
45
|
+
<col style="width:7em;"/>
|
46
|
+
<col/>
|
47
|
+
</colgroup>
|
48
|
+
<thead>
|
49
|
+
<tr>
|
50
|
+
<th><xsl:text>ticket</xsl:text></th>
|
51
|
+
<th><xsl:text>body</xsl:text></th>
|
52
|
+
<th><xsl:text>estimate</xsl:text></th>
|
53
|
+
<th><xsl:text>owner</xsl:text></th>
|
54
|
+
</tr>
|
55
|
+
</thead>
|
56
|
+
<tbody>
|
57
|
+
<xsl:apply-templates select="puzzles/puzzle"/>
|
58
|
+
</tbody>
|
59
|
+
</table>
|
60
|
+
</div>
|
61
|
+
</body>
|
62
|
+
</html>
|
63
|
+
</xsl:template>
|
64
|
+
<xsl:template match="puzzle">
|
65
|
+
<tr>
|
66
|
+
<td><xsl:value-of select="ticket"/></td>
|
67
|
+
<td>
|
68
|
+
<code>
|
69
|
+
<xsl:value-of select="file"/>
|
70
|
+
<xsl:text>:</xsl:text>
|
71
|
+
<xsl:value-of select="lines"/>
|
72
|
+
</code>
|
73
|
+
<br/>
|
74
|
+
<xsl:value-of select="body"/>
|
75
|
+
</td>
|
76
|
+
<td><xsl:value-of select="estimate"/></td>
|
77
|
+
<td><xsl:value-of select="owner"/></td>
|
78
|
+
</tr>
|
79
|
+
</xsl:template>
|
80
|
+
</xsl:stylesheet>
|
data/bin/pdd
CHANGED
@@ -25,5 +25,19 @@
|
|
25
25
|
STDOUT.sync = true
|
26
26
|
|
27
27
|
require 'pdd'
|
28
|
+
require 'slop'
|
28
29
|
|
29
|
-
|
30
|
+
opts = Slop.parse do
|
31
|
+
banner 'Usage: pdd [options]'
|
32
|
+
on 'h', 'help', 'Print this page'
|
33
|
+
on 'v', 'verbose', 'Enable verbose mode'
|
34
|
+
on 's', 'source', 'Source directory to parse', argument: :required
|
35
|
+
on 'f', 'file', 'File to save XML into', argument: :required
|
36
|
+
end
|
37
|
+
|
38
|
+
if opts.help?
|
39
|
+
puts opts
|
40
|
+
else
|
41
|
+
file = opts.file? ? opts[:file] : STDOUT
|
42
|
+
File.write(file, PDD::Base.new(opts).xml)
|
43
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Avoiding Duplicate Puzzles
|
2
|
+
As a source code writer I want to be sure that
|
3
|
+
XML output doesn't contain any duplicates
|
4
|
+
|
5
|
+
Scenario: Throwing exception on duplicates
|
6
|
+
Given I have a "Sample.java" file with content:
|
7
|
+
"""
|
8
|
+
public class Main {
|
9
|
+
/**
|
10
|
+
* @todo #13 A simple puzzle
|
11
|
+
* @todo #15 A simple puzzle
|
12
|
+
*/
|
13
|
+
public void main(String[] args) {
|
14
|
+
// later
|
15
|
+
}
|
16
|
+
}
|
17
|
+
"""
|
18
|
+
When I run pdd it fails with "Duplicate key-sequence"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Command Line Processing
|
2
|
+
As a source code writer I want to be able to
|
3
|
+
call PDD as a command line tool
|
4
|
+
|
5
|
+
Scenario: Help can be printed
|
6
|
+
When I run bin/pdd with "-h"
|
7
|
+
Then Exit code is zero
|
8
|
+
And Stdout contains "Usage: pdd"
|
9
|
+
|
10
|
+
Scenario: Simple puzzles collecting
|
11
|
+
Given I have a "Sample.java" file with content:
|
12
|
+
"""
|
13
|
+
public class Main {
|
14
|
+
/**
|
15
|
+
* @todo #13 Let's do it later, dude
|
16
|
+
* or maybe even never :)
|
17
|
+
*/
|
18
|
+
public void main(String[] args) {
|
19
|
+
// later
|
20
|
+
}
|
21
|
+
}
|
22
|
+
"""
|
23
|
+
When I run bin/pdd with "-v -s . -f out.xml"
|
24
|
+
Then XML file "out.xml" matches "/puzzles[count(puzzle)=1]"
|
data/features/parsing.feature
CHANGED
@@ -42,9 +42,9 @@ Feature: Parsing
|
|
42
42
|
"""
|
43
43
|
When I run pdd
|
44
44
|
Then XML matches "/puzzles[count(puzzle)=3]"
|
45
|
-
And XML matches "//puzzle[ticket='13' and lines='3']"
|
45
|
+
And XML matches "//puzzle[ticket='13' and lines='3-3']"
|
46
46
|
And XML matches "//puzzle[ticket='13' and body='This one later']"
|
47
|
-
And XML matches "//puzzle[ticket='ABC-67' and lines='4']"
|
47
|
+
And XML matches "//puzzle[ticket='ABC-67' and lines='4-4']"
|
48
48
|
And XML matches "//puzzle[ticket='F-78-3' and lines='5-6']"
|
49
49
|
And XML matches "//puzzle[ticket='ABC-67' and estimate='15']"
|
50
50
|
And XML matches "//puzzle[ticket='F-78-3' and estimate='120']"
|
@@ -24,11 +24,17 @@
|
|
24
24
|
require 'pdd'
|
25
25
|
require 'nokogiri'
|
26
26
|
require 'tmpdir'
|
27
|
+
require 'slop'
|
28
|
+
require 'English'
|
27
29
|
|
28
30
|
Before do
|
29
31
|
@dir = Dir.mktmpdir('test')
|
30
32
|
FileUtils.mkdir_p(@dir) unless File.exist?(@dir)
|
31
33
|
Dir.chdir(@dir)
|
34
|
+
@opts = Slop.parse ['-v', '-s', @dir] do
|
35
|
+
on 'v', 'verbose'
|
36
|
+
on 's', 'source', argument: :required
|
37
|
+
end
|
32
38
|
end
|
33
39
|
|
34
40
|
After do
|
@@ -43,9 +49,44 @@ Given(/^I have a "([^"]*)" file with content:$/) do |file, text|
|
|
43
49
|
end
|
44
50
|
|
45
51
|
When(/^I run pdd$/) do
|
46
|
-
@xml = Nokogiri::XML.parse(PDD::Base.new(@
|
52
|
+
@xml = Nokogiri::XML.parse(PDD::Base.new(@opts).xml)
|
47
53
|
end
|
48
54
|
|
49
55
|
Then(/^XML matches "([^"]+)"$/) do |xpath|
|
50
56
|
fail "XML doesn't match \"#{xpath}\":\n#{@xml}" if @xml.xpath(xpath).empty?
|
51
57
|
end
|
58
|
+
|
59
|
+
When(/^I run pdd it fails with "([^"]*)"$/) do |txt|
|
60
|
+
begin
|
61
|
+
PDD::Base.new(@opts).xml
|
62
|
+
passed = true
|
63
|
+
rescue PDD::Error => ex
|
64
|
+
unless ex.message.include?(txt)
|
65
|
+
raise "PDD failed but exception doesn't contain \"#{txt}\": #{ex.message}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
fail "PDD didn't fail" if passed
|
69
|
+
end
|
70
|
+
|
71
|
+
When(/^I run bin\/pdd with "([^"]*)"$/) do |arg|
|
72
|
+
home = File.join(File.dirname(__FILE__), '../..')
|
73
|
+
@stdout = `ruby -I#{home}/lib #{home}/bin/pdd #{arg}`
|
74
|
+
@exitstatus = $CHILD_STATUS.exitstatus
|
75
|
+
end
|
76
|
+
|
77
|
+
Then(/^Stdout contains "([^"]*)"$/) do |txt|
|
78
|
+
unless @stdout.include?(txt)
|
79
|
+
fail "STDOUT doesn't contain '#{txt}':\n#{@stdout}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
Then(/^XML file "([^"]+)" matches "([^"]+)"$/) do |file, xpath|
|
84
|
+
xml = Nokogiri::XML.parse(File.read(file))
|
85
|
+
if xml.xpath(xpath).empty?
|
86
|
+
fail "XML file #{file} doesn't match \"#{xpath}\":\n#{xml}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
Then(/^Exit code is zero$/) do
|
91
|
+
fail "Non-zero exit code #{@exitstatus}" unless @exitstatus == 0
|
92
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: 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 'simplecov'
|
25
|
+
require 'pdd'
|
26
|
+
|
27
|
+
PDD.log = Logger.new(STDOUT)
|
data/lib/pdd.rb
CHANGED
@@ -23,30 +23,58 @@
|
|
23
23
|
|
24
24
|
require 'pdd/sources'
|
25
25
|
require 'nokogiri'
|
26
|
+
require 'logger'
|
26
27
|
|
27
28
|
# PDD main module.
|
28
29
|
# Author:: Yegor Bugayenko (yegor@teamed.io)
|
29
30
|
# Copyright:: Copyright (c) 2014 Yegor Bugayenko
|
30
31
|
# License:: MIT
|
31
32
|
module PDD
|
33
|
+
# If it breaks.
|
34
|
+
class Error < StandardError
|
35
|
+
end
|
36
|
+
|
37
|
+
# If it violates XSD schema.
|
38
|
+
class SchemaError < Error
|
39
|
+
end
|
40
|
+
|
41
|
+
# Get logger.
|
42
|
+
def self.log
|
43
|
+
@log ||= Logger.new(STDOUT)
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
attr_writer :log
|
48
|
+
end
|
49
|
+
|
32
50
|
# Code base abstraction
|
33
51
|
class Base
|
34
52
|
# Ctor.
|
35
|
-
# +
|
36
|
-
def initialize(
|
37
|
-
@
|
53
|
+
# +opts+:: Options
|
54
|
+
def initialize(opts)
|
55
|
+
@opts = opts
|
56
|
+
PDD.log = Logger.new(File::NULL) unless @opts.verbose?
|
38
57
|
end
|
39
58
|
|
40
59
|
# Generate XML.
|
41
60
|
def xml
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
61
|
+
dir = @opts.source? ? @opts[:source] : Dir.pwd
|
62
|
+
PDD.log.info "reading #{dir}"
|
63
|
+
sanitize(
|
64
|
+
Nokogiri::XML::Builder.new do |xml|
|
65
|
+
xml << '<?xml-stylesheet type="text/xsl" href="puzzles.xsl"?>'
|
66
|
+
xml.puzzles do
|
67
|
+
Sources.new(dir).fetch.each do |source|
|
68
|
+
source.puzzles.each do |puzzle|
|
69
|
+
PDD.log.info "puzzle #{puzzle.props[:ticket]}:" \
|
70
|
+
"#{puzzle.props[:estimate]}/#{puzzle.props[:role]}" \
|
71
|
+
" at #{puzzle.props[:file]}"
|
72
|
+
render puzzle, xml
|
73
|
+
end
|
74
|
+
end
|
47
75
|
end
|
48
|
-
end
|
49
|
-
|
76
|
+
end.to_xml
|
77
|
+
)
|
50
78
|
end
|
51
79
|
|
52
80
|
private
|
@@ -59,5 +87,15 @@ module PDD
|
|
59
87
|
end
|
60
88
|
end
|
61
89
|
end
|
90
|
+
|
91
|
+
def sanitize(xml)
|
92
|
+
xsd = Nokogiri::XML::Schema(
|
93
|
+
File.read(File.join(File.dirname(__FILE__), '../asserts/puzzles.xsd'))
|
94
|
+
)
|
95
|
+
errors = xsd.validate(Nokogiri::XML(xml)).map { |error| error.message }
|
96
|
+
errors.each { |e| PDD.log.error e }
|
97
|
+
fail SchemaError, errors.join('; ') unless errors.empty?
|
98
|
+
xml
|
99
|
+
end
|
62
100
|
end
|
63
101
|
end
|
data/lib/pdd/source.rb
CHANGED
data/pdd.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.rubygems_version = '2.2.2'
|
30
30
|
s.required_ruby_version = '>= 1.9.3'
|
31
31
|
s.name = 'pdd'
|
32
|
-
s.version = '0.
|
32
|
+
s.version = '0.2'
|
33
33
|
s.license = 'MIT'
|
34
34
|
s.summary = 'Puzzle Driven Development collector'
|
35
35
|
s.description = 'Collects puzzles from source code base'
|
@@ -43,10 +43,13 @@ Gem::Specification.new do |s|
|
|
43
43
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
44
44
|
s.add_runtime_dependency 'nokogiri', '~> 1.6', '>= 1.6.3.1'
|
45
45
|
s.add_runtime_dependency 'ruby-filemagic', '~> 0.6', '>= 0.6.0'
|
46
|
+
s.add_runtime_dependency 'slop', '~> 3.6', '>= 3.6.0'
|
46
47
|
s.add_development_dependency 'rake', '~> 10.1'
|
48
|
+
s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7.0'
|
47
49
|
s.add_development_dependency 'rdoc', '~> 3.11'
|
48
50
|
s.add_development_dependency 'cucumber', '1.3.11'
|
49
51
|
s.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.0'
|
50
52
|
s.add_development_dependency 'rubocop', '~> 0.24', '>= 0.24.1'
|
51
53
|
s.add_development_dependency 'rubocop-rspec', '~> 1.1', '>= 1.1.0'
|
54
|
+
s.add_development_dependency 'rspec-rails', '~> 2.13'
|
52
55
|
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: 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 'simplecov'
|
25
|
+
require 'pdd'
|
26
|
+
|
27
|
+
PDD.log = Logger.new(STDOUT)
|
data/test/test_pdd.rb
CHANGED
@@ -25,6 +25,7 @@ require 'minitest/autorun'
|
|
25
25
|
require 'nokogiri'
|
26
26
|
require 'pdd'
|
27
27
|
require 'tmpdir'
|
28
|
+
require 'slop'
|
28
29
|
|
29
30
|
# PDD main module test.
|
30
31
|
# Author:: Yegor Bugayenko (yegor@teamed.io)
|
@@ -33,9 +34,13 @@ require 'tmpdir'
|
|
33
34
|
class TestPDD < Minitest::Test
|
34
35
|
def test_basic
|
35
36
|
Dir.mktmpdir 'test' do |dir|
|
37
|
+
opts = Slop.parse ['-v', '-s', dir] do
|
38
|
+
on 'v', 'verbose'
|
39
|
+
on 's', 'source', argument: :required
|
40
|
+
end
|
36
41
|
File.write(File.join(dir, 'a.txt'), '@todo #55 hello!')
|
37
|
-
xml = Nokogiri::XML::Document.parse(PDD::Base.new(
|
38
|
-
assert_equal xml.xpath('/puzzles/puzzle[file="a.txt"]').size
|
42
|
+
xml = Nokogiri::XML::Document.parse(PDD::Base.new(opts).xml)
|
43
|
+
assert_equal 1, xml.xpath('/puzzles/puzzle[file="a.txt"]').size
|
39
44
|
end
|
40
45
|
end
|
41
46
|
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.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -55,6 +55,28 @@ dependencies:
|
|
55
55
|
- - ! '>='
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: 0.6.0
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: slop
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '3.6'
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.6.0
|
69
|
+
type: :runtime
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '3.6'
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 3.6.0
|
58
80
|
- !ruby/object:Gem::Dependency
|
59
81
|
name: rake
|
60
82
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,6 +93,28 @@ dependencies:
|
|
71
93
|
- - ~>
|
72
94
|
- !ruby/object:Gem::Version
|
73
95
|
version: '10.1'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: coveralls
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.7'
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 0.7.0
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ~>
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0.7'
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.7.0
|
74
118
|
- !ruby/object:Gem::Dependency
|
75
119
|
name: rdoc
|
76
120
|
requirement: !ruby/object:Gem::Requirement
|
@@ -169,6 +213,22 @@ dependencies:
|
|
169
213
|
- - ! '>='
|
170
214
|
- !ruby/object:Gem::Version
|
171
215
|
version: 1.1.0
|
216
|
+
- !ruby/object:Gem::Dependency
|
217
|
+
name: rspec-rails
|
218
|
+
requirement: !ruby/object:Gem::Requirement
|
219
|
+
none: false
|
220
|
+
requirements:
|
221
|
+
- - ~>
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '2.13'
|
224
|
+
type: :development
|
225
|
+
prerelease: false
|
226
|
+
version_requirements: !ruby/object:Gem::Requirement
|
227
|
+
none: false
|
228
|
+
requirements:
|
229
|
+
- - ~>
|
230
|
+
- !ruby/object:Gem::Version
|
231
|
+
version: '2.13'
|
172
232
|
description: Collects puzzles from source code base
|
173
233
|
email: yegor@teamed.io
|
174
234
|
executables: []
|
@@ -177,23 +237,31 @@ extra_rdoc_files:
|
|
177
237
|
- README.md
|
178
238
|
- LICENSE.txt
|
179
239
|
files:
|
240
|
+
- .coveralls.yml
|
180
241
|
- .gitignore
|
181
242
|
- .rubocop.yml
|
182
243
|
- .rultor.yml
|
244
|
+
- .simplecov
|
183
245
|
- .travis.yml
|
184
246
|
- Gemfile
|
185
247
|
- LICENSE.txt
|
186
248
|
- README.md
|
187
249
|
- Rakefile
|
250
|
+
- asserts/puzzles.xsd
|
251
|
+
- asserts/puzzles.xsl
|
188
252
|
- bin/pdd
|
189
253
|
- cucumber.yml
|
254
|
+
- features/avoiding_duplicates.feature
|
255
|
+
- features/cli.feature
|
190
256
|
- features/parsing.feature
|
191
257
|
- features/step_definitions/steps.rb
|
258
|
+
- features/support/env.rb
|
192
259
|
- lib/pdd.rb
|
193
260
|
- lib/pdd/puzzle.rb
|
194
261
|
- lib/pdd/source.rb
|
195
262
|
- lib/pdd/sources.rb
|
196
263
|
- pdd.gemspec
|
264
|
+
- test/test_helper.rb
|
197
265
|
- test/test_pdd.rb
|
198
266
|
- test/test_source.rb
|
199
267
|
- test/test_sources.rb
|