cuporter 0.2.7 → 0.2.8
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/README.textile +41 -14
- data/Rakefile +2 -2
- data/bin/cuporter +11 -5
- data/lib/cuporter/cli/filter_args_builder.rb +37 -0
- data/lib/cuporter/cli/options.rb +56 -36
- data/lib/cuporter/feature_parser.rb +5 -57
- data/lib/cuporter/filter.rb +52 -0
- data/lib/cuporter/{formatters → formatter}/csv.rb +1 -1
- data/lib/cuporter/{formatters → formatter}/cuporter.css +27 -2
- data/lib/cuporter/{formatters/html.rb → formatter/html_methods.rb} +14 -36
- data/lib/cuporter/{formatters → formatter}/html_node_writer.rb +2 -3
- data/lib/cuporter/{formatters → formatter}/jquery-min.js +0 -0
- data/lib/cuporter/formatter/name_report_html.rb +62 -0
- data/lib/cuporter/formatter/tag_report_html.rb +48 -0
- data/lib/cuporter/{formatters → formatter}/text.rb +1 -1
- data/lib/cuporter/{formatters → formatter}/text_methods.rb +2 -2
- data/lib/cuporter/formatter/writer.rb +29 -0
- data/lib/cuporter/name_list.rb +65 -0
- data/lib/cuporter/report/name_report.rb +19 -0
- data/lib/cuporter/report/report.rb +23 -0
- data/lib/cuporter/report/tag_report.rb +17 -0
- data/lib/cuporter/tag_list.rb +64 -0
- data/lib/cuporter/tag_list_node.rb +14 -9
- data/lib/cuporter.rb +15 -7
- metadata +23 -15
- data/lib/cuporter/formatters/writer.rb +0 -14
- data/lib/cuporter/tag_report.rb +0 -24
data/README.textile
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
h1. Cuporter
|
2
2
|
|
3
|
-
Scrapes your feature files and shows
|
3
|
+
Scrapes your feature files and shows 2 possible reports:
|
4
4
|
|
5
|
-
|
5
|
+
# scenarios and examples per tag
|
6
|
+
** in Feature and Scenario Outline context, as appropriate
|
7
|
+
** sorted alphbetically
|
8
|
+
** optionally numbered, counting scenarios and outline examples per tag
|
9
|
+
# feature, scenario and example names
|
10
|
+
** may be filtered by tags, using same CLI syntax as Cucumber
|
11
|
+
** sorted alphbetically
|
12
|
+
** optionally numbered, using 1 count of all scenarios and outline examples for the report
|
13
|
+
|
14
|
+
Either report may be formatted in HTML, CSV, or Pretty Text.
|
6
15
|
|
7
|
-
|
16
|
+
* HTML reports do jQuery expand-collapse, with acklowedgment due to the Cucumber HTML formatter.
|
17
|
+
|
18
|
+
Consider this a stop-gap until we get this functionality in a proper cucumber formatter.
|
8
19
|
|
9
20
|
---------
|
10
|
-
h3. Example Output: numbered pretty text
|
21
|
+
h3. Example Tag Report Output: numbered pretty text
|
11
22
|
|
12
23
|
<pre>
|
13
24
|
@failing
|
@@ -63,28 +74,44 @@ h4. help
|
|
63
74
|
$ ./bin/cuporter -h
|
64
75
|
|
65
76
|
Usage: cuporter [options]
|
66
|
-
|
77
|
+
|
67
78
|
-i, --in DIR directory of *.feature files
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
79
|
+
Default: features/**/*.feature
|
80
|
+
|
81
|
+
-I, --input-file FILE full file name with extension: 'path/to/file.feature'
|
82
|
+
|
72
83
|
-o, --out FILE Output file path
|
73
|
-
|
84
|
+
|
74
85
|
-f, --format [pretty|html|csv] Output format
|
75
|
-
|
86
|
+
Default: pretty text
|
76
87
|
|
77
88
|
-n, --numbers number scenarios and examples
|
89
|
+
|
90
|
+
-t, --tags TAG_EXPRESSION Filter on tags for name report.
|
91
|
+
TAG_EXPRESSION rules: see '$ cucumber --help' and http://github.com/aslakhellesoy/cucumber/wiki/Tags
|
92
|
+
|
93
|
+
-r, --report [tag|name] type of report
|
94
|
+
Default: tag
|
95
|
+
|
96
|
+
-T, --title STRING title of name report
|
97
|
+
Default: 'Cucumber Scenario Inventory'
|
98
|
+
|
78
99
|
</pre>
|
79
100
|
|
80
101
|
h4. run script directly
|
81
102
|
|
82
103
|
<pre>
|
83
|
-
|
104
|
+
# pretty-print demo report to stdout
|
105
|
+
$ ./bin/cuporter -i fixtures/self_text
|
106
|
+
|
107
|
+
# default input features/**/*.feature to named output file
|
108
|
+
$ ./bin/cuporter -f html -o feature_tag_report.html
|
84
109
|
|
85
|
-
|
110
|
+
# same, but number the scenarios and example rows
|
111
|
+
$ ./bin/cuporter -f html --numbers -o feature_tag_report.html
|
86
112
|
|
87
|
-
|
113
|
+
# filtered html name report, with non-default title
|
114
|
+
$ ./bin/cuporter -f html -o active_customer.html -r name -n -T "Active Customer Test Inventory" -t ~@wip -t @customer,@client
|
88
115
|
</pre>
|
89
116
|
|
90
117
|
h4. run via rake
|
data/Rakefile
CHANGED
@@ -56,14 +56,14 @@ namespace :cuporter do
|
|
56
56
|
|
57
57
|
spec = Gem::Specification.new do |s|
|
58
58
|
s.name = 'cuporter'
|
59
|
-
s.version = '0.2.
|
59
|
+
s.version = '0.2.8'
|
60
60
|
s.rubyforge_project = s.name
|
61
61
|
|
62
62
|
s.platform = Gem::Platform::RUBY
|
63
63
|
s.has_rdoc = true
|
64
64
|
s.extra_rdoc_files = XTRA_RDOC
|
65
65
|
s.rdoc_options += RDOC_OPTS
|
66
|
-
s.summary = "Scrapes Cucumber *.feature files to build
|
66
|
+
s.summary = "Scrapes Cucumber *.feature files to build reports on tag usage and test inventory"
|
67
67
|
s.description = s.summary
|
68
68
|
s.author = "Tim Camper"
|
69
69
|
s.email = 'twcamper@thoughtworks.com'
|
data/bin/cuporter
CHANGED
@@ -3,9 +3,15 @@
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
4
4
|
require 'cuporter'
|
5
5
|
|
6
|
-
|
6
|
+
filter_args = Cuporter::CLI::FilterArgsBuilder.new(Cuporter::CLI::Options[:tags]).args
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
report = Cuporter::Report.create(Cuporter::CLI::Options[:report],
|
9
|
+
Cuporter::CLI::Options[:input_file] || Cuporter::CLI::Options[:input_dir],
|
10
|
+
Cuporter::CLI::Options[:numbers],
|
11
|
+
filter_args,
|
12
|
+
Cuporter::CLI::Options[:title])
|
13
|
+
|
14
|
+
formatter = Cuporter::Formatter::Writer.create(Cuporter::CLI::Options[:format],
|
15
|
+
report,
|
16
|
+
Cuporter::CLI::Options[:output])
|
17
|
+
formatter.write
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
module CLI
|
5
|
+
class FilterArgsBuilder
|
6
|
+
def initialize(cli_tags = [])
|
7
|
+
@cli_tags = cli_tags
|
8
|
+
@all = []
|
9
|
+
@any = []
|
10
|
+
@none = []
|
11
|
+
@args = {}
|
12
|
+
filter_args
|
13
|
+
end
|
14
|
+
|
15
|
+
def filter_args
|
16
|
+
@cli_tags.each do |expression|
|
17
|
+
case expression
|
18
|
+
when /^~@/
|
19
|
+
@none << expression.sub(/~/,'')
|
20
|
+
when /,/
|
21
|
+
@any |= expression.split(',')
|
22
|
+
else
|
23
|
+
@all << expression
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def args
|
29
|
+
@args[:any] = @any unless @any.empty?
|
30
|
+
@args[:all] = @all unless @all.empty?
|
31
|
+
@args[:none] = @none unless @none.empty?
|
32
|
+
@args
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/cuporter/cli/options.rb
CHANGED
@@ -3,47 +3,67 @@ require 'optparse'
|
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
5
|
module Cuporter
|
6
|
-
|
6
|
+
module CLI
|
7
|
+
class Options
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def self.[](key)
|
10
|
+
self.options[key]
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def self.options
|
14
|
+
self.parse unless @options
|
15
|
+
@options
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse
|
19
|
+
@options = {}
|
20
|
+
OptionParser.new(ARGV.dup) do |opts|
|
21
|
+
opts.banner = "Usage: cuporter [options]\n\n"
|
22
|
+
|
23
|
+
@options[:input_dir] = "features/**/*.feature"
|
24
|
+
opts.on("-i", "--in DIR", "directory of *.feature files\n\t\t\t\t\tDefault: features/**/*.feature\n\n") do |i|
|
25
|
+
@options[:input_dir] = "#{i}/**/*.feature"
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-I", "--input-file FILE", "full file name with extension: 'path/to/file.feature'\n\n") do |file|
|
29
|
+
@options[:input_file] = file
|
30
|
+
end
|
31
|
+
opts.on("-o", "--out FILE", "Output file path\n\n") do |o|
|
32
|
+
full_path = File.expand_path(o)
|
33
|
+
path = full_path.split(File::SEPARATOR)
|
34
|
+
file = path.pop
|
35
|
+
FileUtils.makedirs(path.join(File::SEPARATOR))
|
36
|
+
|
37
|
+
@options[:output] = full_path
|
38
|
+
end
|
39
|
+
@options[:format] = "text"
|
40
|
+
opts.on("-f", "--format [pretty|html|csv]", "Output format\n\t\t\t\t\tDefault: pretty text\n\n") do |f|
|
41
|
+
@options[:format] = f
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-n", "--numbers", "number scenarios and examples\n\n") do |n|
|
45
|
+
@options[:numbers] = n
|
46
|
+
end
|
47
|
+
|
48
|
+
@options[:tags] = []
|
49
|
+
opts.on("-t", "--tags TAG_EXPRESSION", "Filter on tags for name report.\n\t\t\t\t\tTAG_EXPRESSION rules: see '$ cucumber --help' and http://github.com/aslakhellesoy/cucumber/wiki/Tags\n\n") do |t|
|
50
|
+
@options[:tags] << t
|
51
|
+
end
|
52
|
+
|
53
|
+
@options[:report] = "tag"
|
54
|
+
opts.on("-r", "--report [tag|name]", "type of report\n\t\t\t\t\tDefault: tag\n\n") do |r|
|
55
|
+
@options[:report] = r
|
56
|
+
end
|
57
|
+
|
58
|
+
@options[:title] = "Cucumber Scenario Inventory"
|
59
|
+
opts.on("-T", "--title STRING", "title of name report\n\t\t\t\t\tDefault: 'Cucumber Scenario Inventory'\n\n") do |title|
|
60
|
+
@options[:title] = title
|
61
|
+
end
|
16
62
|
|
17
|
-
|
18
|
-
@options = {}
|
19
|
-
OptionParser.new(ARGV.dup) do |opts|
|
20
|
-
opts.banner = "Usage: cuporter [options]\n\n"
|
21
|
-
|
22
|
-
opts.on("-i", "--in DIR", "directory of *.feature files\n\t\t\t\t\tDefault: features/**/*.feature\n\n") do |i|
|
23
|
-
@options[:input_dir] = "#{i}/**/*.feature"
|
24
|
-
end
|
25
|
-
opts.on("--input-file FILE", "full file name with extension: 'path/to/file.feature'\n\n") do |file|
|
26
|
-
@options[:input_file] = file
|
27
|
-
end
|
28
|
-
opts.on("-o", "--out FILE", "Output file path\n\n") do |o|
|
29
|
-
full_path = File.expand_path(o)
|
30
|
-
path = full_path.split(File::SEPARATOR)
|
31
|
-
file = path.pop
|
32
|
-
FileUtils.makedirs(path.join(File::SEPARATOR))
|
33
|
-
|
34
|
-
@options[:output] = full_path
|
35
|
-
end
|
36
|
-
opts.on("-f", "--format [pretty|html|csv]", "Output format\n\t\t\t\t\tDefault: pretty text\n\n") do |f|
|
37
|
-
@options[:format] = f.downcase.to_class_name
|
38
|
-
end
|
39
|
-
@options[:format] ||= :Text
|
40
|
-
|
41
|
-
opts.on("-n", "--numbers", "number scenarios and examples") do |n|
|
42
|
-
@options[:numbers] = n
|
43
|
-
end
|
44
|
-
end.parse!
|
63
|
+
end.parse!
|
45
64
|
|
46
65
|
|
66
|
+
end
|
47
67
|
end
|
48
68
|
end
|
49
69
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
2
|
|
3
3
|
module Cuporter
|
4
|
-
|
4
|
+
module FeatureParser
|
5
5
|
FEATURE_LINE = /^\s*(Feature:[^#]+)/
|
6
6
|
TAG_LINE = /^\s*(@\w.+)/
|
7
7
|
SCENARIO_LINE = /^\s*(Scenario:[^#]+)$/
|
@@ -10,65 +10,13 @@ module Cuporter
|
|
10
10
|
EXAMPLE_SET_LINE = /^\s*(Examples:[^#]*)$/
|
11
11
|
EXAMPLE_LINE = /^\s*(\|.*\|)\s*$/
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
@current_tags = []
|
13
|
+
def self.tag_list(file)
|
14
|
+
TagList.new(file).parse_feature
|
16
15
|
end
|
17
16
|
|
18
|
-
def self.
|
19
|
-
|
17
|
+
def self.name_list(file, filter)
|
18
|
+
NameList.new(file, filter).parse_feature
|
20
19
|
end
|
21
20
|
|
22
|
-
def parse
|
23
|
-
lines = File.read(@file).split(/\n/)
|
24
|
-
|
25
|
-
lines.each_with_index do |line, i|
|
26
|
-
case line
|
27
|
-
when TAG_LINE
|
28
|
-
# may be more than one tag line
|
29
|
-
@current_tags |= $1.strip.split(/\s+/)
|
30
|
-
when FEATURE_LINE
|
31
|
-
@feature = TagListNode.new($1, @current_tags)
|
32
|
-
@feature.file = @file.sub(/^.*features\//,"features/")
|
33
|
-
@current_tags = []
|
34
|
-
when SCENARIO_LINE
|
35
|
-
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
36
|
-
# One way is when we encounter a "Scenario:"
|
37
|
-
close_scenario_outline
|
38
|
-
|
39
|
-
@feature.add_to_tag_nodes(TagListNode.new($1, @current_tags))
|
40
|
-
@current_tags = []
|
41
|
-
when SCENARIO_OUTLINE_LINE
|
42
|
-
# ... another is when we hit a subsequent "Scenario Outline:"
|
43
|
-
close_scenario_outline
|
44
|
-
|
45
|
-
@scenario_outline = TagListNode.new($1, @current_tags)
|
46
|
-
@current_tags = []
|
47
|
-
when EXAMPLE_SET_LINE, SCENARIO_SET_LINE
|
48
|
-
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
49
|
-
|
50
|
-
@example_set = ExampleSetNode.new($1, @feature.tags | @current_tags)
|
51
|
-
@current_tags = []
|
52
|
-
when @example_set && EXAMPLE_LINE
|
53
|
-
@example_set.add_child(Node.new($1))
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
58
|
-
close_scenario_outline
|
59
|
-
return @feature
|
60
|
-
end
|
61
|
-
|
62
|
-
def close_scenario_outline
|
63
|
-
if @scenario_outline
|
64
|
-
if @example_set
|
65
|
-
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
66
|
-
@example_set = nil
|
67
|
-
end
|
68
|
-
@feature.merge(@scenario_outline)
|
69
|
-
@scenario_outline = nil
|
70
|
-
end
|
71
|
-
end
|
72
21
|
end
|
73
|
-
|
74
22
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
module Cuporter
|
3
|
+
class Filter
|
4
|
+
|
5
|
+
attr_reader :all, :any, :none
|
6
|
+
|
7
|
+
def initialize(args = {})
|
8
|
+
@all = to_tag_array(args[:all]) # logical AND
|
9
|
+
@any = to_tag_array(args[:any]) # logical OR
|
10
|
+
@none = to_tag_array(args[:none])# logical NOT
|
11
|
+
end
|
12
|
+
|
13
|
+
def pass?(other_tags)
|
14
|
+
pass = true
|
15
|
+
|
16
|
+
# Logical AND: are all of the tags in :all in the tests' tags?
|
17
|
+
unless all.empty?
|
18
|
+
pass = false unless (other_tags & all).size == all.size
|
19
|
+
end
|
20
|
+
|
21
|
+
# Logical OR: are any of the tests' tags in :any?
|
22
|
+
unless any.empty?
|
23
|
+
pass = false if (other_tags & any).empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
unless none.empty?
|
27
|
+
pass = false if !(other_tags & none).empty?
|
28
|
+
end
|
29
|
+
pass
|
30
|
+
end
|
31
|
+
|
32
|
+
def empty?
|
33
|
+
all.empty? && any.empty? && none.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def to_tag_array(tag_input)
|
39
|
+
case tag_input
|
40
|
+
when Array
|
41
|
+
tag_input
|
42
|
+
when String
|
43
|
+
tag_input.split(" ")
|
44
|
+
when Numeric, Symbol
|
45
|
+
[tag_input.to_s]
|
46
|
+
else
|
47
|
+
[]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -7,14 +7,35 @@ body {
|
|
7
7
|
padding-left: 2em;
|
8
8
|
padding-bottom: 0.3em;
|
9
9
|
padding-top: 0.05em;
|
10
|
-
height: 6em;
|
11
10
|
background-color: #24A6C1;
|
12
11
|
color: white;
|
12
|
+
height: 7em;
|
13
|
+
}
|
14
|
+
.cuporter_header #label {
|
15
|
+
padding-right: 2em;
|
16
|
+
float: left;
|
17
|
+
}
|
18
|
+
#filter_summary {
|
19
|
+
width: 60em;
|
20
|
+
float: right;
|
21
|
+
padding-top: 1.2em;
|
13
22
|
}
|
14
23
|
|
15
|
-
#
|
24
|
+
#summary {
|
16
25
|
position: absolute;
|
17
26
|
right: 1em;
|
27
|
+
text-align: right;
|
28
|
+
top: 1.2em;
|
29
|
+
}
|
30
|
+
|
31
|
+
#summary p, #filter_summary p {
|
32
|
+
margin: 0px 0px 0px 2px;
|
33
|
+
}
|
34
|
+
|
35
|
+
.tag_report #expand-collapse {
|
36
|
+
position: absolute;
|
37
|
+
right: 1em;
|
38
|
+
text-align: right;
|
18
39
|
top: 0.5em;
|
19
40
|
}
|
20
41
|
ul {
|
@@ -78,6 +99,10 @@ ul {
|
|
78
99
|
left: 4.5em;
|
79
100
|
font-weight: bold;
|
80
101
|
}
|
102
|
+
|
103
|
+
.name_report .number {
|
104
|
+
left: 4em;
|
105
|
+
}
|
81
106
|
.file {
|
82
107
|
float: right;
|
83
108
|
padding-right: 0.5em;
|
@@ -3,8 +3,8 @@ require 'rubygems'
|
|
3
3
|
require 'erb'
|
4
4
|
|
5
5
|
module Cuporter
|
6
|
-
module
|
7
|
-
|
6
|
+
module Formatter
|
7
|
+
module HtmlMethods
|
8
8
|
|
9
9
|
def inline_style
|
10
10
|
File.read(File.dirname(__FILE__) + "/cuporter.css")
|
@@ -15,7 +15,7 @@ module Cuporter
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def rhtml
|
18
|
-
ERB.new(RHTML)
|
18
|
+
ERB.new(self.class::RHTML)
|
19
19
|
end
|
20
20
|
|
21
21
|
def write
|
@@ -61,45 +61,23 @@ module Cuporter
|
|
61
61
|
$(FEATURES).siblings().show();
|
62
62
|
});
|
63
63
|
|
64
|
+
$("#expand_features").css('cursor', 'pointer');
|
65
|
+
$("#expand_features").click(function() {
|
66
|
+
$(FEATURES).siblings().show();
|
67
|
+
});
|
68
|
+
|
69
|
+
$("#collapse_features").css('cursor', 'pointer');
|
70
|
+
$("#collapse_features").click(function() {
|
71
|
+
$(FEATURES).siblings().hide();
|
72
|
+
});
|
73
|
+
|
64
74
|
// load page with features collapsed
|
65
|
-
$("#expand_tags").click();
|
75
|
+
$("#expand_tags, #collapse_features").click();
|
66
76
|
})
|
67
77
|
|
68
78
|
EOF
|
69
79
|
end
|
70
80
|
|
71
|
-
RHTML = %{
|
72
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
73
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
74
|
-
<head>
|
75
|
-
<title>Cucumber Tags</title>
|
76
|
-
<style type="text/css">
|
77
|
-
<%= inline_style%>
|
78
|
-
</style>
|
79
|
-
<script type="text/javascript">
|
80
|
-
<%= inline_jquery%>
|
81
|
-
<%= inline_js_content%>
|
82
|
-
</script>
|
83
|
-
</head>
|
84
|
-
<body>
|
85
|
-
<div class="cuporter_header">
|
86
|
-
<div id="label">
|
87
|
-
<h1>Cucumber Tags</h1>
|
88
|
-
</div>
|
89
|
-
<div id="expand-collapse">
|
90
|
-
<p id="expand_tags">Expand Tags</p>
|
91
|
-
<p id="expand_all">Expand All</p>
|
92
|
-
<p id="collapser">Collapse All</p>
|
93
|
-
</div>
|
94
|
-
</div>
|
95
|
-
<ul class="tag_list">
|
96
|
-
<%= HtmlNodeWriter.new.write_nodes(@report, @number_scenarios)%>
|
97
|
-
</ul>
|
98
|
-
</body>
|
99
|
-
</html>
|
100
|
-
}
|
101
|
-
|
102
|
-
|
103
81
|
end
|
104
82
|
end
|
105
83
|
end
|
@@ -3,7 +3,7 @@ require 'rubygems'
|
|
3
3
|
require 'builder'
|
4
4
|
|
5
5
|
module Cuporter
|
6
|
-
module
|
6
|
+
module Formatter
|
7
7
|
class HtmlNodeWriter
|
8
8
|
|
9
9
|
attr_reader :builder
|
@@ -13,8 +13,7 @@ module Cuporter
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def write_nodes(report, number_scenarios)
|
16
|
-
report.children.each do |tag_node|
|
17
|
-
tag_node.number_all_descendants if number_scenarios
|
16
|
+
report.report_node.children.each do |tag_node|
|
18
17
|
write_node(tag_node)
|
19
18
|
end
|
20
19
|
builder
|
File without changes
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
require 'rubygems'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Cuporter
|
6
|
+
module Formatter
|
7
|
+
class NameReportHtml < Writer
|
8
|
+
include HtmlMethods
|
9
|
+
|
10
|
+
def title
|
11
|
+
@report.title
|
12
|
+
end
|
13
|
+
|
14
|
+
def filter_summary
|
15
|
+
return if @report.filter.empty?
|
16
|
+
builder = Builder::XmlMarkup.new
|
17
|
+
builder.div(:id => :filter_summary) do |div|
|
18
|
+
div.p("Filtering:")
|
19
|
+
div.p("Include: #{@report.filter.all.join(' AND ')}") unless @report.filter.all.empty?
|
20
|
+
div.p("Include: #{@report.filter.any.join(' OR ')}") unless @report.filter.any.empty?
|
21
|
+
div.p("Exclude: #{@report.filter.none.join(', ')}") unless @report.filter.none.empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
RHTML = %{
|
26
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
27
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
28
|
+
<head>
|
29
|
+
<title><%= title %></title>
|
30
|
+
<style type="text/css">
|
31
|
+
<%= inline_style%>
|
32
|
+
</style>
|
33
|
+
<script type="text/javascript">
|
34
|
+
<%= inline_jquery%>
|
35
|
+
<%= inline_js_content%>
|
36
|
+
</script>
|
37
|
+
</head>
|
38
|
+
<body class="name_report">
|
39
|
+
<div class="cuporter_header">
|
40
|
+
<div id="label">
|
41
|
+
<h1><%= title %></h1>
|
42
|
+
</div>
|
43
|
+
<%= filter_summary %>
|
44
|
+
<div id="summary">
|
45
|
+
<p id="total"><%= @report.report_node.total%> Scenarios </p>
|
46
|
+
<div id="expand-collapse">
|
47
|
+
<p id="expand_features">Expand All</p>
|
48
|
+
<p id="collapse_features">Collapse All</p>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
<ul class="tag_list, name_report">
|
53
|
+
<%= HtmlNodeWriter.new.write_nodes(@report, @number_scenarios)%>
|
54
|
+
</ul>
|
55
|
+
</body>
|
56
|
+
</html>
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
require 'rubygems'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Cuporter
|
6
|
+
module Formatter
|
7
|
+
class TagReportHtml < Writer
|
8
|
+
include HtmlMethods
|
9
|
+
|
10
|
+
def title
|
11
|
+
"Cucumber Tags"
|
12
|
+
end
|
13
|
+
|
14
|
+
RHTML = %{
|
15
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
16
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
17
|
+
<head>
|
18
|
+
<title><%= title %></title>
|
19
|
+
<style type="text/css">
|
20
|
+
<%= inline_style%>
|
21
|
+
</style>
|
22
|
+
<script type="text/javascript">
|
23
|
+
<%= inline_jquery%>
|
24
|
+
<%= inline_js_content%>
|
25
|
+
</script>
|
26
|
+
</head>
|
27
|
+
<body class="tag_report">
|
28
|
+
<div class="cuporter_header">
|
29
|
+
<div id="label">
|
30
|
+
<h1><%= title %></h1>
|
31
|
+
</div>
|
32
|
+
<div id="expand-collapse">
|
33
|
+
<p id="expand_tags">Expand Tags</p>
|
34
|
+
<p id="expand_all">Expand All</p>
|
35
|
+
<p id="collapser">Collapse All</p>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<ul class="tag_list">
|
39
|
+
<%= HtmlNodeWriter.new.write_nodes(@report, @number_scenarios)%>
|
40
|
+
</ul>
|
41
|
+
</body>
|
42
|
+
</html>
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
2
|
module Cuporter
|
3
|
-
module
|
3
|
+
module Formatter
|
4
4
|
module TextMethods
|
5
5
|
|
6
6
|
def write
|
7
|
-
@report.children.each do |tag_node|
|
7
|
+
@report.report_node.children.each do |tag_node|
|
8
8
|
tag_node.number_all_descendants if @number_scenarios
|
9
9
|
write_node(tag_node, 0)
|
10
10
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
module Formatter
|
5
|
+
class Writer
|
6
|
+
|
7
|
+
def initialize(report, output)
|
8
|
+
@report = report
|
9
|
+
@output = output ? File.open(output, "w") : STDOUT
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(format, report, output)
|
13
|
+
klass = writer_class(format, report.class.name.split(/::/).last)
|
14
|
+
klass.new(report, output)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.writer_class(format, report_class)
|
18
|
+
case format
|
19
|
+
when /text|pretty/i
|
20
|
+
Cuporter::Formatter::Text
|
21
|
+
when /csv/i
|
22
|
+
Cuporter::Formatter::Csv
|
23
|
+
when /html/i
|
24
|
+
Cuporter::Formatter.const_get("#{report_class}Html")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
class NameList
|
5
|
+
|
6
|
+
def initialize(file, filter)
|
7
|
+
@file = file
|
8
|
+
@current_tags = []
|
9
|
+
@filter = filter
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_feature
|
13
|
+
lines = File.read(@file).split(/\n/)
|
14
|
+
|
15
|
+
lines.each do |line|
|
16
|
+
case line
|
17
|
+
when FeatureParser::TAG_LINE
|
18
|
+
# may be more than one tag line
|
19
|
+
@current_tags |= $1.strip.split(/\s+/)
|
20
|
+
when FeatureParser::FEATURE_LINE
|
21
|
+
@feature = TagListNode.new($1, @current_tags, @filter)
|
22
|
+
@feature.file = @file.sub(/^.*features\//,"features/")
|
23
|
+
@current_tags = []
|
24
|
+
when FeatureParser::SCENARIO_LINE
|
25
|
+
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
26
|
+
# One way is when we encounter a "Scenario:"
|
27
|
+
close_scenario_outline
|
28
|
+
|
29
|
+
@feature.filter_child(Node.new($1), @current_tags)
|
30
|
+
@current_tags = []
|
31
|
+
when FeatureParser::SCENARIO_OUTLINE_LINE
|
32
|
+
# ... another is when we hit a subsequent "Scenario Outline:"
|
33
|
+
close_scenario_outline
|
34
|
+
|
35
|
+
@scenario_outline = TagListNode.new($1, @current_tags, @filter)
|
36
|
+
@current_tags = []
|
37
|
+
when FeatureParser::EXAMPLE_SET_LINE, FeatureParser::SCENARIO_SET_LINE
|
38
|
+
@scenario_outline.filter_child(@example_set, @example_set.tags) if @example_set
|
39
|
+
|
40
|
+
@example_set = ExampleSetNode.new($1, @feature.tags | @current_tags, @filter)
|
41
|
+
@current_tags = []
|
42
|
+
when @example_set && FeatureParser::EXAMPLE_LINE
|
43
|
+
@example_set.add_child(Node.new($1))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
48
|
+
close_scenario_outline
|
49
|
+
return @feature
|
50
|
+
end
|
51
|
+
|
52
|
+
def close_scenario_outline
|
53
|
+
if @scenario_outline
|
54
|
+
if @example_set
|
55
|
+
@scenario_outline.filter_child(@example_set, @example_set.tags) if @example_set
|
56
|
+
@example_set = nil
|
57
|
+
end
|
58
|
+
@feature.add_child(@scenario_outline) if @scenario_outline.has_children?
|
59
|
+
@scenario_outline = nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
module Cuporter
|
3
|
+
class NameReport < Report
|
4
|
+
|
5
|
+
def report_node
|
6
|
+
names = TagListNode.new("report", @filter)
|
7
|
+
files.each do |file|
|
8
|
+
feature = FeatureParser.name_list(file, @filter)
|
9
|
+
if feature && feature.has_children?
|
10
|
+
names.add_child(feature)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
names.sort_all_descendants!
|
14
|
+
names.number_all_descendants if number_scenarios
|
15
|
+
names
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
module Cuporter
|
3
|
+
class Report
|
4
|
+
|
5
|
+
attr_reader :number_scenarios, :filter, :title
|
6
|
+
|
7
|
+
def initialize(input_file_pattern, number_scenarios, filter_args = nil, title = nil)
|
8
|
+
@input_file_pattern = input_file_pattern
|
9
|
+
@number_scenarios = number_scenarios
|
10
|
+
@filter = Filter.new(filter_args || {})
|
11
|
+
@title = title
|
12
|
+
end
|
13
|
+
|
14
|
+
def files
|
15
|
+
Dir[@input_file_pattern].collect {|f| File.expand_path f}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create(type, input_file_pattern, number_scenarios, filter_args = nil, title = nil)
|
19
|
+
klass = Cuporter.const_get("#{type.downcase}Report".to_class_name)
|
20
|
+
klass.new(input_file_pattern, number_scenarios, filter_args, title)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
module Cuporter
|
3
|
+
class TagReport < Report
|
4
|
+
|
5
|
+
def report_node
|
6
|
+
tags = TagListNode.new("report",[])
|
7
|
+
files.each do |file|
|
8
|
+
feature = FeatureParser.tag_list(file)
|
9
|
+
tags.merge_tag_nodes(feature) if feature
|
10
|
+
end
|
11
|
+
tags.sort_all_descendants!
|
12
|
+
tags.children.each { |child| child.number_all_descendants } if number_scenarios
|
13
|
+
tags
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
class TagList
|
5
|
+
|
6
|
+
def initialize(file)
|
7
|
+
@file = file
|
8
|
+
@current_tags = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_feature
|
12
|
+
lines = File.read(@file).split(/\n/)
|
13
|
+
|
14
|
+
lines.each do |line|
|
15
|
+
case line
|
16
|
+
when FeatureParser::TAG_LINE
|
17
|
+
# may be more than one tag line
|
18
|
+
@current_tags |= $1.strip.split(/\s+/)
|
19
|
+
when FeatureParser::FEATURE_LINE
|
20
|
+
@feature = TagListNode.new($1, @current_tags)
|
21
|
+
@feature.file = @file.sub(/^.*features\//,"features/")
|
22
|
+
@current_tags = []
|
23
|
+
when FeatureParser::SCENARIO_LINE
|
24
|
+
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
25
|
+
# One way is when we encounter a "Scenario:"
|
26
|
+
close_scenario_outline
|
27
|
+
|
28
|
+
@feature.add_to_tag_nodes(TagListNode.new($1, @current_tags))
|
29
|
+
@current_tags = []
|
30
|
+
when FeatureParser::SCENARIO_OUTLINE_LINE
|
31
|
+
# ... another is when we hit a subsequent "Scenario Outline:"
|
32
|
+
close_scenario_outline
|
33
|
+
|
34
|
+
@scenario_outline = TagListNode.new($1, @current_tags)
|
35
|
+
@current_tags = []
|
36
|
+
when FeatureParser::EXAMPLE_SET_LINE, FeatureParser::SCENARIO_SET_LINE
|
37
|
+
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
38
|
+
|
39
|
+
@example_set = ExampleSetNode.new($1, @feature.tags | @current_tags)
|
40
|
+
@current_tags = []
|
41
|
+
when @example_set && FeatureParser::EXAMPLE_LINE
|
42
|
+
@example_set.add_child(Node.new($1))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
47
|
+
close_scenario_outline
|
48
|
+
return @feature
|
49
|
+
end
|
50
|
+
|
51
|
+
def close_scenario_outline
|
52
|
+
if @scenario_outline
|
53
|
+
if @example_set
|
54
|
+
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
55
|
+
@example_set = nil
|
56
|
+
end
|
57
|
+
@feature.merge_tag_nodes(@scenario_outline)
|
58
|
+
@scenario_outline = nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -5,15 +5,20 @@ module Cuporter
|
|
5
5
|
|
6
6
|
attr_reader :tags
|
7
7
|
|
8
|
-
def initialize(name, tags)
|
8
|
+
def initialize(name, tags, filter = {})
|
9
9
|
super(name)
|
10
10
|
@tags = tags
|
11
|
+
@filter = filter
|
11
12
|
end
|
12
13
|
|
13
14
|
def has_tags?
|
14
15
|
@tags.size > 0
|
15
16
|
end
|
16
17
|
|
18
|
+
def filter_child(node, node_tags)
|
19
|
+
add_child(node) if @filter.pass?(tags | node_tags)
|
20
|
+
end
|
21
|
+
|
17
22
|
def add_to_tag_nodes(node)
|
18
23
|
(tags | node.tags).each do |tag|
|
19
24
|
tag_node = find_or_create_child(tag)
|
@@ -25,14 +30,14 @@ module Cuporter
|
|
25
30
|
#
|
26
31
|
# Copy children of other node's top-level, direct descendants to this
|
27
32
|
# node's direct descendants of the same name.
|
28
|
-
def
|
29
|
-
other.children.each do |
|
30
|
-
|
31
|
-
new_grandchild
|
32
|
-
new_grandchild.children
|
33
|
-
new_grandchild.file
|
34
|
-
|
35
|
-
|
33
|
+
def merge_tag_nodes(other)
|
34
|
+
other.children.each do |other_tag_node|
|
35
|
+
tag_node = find_or_create_child(other_tag_node.name)
|
36
|
+
new_grandchild = Node.new(other.name)
|
37
|
+
new_grandchild.children = other_tag_node.children
|
38
|
+
new_grandchild.file = other.file
|
39
|
+
|
40
|
+
tag_node.add_child(new_grandchild)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
data/lib/cuporter.rb
CHANGED
@@ -1,15 +1,23 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
2
|
require 'cuporter/node'
|
3
|
+
require 'cuporter/filter'
|
4
|
+
require 'cuporter/tag_list'
|
5
|
+
require 'cuporter/name_list'
|
3
6
|
require 'cuporter/tag_list_node'
|
4
7
|
require 'cuporter/example_set_node'
|
5
8
|
require 'cuporter/node_numberer'
|
6
9
|
require 'cuporter/feature_parser'
|
7
10
|
require 'cuporter/extensions/string'
|
8
11
|
require 'cuporter/cli/options'
|
9
|
-
require 'cuporter/
|
10
|
-
require 'cuporter/
|
11
|
-
require 'cuporter/
|
12
|
-
require 'cuporter/
|
13
|
-
require 'cuporter/
|
14
|
-
require 'cuporter/
|
15
|
-
require 'cuporter/
|
12
|
+
require 'cuporter/cli/filter_args_builder'
|
13
|
+
require 'cuporter/report/report'
|
14
|
+
require 'cuporter/report/tag_report'
|
15
|
+
require 'cuporter/report/name_report'
|
16
|
+
require 'cuporter/formatter/writer'
|
17
|
+
require 'cuporter/formatter/text_methods'
|
18
|
+
require 'cuporter/formatter/text'
|
19
|
+
require 'cuporter/formatter/csv'
|
20
|
+
require 'cuporter/formatter/html_node_writer'
|
21
|
+
require 'cuporter/formatter/html_methods'
|
22
|
+
require 'cuporter/formatter/tag_report_html'
|
23
|
+
require 'cuporter/formatter/name_report_html'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 8
|
10
|
+
version: 0.2.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tim Camper
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-27 00:00:00 -04:00
|
19
19
|
default_executable: cuporter
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
version: 2.1.2
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
|
-
description: Scrapes Cucumber *.feature files to build
|
37
|
+
description: Scrapes Cucumber *.feature files to build reports on tag usage and test inventory
|
38
38
|
email: twcamper@thoughtworks.com
|
39
39
|
executables:
|
40
40
|
- cuporter
|
@@ -47,23 +47,31 @@ files:
|
|
47
47
|
- LICENSE
|
48
48
|
- README.textile
|
49
49
|
- Rakefile
|
50
|
+
- lib/cuporter/name_list.rb
|
50
51
|
- lib/cuporter/example_set_node.rb
|
51
|
-
- lib/cuporter/
|
52
|
-
- lib/cuporter/
|
53
|
-
- lib/cuporter/
|
54
|
-
- lib/cuporter/
|
55
|
-
- lib/cuporter/
|
56
|
-
- lib/cuporter/
|
52
|
+
- lib/cuporter/formatter/csv.rb
|
53
|
+
- lib/cuporter/formatter/text.rb
|
54
|
+
- lib/cuporter/formatter/html_node_writer.rb
|
55
|
+
- lib/cuporter/formatter/html_methods.rb
|
56
|
+
- lib/cuporter/formatter/tag_report_html.rb
|
57
|
+
- lib/cuporter/formatter/name_report_html.rb
|
58
|
+
- lib/cuporter/formatter/writer.rb
|
59
|
+
- lib/cuporter/formatter/text_methods.rb
|
60
|
+
- lib/cuporter/tag_list.rb
|
61
|
+
- lib/cuporter/report/report.rb
|
62
|
+
- lib/cuporter/report/name_report.rb
|
63
|
+
- lib/cuporter/report/tag_report.rb
|
64
|
+
- lib/cuporter/cli/filter_args_builder.rb
|
57
65
|
- lib/cuporter/cli/options.rb
|
58
66
|
- lib/cuporter/tag_list_node.rb
|
59
67
|
- lib/cuporter/extensions/string.rb
|
60
68
|
- lib/cuporter/feature_parser.rb
|
61
69
|
- lib/cuporter/node.rb
|
70
|
+
- lib/cuporter/filter.rb
|
62
71
|
- lib/cuporter/node_numberer.rb
|
63
|
-
- lib/cuporter/tag_report.rb
|
64
72
|
- lib/cuporter.rb
|
65
|
-
- lib/cuporter/
|
66
|
-
- lib/cuporter/
|
73
|
+
- lib/cuporter/formatter/cuporter.css
|
74
|
+
- lib/cuporter/formatter/jquery-min.js
|
67
75
|
- bin/cuporter
|
68
76
|
has_rdoc: true
|
69
77
|
homepage: http://github.com/twcamper/cuporter
|
@@ -107,6 +115,6 @@ rubyforge_project: cuporter
|
|
107
115
|
rubygems_version: 1.3.7
|
108
116
|
signing_key:
|
109
117
|
specification_version: 3
|
110
|
-
summary: Scrapes Cucumber *.feature files to build
|
118
|
+
summary: Scrapes Cucumber *.feature files to build reports on tag usage and test inventory
|
111
119
|
test_files: []
|
112
120
|
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
|
3
|
-
module Cuporter
|
4
|
-
module Formatters
|
5
|
-
class Writer
|
6
|
-
|
7
|
-
def initialize(report, output, number_scenarios)
|
8
|
-
@report = report
|
9
|
-
@output = output ? File.open(output, "w") : STDOUT
|
10
|
-
@number_scenarios = number_scenarios
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/cuporter/tag_report.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
module Cuporter
|
3
|
-
class TagReport
|
4
|
-
|
5
|
-
def initialize(input_file_pattern)
|
6
|
-
@input_file_pattern = input_file_pattern || "features/**/*.feature"
|
7
|
-
end
|
8
|
-
|
9
|
-
def files
|
10
|
-
Dir[@input_file_pattern].collect {|f| File.expand_path f}
|
11
|
-
end
|
12
|
-
|
13
|
-
def scenarios_per_tag
|
14
|
-
tags = TagListNode.new("report",[])
|
15
|
-
files.each do |file|
|
16
|
-
feature = FeatureParser.parse(file)
|
17
|
-
tags.merge(feature) if feature
|
18
|
-
end
|
19
|
-
tags.sort_all_descendants!
|
20
|
-
tags
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|