cuporter 0.3.10 → 0.3.12
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 +86 -70
- data/Rakefile +6 -5
- data/bin/cuporter +2 -0
- data/config/batch_mode.example.yml +47 -0
- data/config/cli/options.rb +19 -3
- data/config/configuration.rb +23 -126
- data/config/cuporter.example.yml +8 -0
- data/config/option_set.rb +79 -0
- data/config/yaml_file/option_set_collection.rb +42 -0
- data/lib/cuporter.rb +1 -3
- data/lib/cuporter/feature_parser.rb +6 -70
- data/lib/cuporter/feature_parser/language.rb +41 -0
- data/lib/cuporter/feature_parser/node_parser.rb +64 -0
- data/lib/cuporter/feature_parser/old_gherkin_yaml/i18n.rb +9 -0
- data/lib/cuporter/feature_parser/parser_base.rb +84 -0
- data/lib/cuporter/feature_parser/tag_nodes_parser.rb +96 -0
- data/lib/cuporter/logging.rb +32 -0
- data/lib/cuporter/node.rb +6 -6
- data/lib/cuporter/report/tag_report.rb +1 -1
- metadata +31 -9
- data/lib/cuporter/node_parser.rb +0 -62
- data/lib/cuporter/tag_nodes_parser.rb +0 -94
data/README.textile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
h1. Cuporter
|
2
2
|
|
3
|
-
h3. A Cucumber Reporter
|
3
|
+
h3. A "Cucumber":http://github.com/cucumber/cucumber Reporter
|
4
4
|
|
5
5
|
Scrapes your feature files to show test counts and tag relationships.
|
6
6
|
|
@@ -28,9 +28,13 @@ h3. 4 Output Formats
|
|
28
28
|
Splitting the output among multiple formats is supported, so you could run a single report and write it
|
29
29
|
to an html file, a csv file, and show the xml or text on @stdout@ in the terminal.
|
30
30
|
|
31
|
-
h3.
|
31
|
+
h3. i18n: Dozens of Languages
|
32
32
|
|
33
|
-
|
33
|
+
Internationalization through the "gherkin":http://github.com/cucumber/gherkin lanugage file (@i18n.yml@). Following "cucumber's":http://github.com/cucumber/cucumber/wiki/Spoken-languages rules, non-English keywords will be used for any feature file with a '@# language: <iso-code>@' header on line 1,
|
34
|
+
|
35
|
+
h3. A Bunch of Configuration Options
|
36
|
+
|
37
|
+
See the help output below for all of the options, which can be supplied in two ways:
|
34
38
|
|
35
39
|
# Command Line
|
36
40
|
# Yaml File
|
@@ -131,75 +135,85 @@ h4. help
|
|
131
135
|
$ cuporter -h
|
132
136
|
|
133
137
|
Usage: cuporter [options]
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
138
|
+
|
139
|
+
-r, --report [tag|feature|tree] View, or type of report.
|
140
|
+
Default: "tag"
|
141
|
+
|
142
|
+
-f, --format [xml|html|csv|text] Output format.
|
143
|
+
Default: text (it's pretty, though!)
|
144
|
+
|
145
|
+
-i, --input-dir DIR Root directory of *.feature files to be read.
|
146
|
+
Default: "features"
|
147
|
+
|
148
|
+
Used to build the glob pattern '[--input-dir]/**/*.feature', which is really most likely
|
149
|
+
"features/**/*.features" and finds all feature files anywhere under "features" or
|
150
|
+
your custom root supplied with this option.
|
151
|
+
Overridden by "--file-input".
|
152
|
+
|
153
|
+
-I, --file-input FILE Single *.feature file. Full name with extension, like 'path/to/file.feature.'
|
154
|
+
Overrides "--input-dir" and used mostly for testing.
|
155
|
+
|
156
|
+
-H, --output-home PATH Root directory for the output files, like 'tmp/cucumber'.
|
157
|
+
Optional, because the path can also be specified along with the
|
158
|
+
file name in "--output-file"
|
159
|
+
|
160
|
+
Default: ""
|
161
|
+
|
162
|
+
--log-dir PATH Home directory for the error log 'cuporter_errors.log'.
|
163
|
+
|
164
|
+
Default: "." if no report output file is specified, else same as output file dir.
|
165
|
+
|
166
|
+
|
167
|
+
-o, --output-file FILE Output file path, like 'tmp/cucumber/tag_report.html'.
|
168
|
+
|
169
|
+
-t, --tags TAG_EXPRESSION Filter on tags for name report.
|
170
|
+
TAG_EXPRESSION rules:
|
171
|
+
1. $ cucumber --help
|
172
|
+
2. http://github.com/aslakhellesoy/cucumber/wiki/Tags
|
173
|
+
|
174
|
+
-T, --title STRING Override report default title, which is different for each view/report.
|
175
|
+
This affects the xml 'report' node title and the html head > title attributes.
|
176
|
+
|
177
|
+
--config-file PATH Specify any of these options in a yml file.
|
178
|
+
Order of precedence:
|
179
|
+
1 - command line
|
180
|
+
2 - yaml file
|
181
|
+
3 - these defaults
|
182
|
+
|
183
|
+
Default: 'config/cuporter.yml'
|
184
|
+
|
185
|
+
-d, --dry-run Print the configuration without running any reports.
|
186
|
+
|
187
|
+
--text-summary Add a summary to the text format.
|
188
|
+
|
174
189
|
CSS and Javascript asset options:
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
190
|
+
|
191
|
+
-l, --link-assets Do not inline CSS and js in <style/> and <script/> tags, but link to external files instead.
|
192
|
+
Default: 'false' for the tag and feature views, not optional for the
|
193
|
+
tree view, which requires external gifs.
|
194
|
+
|
195
|
+
-c, --copy-public-assets If --output-file is supplied, and you're linking to external
|
196
|
+
CSS and JavaScript assets, copy them from 'public/' to 'cuporter_public'
|
197
|
+
in the same dir as the output file.
|
198
|
+
Sets --use-copied-public-assets to 'true', and
|
199
|
+
the html report will link to these files by relative path.
|
200
|
+
|
201
|
+
Default: 'false'
|
202
|
+
|
203
|
+
-u, --use-copied-public-assets When running batches of reports, and the assets folder has already been
|
204
|
+
created by another call to cuporter with '--copy-public-assets'.
|
205
|
+
Set to 'true' automatically along with --copy-public-assets.
|
206
|
+
|
207
|
+
Default: 'false'
|
208
|
+
|
194
209
|
Reporting options: on by default but can be turned off:
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
210
|
+
|
211
|
+
--no-sort Do not sort tags, features, scenarios, or outlines
|
212
|
+
--no-number Do not get or show scenario or example numbers, (i.e., do not number the leaf nodes).
|
213
|
+
--no-total Do not get or show totals
|
214
|
+
--no-show-tags Do not show cucumber tags at the feature, scenario, or outline level.
|
215
|
+
--no-show-files Do not show feature file paths.
|
216
|
+
--no-leaves Show features only, with no scenarios or outlines.
|
203
217
|
</pre>
|
204
218
|
|
205
219
|
h4. Examples
|
@@ -233,6 +247,8 @@ h3. Dependencies
|
|
233
247
|
can at times present installation difficulties in the form of clashes with already-installed C resources. It has to do with very specific
|
234
248
|
lib versioning and installation order issues. It's not always the same problem,
|
235
249
|
so there's no prescription for it but Google, unfortunately.
|
250
|
+
# Gherkin 1.0.0 or above
|
251
|
+
** For looking up keywords @Feature@, @Scenario@, @Scenario Outline@, and @Examples@ by ISO language code.
|
236
252
|
# jQuery and jQueryTreeview
|
237
253
|
** packaged with the gem
|
238
254
|
** jquery.treeview relies on image files, so our tree view requires the HTML to link to its resources rather than copying them to the <head>.
|
data/Rakefile
CHANGED
@@ -6,9 +6,9 @@ require 'rake/gempackagetask'
|
|
6
6
|
|
7
7
|
task :default do
|
8
8
|
Rake::Task["cuporter:load_test:safe_nokogiri"].invoke # MUST RUN THIS FIRST
|
9
|
-
Rake
|
10
|
-
|
11
|
-
|
9
|
+
Rake::Task["cuporter:test:unit"].invoke
|
10
|
+
Rake::Task["cuporter:test:functional"].invoke
|
11
|
+
Rake::Task["cuporter:test:cucumber"].invoke
|
12
12
|
end
|
13
13
|
|
14
14
|
namespace :cuporter do
|
@@ -47,7 +47,7 @@ namespace :cuporter do
|
|
47
47
|
|
48
48
|
desc "cucumber features"
|
49
49
|
task :cucumber do
|
50
|
-
sh "cucumber"
|
50
|
+
sh "cucumber --quiet"
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -65,7 +65,7 @@ namespace :cuporter do
|
|
65
65
|
|
66
66
|
spec = Gem::Specification.new do |s|
|
67
67
|
s.name = 'cuporter'
|
68
|
-
s.version = '0.3.
|
68
|
+
s.version = '0.3.12'
|
69
69
|
s.rubyforge_project = s.name
|
70
70
|
|
71
71
|
s.platform = Gem::Platform::RUBY
|
@@ -79,6 +79,7 @@ namespace :cuporter do
|
|
79
79
|
s.homepage = 'http://github.com/twcamper/cuporter'
|
80
80
|
s.required_ruby_version = '>= 1.8.6'
|
81
81
|
s.add_dependency('nokogiri', '>= 1.4.1')
|
82
|
+
s.add_dependency('gherkin', '>= 1.0.0')
|
82
83
|
s.default_executable = "cuporter"
|
83
84
|
s.executables = [s.default_executable]
|
84
85
|
|
data/bin/cuporter
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# use this file to run mulitple reports/views at once.
|
2
|
+
---
|
3
|
+
# 'defaults' to be inherited by 'option sets'
|
4
|
+
defaults: &base
|
5
|
+
report: tree
|
6
|
+
format: html
|
7
|
+
link_assets: true
|
8
|
+
use_copied_public_assets: true
|
9
|
+
output_home: tmp
|
10
|
+
|
11
|
+
option_sets:
|
12
|
+
- options: &tag_report
|
13
|
+
<<: *base
|
14
|
+
report: tag
|
15
|
+
output_file: cucumber_tags.html
|
16
|
+
copy_public_assets: true
|
17
|
+
|
18
|
+
# 'split' the output stream to more than one formatter
|
19
|
+
# with no file name for the text format, we print to stdout, most likely on the console.
|
20
|
+
- options: &tree_split
|
21
|
+
<<: *base
|
22
|
+
format: [html, text]
|
23
|
+
output_file: active_tests.html
|
24
|
+
tags: [~@wip, ~@blocked]
|
25
|
+
number: false
|
26
|
+
title: Active Scenarios
|
27
|
+
|
28
|
+
|
29
|
+
- options: &inactive_split
|
30
|
+
<<: *base
|
31
|
+
format: [html, csv]
|
32
|
+
output_file: [inactive_tests.html, inactive_tests.csv]
|
33
|
+
tags: [@wip, @blocked]
|
34
|
+
input_dir: fixtures
|
35
|
+
title: Inactive Scenarios
|
36
|
+
|
37
|
+
# this demo won't produce anything because the tags don't exist
|
38
|
+
- options: &tag_syntax_demo
|
39
|
+
<<: *base
|
40
|
+
format: text
|
41
|
+
tags:
|
42
|
+
- @all # AND
|
43
|
+
- @of # AND
|
44
|
+
- @these # AND
|
45
|
+
- "@one, @the_other" # ( OR )
|
46
|
+
# one line version: "@all AND @of AND @these AND (@one OR @the_other)"
|
47
|
+
# tags: [@all, @of, @these, "@one, @or_the_other"]
|
data/config/cli/options.rb
CHANGED
@@ -41,13 +41,13 @@ module Cuporter
|
|
41
41
|
@options[:format] << f
|
42
42
|
end
|
43
43
|
|
44
|
-
opts.on("-i", "--input-dir DIR", %Q{Root directory of *.feature files.
|
44
|
+
opts.on("-i", "--input-dir DIR", %Q{Root directory of *.feature files to be read.
|
45
45
|
Default: "features"
|
46
46
|
|
47
47
|
Used to build the glob pattern '[--input-dir]/**/*.feature', which is really most likely
|
48
48
|
"features/**/*.features" and finds all feature files anywhere under "features" or
|
49
49
|
your custom root supplied with this option.
|
50
|
-
Overridden by "--file-input
|
50
|
+
Overridden by "--file-input".
|
51
51
|
}) do |i|
|
52
52
|
@options[:input_dir] = i.sub(/#{File::SEPARATOR}$/,'')
|
53
53
|
end
|
@@ -58,6 +58,22 @@ module Cuporter
|
|
58
58
|
@options[:input_file] = file
|
59
59
|
end
|
60
60
|
|
61
|
+
opts.on("-H", "--output-home PATH", %Q{Root directory for the output files, like 'tmp/cucumber'.
|
62
|
+
Optional, because the path can also be specified along with the
|
63
|
+
file name in "--output-file"
|
64
|
+
|
65
|
+
Default: ""
|
66
|
+
}) do |h|
|
67
|
+
@options[:output_home] = h
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on("--log-dir PATH", %Q{Root directory for the error log 'cuporter_errors.log'.
|
71
|
+
|
72
|
+
Default: "." if no report output file is specified, else same as output file dir.
|
73
|
+
}) do |d|
|
74
|
+
@options[:log_dir] = d
|
75
|
+
end
|
76
|
+
|
61
77
|
opts.on("-o", "--output-file FILE", %Q{Output file path, like 'tmp/cucumber/tag_report.html'.
|
62
78
|
}) do |o|
|
63
79
|
@options[:output_file] = [] unless @options[:output_file]
|
@@ -85,7 +101,7 @@ module Cuporter
|
|
85
101
|
2 - yaml file
|
86
102
|
3 - these defaults
|
87
103
|
|
88
|
-
Default: 'cuporter.yml'
|
104
|
+
Default: 'config/cuporter.yml'
|
89
105
|
}) do |path|
|
90
106
|
@options[:config_file] = path
|
91
107
|
end
|
data/config/configuration.rb
CHANGED
@@ -3,139 +3,36 @@ $LOAD_PATH.unshift( File.expand_path("#{File.dirname(__FILE__)}"))
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'cli/options'
|
5
5
|
require 'cli/filter_args_builder'
|
6
|
+
require 'yaml_file/option_set_collection'
|
7
|
+
require 'option_set'
|
6
8
|
|
7
9
|
module Cuporter
|
8
|
-
module Config
|
9
|
-
|
10
|
-
class OptionSetCollection
|
11
|
-
|
12
|
-
def self.path
|
13
|
-
Cuporter::Config::CLI::Options[:config_file] || "cuporter.yml"
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.config_file
|
17
|
-
return [] unless File.exists?(path)
|
18
|
-
|
19
|
-
require 'yaml'
|
20
|
-
yaml = YAML.load_file(path)
|
21
|
-
if yaml["option_sets"]
|
22
|
-
yaml["option_sets"].map do |option_set|
|
23
|
-
cast(option_set["options"])
|
24
|
-
end
|
25
|
-
else
|
26
|
-
yaml["defaults"].empty? ? [] : [cast(yaml["defaults"])]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.cast(option_set)
|
31
|
-
pairs = {}
|
32
|
-
option_set.each do |key, value|
|
33
|
-
pairs[key.to_sym] = case key
|
34
|
-
when /^(tags|output_file|format)$/i
|
35
|
-
value.is_a?(Array) ? value : [value]
|
36
|
-
else
|
37
|
-
value
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
return pairs
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class OptionSet
|
46
|
-
|
47
|
-
DEFAULTS = { :report => "tag",
|
48
|
-
:format => ["text"],
|
49
|
-
:input_dir => "features",
|
50
|
-
:output_file => [],
|
51
|
-
:tags => [],
|
52
|
-
:link_assets => false,
|
53
|
-
:copy_public_assets => false,
|
54
|
-
:use_copied_public_assets => false,
|
55
|
-
:dry_run => false,
|
56
|
-
:sort => true,
|
57
|
-
:number => true,
|
58
|
-
:total => true,
|
59
|
-
:show_tags => true,
|
60
|
-
:show_files => true,
|
61
|
-
:leaves => true
|
62
|
-
}
|
63
|
-
|
64
|
-
attr_reader :options
|
65
|
-
|
66
|
-
def initialize(file_config = {})
|
67
|
-
# CLI options replace any found in the file
|
68
|
-
cli_options_over_file_options = file_config.merge(Cuporter::Config::CLI::Options.options)
|
69
|
-
|
70
|
-
# defaults will be used for anything not so far specified in the file
|
71
|
-
# or CLI
|
72
|
-
@options = post_process(DEFAULTS.merge(cli_options_over_file_options))
|
73
|
-
end
|
74
|
-
|
75
|
-
def [](key)
|
76
|
-
@options[key]
|
77
|
-
end
|
78
|
-
|
79
|
-
def output_file(format)
|
80
|
-
if (file = @options[:output_file].find {|f| f =~ ext_for(format) })
|
81
|
-
File.open(file, "w")
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def dump
|
86
|
-
col_1_max = @options.keys.max_by {|i| i.to_s.length }.to_s.size
|
87
|
-
@options.each do |key, value|
|
88
|
-
puts ":#{key.to_s.ljust(col_1_max, ' ')} => #{value.inspect}"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def dry_run?
|
93
|
-
@options[:dry_run]
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def post_process(options)
|
99
|
-
options[:input_file_pattern] = options.delete(:input_file) || "#{options.delete(:input_dir)}/**/*.feature"
|
100
|
-
options[:root_dir] = options[:input_file_pattern].split(File::SEPARATOR).first
|
101
|
-
options[:filter_args] = Cuporter::Config::CLI::FilterArgsBuilder.new(options.delete(:tags)).args
|
102
|
-
options[:output_file].each_with_index do |file_path, i|
|
103
|
-
options[:output_file][i] = full_path(file_path.dup)
|
104
|
-
end
|
105
|
-
|
106
|
-
unless options[:output_file].find {|f| f =~ /\.html$/ }
|
107
|
-
options[:copy_public_assets] = options[:use_copied_public_assets] = false
|
108
|
-
end
|
109
|
-
|
110
|
-
options
|
111
|
-
end
|
112
|
-
|
113
|
-
def full_path(path)
|
114
|
-
expanded_path = File.expand_path(path)
|
115
|
-
path_nodes = expanded_path.split(File::SEPARATOR)
|
116
|
-
file = path_nodes.pop
|
117
|
-
FileUtils.makedirs(path_nodes.join(File::SEPARATOR))
|
118
|
-
expanded_path
|
119
|
-
end
|
120
|
-
|
121
|
-
def ext_for(format)
|
122
|
-
case format
|
123
|
-
when 'text', 'pretty'
|
124
|
-
/\.txt$/
|
125
|
-
else
|
126
|
-
/\.#{format}$/
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
10
|
def self.option_sets
|
133
|
-
if (yaml_hashes = Config::OptionSetCollection.config_file).any?
|
134
|
-
yaml_hashes.map {|
|
11
|
+
if (yaml_hashes = Config::YamlFile::OptionSetCollection.config_file).any?
|
12
|
+
yaml_hashes.map {|yaml_hash| Config::OptionSet.new(yaml_hash) }
|
135
13
|
else
|
136
14
|
[Config::OptionSet.new]
|
137
15
|
end
|
138
16
|
end
|
139
17
|
|
18
|
+
module Config
|
19
|
+
DEFAULTS = { :report => "tag",
|
20
|
+
:format => ["text"],
|
21
|
+
:input_dir => "features",
|
22
|
+
:output_file => [],
|
23
|
+
:output_home => "",
|
24
|
+
:log_dir => ".",
|
25
|
+
:tags => [],
|
26
|
+
:link_assets => false,
|
27
|
+
:copy_public_assets => false,
|
28
|
+
:use_copied_public_assets => false,
|
29
|
+
:dry_run => false,
|
30
|
+
:sort => true,
|
31
|
+
:number => true,
|
32
|
+
:total => true,
|
33
|
+
:show_tags => true,
|
34
|
+
:show_files => true,
|
35
|
+
:leaves => true }
|
140
36
|
|
37
|
+
end
|
141
38
|
end
|