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