cuker 0.3.15
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.
- checksums.yaml +7 -0
- data/.gitignore +71 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +16 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cuker.gemspec +43 -0
- data/lib/cuker.rb +7 -0
- data/lib/cuker/gherkin_lexer.rb +33 -0
- data/lib/cuker/gherkin_parser.rb +23 -0
- data/lib/cuker/gherkin_reporter.rb +85 -0
- data/lib/cuker/gherkin_ripper.rb +67 -0
- data/lib/cuker/gp.rb +82 -0
- data/lib/cuker/helper/file_helper.rb +14 -0
- data/lib/cuker/helper/gherkin_helper.rb +28 -0
- data/lib/cuker/high.rb +57 -0
- data/lib/cuker/log_utils.rb +88 -0
- data/lib/cuker/models/model_try.rb +30 -0
- data/lib/cuker/models/models_forming.rb +65 -0
- data/lib/cuker/models/models_ready.rb +132 -0
- data/lib/cuker/models/state.rb +3 -0
- data/lib/cuker/state/in_background.rb +0 -0
- data/lib/cuker/state/in_comment.rb +3 -0
- data/lib/cuker/state/in_feature.rb +0 -0
- data/lib/cuker/state/in_scenario.rb +0 -0
- data/lib/cuker/state/in_scenario_outline.rb +0 -0
- data/lib/cuker/state/in_table.rb +0 -0
- data/lib/cuker/state/in_tag.rb +0 -0
- data/lib/cuker/version.rb +3 -0
- data/lib/cuker/writer_helper/_interfact.rb +7 -0
- data/lib/cuker/writer_helper/abstract_model.rb +37 -0
- data/lib/cuker/writer_helper/abstract_writer.rb +77 -0
- data/lib/cuker/writer_helper/csv_model.rb +148 -0
- data/lib/cuker/writer_helper/csv_writer.rb +59 -0
- data/lib/cuker/writer_helper/jira_model.rb +174 -0
- data/lib/cuker/writer_helper/jira_writer.rb +55 -0
- data/lib/cuker/writer_helper/ruby_x_l_writer.rb +32 -0
- data/lib/cuker/writer_helper/title.rb +14 -0
- metadata +129 -0
data/lib/cuker/gp.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
require 'require_all'
|
4
|
+
# require_all 'lib/cuker/**/*.rb'
|
5
|
+
# require_all 'lib/cuker/*.rb'
|
6
|
+
require_rel '**/*.rb'
|
7
|
+
require_rel '*.rb'
|
8
|
+
|
9
|
+
|
10
|
+
module Cuker
|
11
|
+
module GPHelper
|
12
|
+
def self.dash_print(ary)
|
13
|
+
# ary.each {|x| puts " - '#{x}'"}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class GherkinParserCmd < Thor
|
18
|
+
include LoggerSetup
|
19
|
+
|
20
|
+
GPTOOL = GherkinParser.new
|
21
|
+
PRESET_LOCS = ['*', './*']
|
22
|
+
|
23
|
+
desc "gp LOCATION", "parse all *.feature files in the given LOCATION"
|
24
|
+
|
25
|
+
def gp loc = "../jira*/**/*", file_name = nil
|
26
|
+
init
|
27
|
+
@log.warn "running GPTOOL @ #{loc}"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "gpp", "parse all *.feature files in the preset locations: \n#{GPHelper.dash_print PRESET_LOCS}"
|
31
|
+
|
32
|
+
def gpp
|
33
|
+
init
|
34
|
+
@log.warn "running GPTOOL @ #{PRESET_LOCS}"
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
desc "gpr FEATURE_PATH REPORT_PATH [REPORT_FILE_NAME]",
|
39
|
+
"reports parsed results into REPORT_FILE_NAME for all *.feature files in the given LOCATION"
|
40
|
+
|
41
|
+
def gpr report_file_name = 'sample_report', feat_path = "../", report_path = "reports"
|
42
|
+
init
|
43
|
+
@log.warn "running GPTOOL @ '#{feat_path}' => '#{report_path}' '#{report_file_name}.csv' "
|
44
|
+
|
45
|
+
report_path = File.join report_path, LOG_TIME_TODAY
|
46
|
+
@log.info Dir.pwd
|
47
|
+
|
48
|
+
gr = GherkinRipper.new feat_path
|
49
|
+
ast_map = gr.ast_map
|
50
|
+
csv_model = CsvModel.new ast_map
|
51
|
+
csv_writer = CsvWriter.new
|
52
|
+
grr = GherkinReporter.new csv_writer, csv_model, report_path, report_file_name
|
53
|
+
grr.write
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "gpj FEATURE_PATH REPORT_PATH [REPORT_FILE_NAME]",
|
57
|
+
"reports parsed results into REPORT_FILE_NAME for all *.feature files in the given LOCATION"
|
58
|
+
|
59
|
+
def gpj feat_path = "spec/cuker_spec/testdata", report_path = "reports/#{LOG_TIME_TODAY}", report_file_name = 'sample_report'
|
60
|
+
init
|
61
|
+
@log.warn "running GPTOOL @ '#{feat_path}' => '#{report_path}' '#{report_file_name}.csv' "
|
62
|
+
|
63
|
+
@log.info Dir.pwd
|
64
|
+
|
65
|
+
gr = GherkinRipper.new feat_path
|
66
|
+
ast_map = gr.ast_map
|
67
|
+
csv_model = JiraModel.new ast_map
|
68
|
+
csv_writer = JiraWriter.new
|
69
|
+
grr = GherkinReporter.new csv_writer, csv_model, report_path, report_file_name
|
70
|
+
grr.write
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def init
|
77
|
+
init_logger :warn
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# GherkinParserCmd.start(ARGV)
|
82
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module FileHelper
|
2
|
+
def self.get_files path, target_pattern, ignore_patterns = nil
|
3
|
+
Dir.glob("#{path}/**/*#{target_pattern}").select {|x| x !~ ignore_patterns}
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.get_file file_name, target_pattern, ignore_patterns = nil
|
7
|
+
Dir.glob("*#{file_name}*#{target_pattern}").select {|x| x !~ ignore_patterns}
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.file_path path, file_name
|
11
|
+
FileUtils.mkdir_p(path) unless Dir.exist? path
|
12
|
+
File.join(path, file_name)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'gherkin/parser'
|
2
|
+
require 'gherkin/token_scanner'
|
3
|
+
require 'gherkin/token_matcher'
|
4
|
+
require 'gherkin/ast_builder'
|
5
|
+
require 'gherkin/errors'
|
6
|
+
|
7
|
+
module GherkinHelper
|
8
|
+
include Gherkin
|
9
|
+
|
10
|
+
def parse_handle(file_name)
|
11
|
+
begin
|
12
|
+
yield
|
13
|
+
rescue Gherkin::ParserError => e
|
14
|
+
msg = "unable to read #{file_name}..\n Issues:\n#{error_digest e}"
|
15
|
+
@log.error msg
|
16
|
+
#todo: handle issues promot to user on cli
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def error_digest(e)
|
21
|
+
# todo: maybe give friendly error promots?
|
22
|
+
e.errors.map do |err|
|
23
|
+
err.message
|
24
|
+
.gsub(/^\((\d+):(\d+)\):/, ' ( line \1 : char \2 ) :')
|
25
|
+
# .gsub(' : ', "\t:\t") # not so pretty, but if needed
|
26
|
+
end.join "\n"
|
27
|
+
end
|
28
|
+
end
|
data/lib/cuker/high.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# require 'highline'
|
2
|
+
#
|
3
|
+
# # Basic usage
|
4
|
+
#
|
5
|
+
# cli = HighLine.new
|
6
|
+
# answer = cli.ask "What do you think?"
|
7
|
+
# puts "You have answered: #{answer}"
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# # Default answer
|
11
|
+
#
|
12
|
+
# cli.ask("Company? ") { |q| q.default = "none" }
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# # Validation
|
16
|
+
#
|
17
|
+
# cli.ask("Age? ", Integer) { |q| q.in = 0..105 }
|
18
|
+
# cli.ask("Name? (last, first) ") { |q| q.validate = /\A\w+, ?\w+\Z/ }
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# # Type conversion for answers:
|
22
|
+
#
|
23
|
+
# cli.ask("Birthday? ", Date)
|
24
|
+
# cli.ask("Interests? (comma sep list) ", lambda { |str| str.split(/,\s*/) })
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# # Reading passwords:
|
28
|
+
#
|
29
|
+
# cli.ask("Enter your password: ") { |q| q.echo = false }
|
30
|
+
# cli.ask("Enter your password: ") { |q| q.echo = "x" }
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# # ERb based output (with HighLine's ANSI color tools):
|
34
|
+
#
|
35
|
+
# cli.say("This should be <%= color('bold', BOLD) %>!")
|
36
|
+
#
|
37
|
+
#
|
38
|
+
# # Menus:
|
39
|
+
#
|
40
|
+
# cli.choose do |menu|
|
41
|
+
# menu.prompt = "Please choose your favorite programming language? "
|
42
|
+
# menu.choice(:ruby) { cli.say("Good choice!") }
|
43
|
+
# menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
|
44
|
+
# menu.default = :ruby
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# ## Using colored indices on Menus
|
48
|
+
#
|
49
|
+
# HighLine::Menu.index_color = :rgb_77bbff # set default index color
|
50
|
+
#
|
51
|
+
# cli.choose do |menu|
|
52
|
+
# menu.index_color = :rgb_999999 # override default color of index
|
53
|
+
# # you can also use constants like :blue
|
54
|
+
# menu.prompt = "Please choose your favorite programming language? "
|
55
|
+
# menu.choice(:ruby) { cli.say("Good choice!") }
|
56
|
+
# menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
|
57
|
+
# end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# $LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}")
|
2
|
+
require 'logging'
|
3
|
+
|
4
|
+
# Logger params
|
5
|
+
Logging.init :trace, :debug, :info, :warn, :error, :fatal
|
6
|
+
|
7
|
+
# Custom colour set
|
8
|
+
Logging.color_scheme('my_bright',
|
9
|
+
:levels => {
|
10
|
+
:trace => :white,
|
11
|
+
:debug => :blue,
|
12
|
+
:info => :green,
|
13
|
+
:warn => :yellow,
|
14
|
+
:error => :red,
|
15
|
+
:fatal => [:black, :on_red]
|
16
|
+
},
|
17
|
+
:date => :blue,
|
18
|
+
:logger => :cyan,
|
19
|
+
:message => :white
|
20
|
+
)
|
21
|
+
|
22
|
+
# https://www.rubydoc.info/gems/logging/Logging/Layouts/Pattern/FormatMethodBuilder
|
23
|
+
|
24
|
+
LOG_PATTERN_SIMPLE = "[%d] %-5l %m\n"
|
25
|
+
LOG_PATTERN_WITH_CLASS = "[%d] %-5l %c: %m\n"
|
26
|
+
LOG_PATTERN_WITH_METHODS = "[%d] %-5l %c: %M: %m\n" # need to get this to work
|
27
|
+
LOG_PATTERN_WITH_ALL = "[%d] %-5l %c: %M: %h: %p: %r: %T: %t: %F: %L: %M: %x\n"
|
28
|
+
|
29
|
+
|
30
|
+
TIMESTAMP_PATTERN = "%Y-%m-%d %H:%M:%S.%L"
|
31
|
+
LOG_TIME_TODAY = Time.now.strftime("%Y-%m-%d")
|
32
|
+
LOG_TIME_NOW = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
|
33
|
+
|
34
|
+
LOG_LOC = "./logs"
|
35
|
+
LOG_FILE = "log_#{LOG_TIME_TODAY}.log"
|
36
|
+
LOG_FILE_PATH = File.join(LOG_LOC, LOG_FILE)
|
37
|
+
|
38
|
+
LOG_STDOUT = 'stdout'
|
39
|
+
|
40
|
+
Dir.mkdir(LOG_LOC) unless Dir.exists? LOG_LOC
|
41
|
+
|
42
|
+
module LoggerSetup
|
43
|
+
def self.reset_appender_log_levels stdout_level = :info, file_level = :trace
|
44
|
+
|
45
|
+
# Stdout appender
|
46
|
+
Logging.appenders.stdout(LOG_STDOUT,
|
47
|
+
# level: :info, # a different log level to your file appender
|
48
|
+
level: stdout_level, # a different log level to your file appender
|
49
|
+
layout: Logging.layouts.pattern(
|
50
|
+
pattern: LOG_PATTERN_WITH_CLASS,
|
51
|
+
color_scheme: 'my_bright', # best not to use color_schemes on file loggers
|
52
|
+
date_pattern: TIMESTAMP_PATTERN))
|
53
|
+
|
54
|
+
# File appender
|
55
|
+
Logging.appenders.file(LOG_FILE_PATH,
|
56
|
+
# level: :debug, # or your custom lowest level init-ed
|
57
|
+
level: file_level, # or your custom lowest level init-ed
|
58
|
+
layout: Logging.layouts.pattern(
|
59
|
+
pattern: LOG_PATTERN_WITH_CLASS,
|
60
|
+
# color_scheme: 'my_bright', # best not to use color_schemes on file loggers
|
61
|
+
date_pattern: TIMESTAMP_PATTERN),
|
62
|
+
# truncate: true, # if you want to clear old log information
|
63
|
+
# age: 5 * 60, # feel free to play around with these
|
64
|
+
roll_by: :date # for rolling logs if you want to change files periodically
|
65
|
+
)
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# to restore defaults, run
|
71
|
+
# LoggerSetup.reset_appender_log_levels # stdout_level = :info, file_level = :debug
|
72
|
+
LoggerSetup.reset_appender_log_levels :error, :trace
|
73
|
+
|
74
|
+
|
75
|
+
# sample logger setup module
|
76
|
+
module LoggerSetup
|
77
|
+
attr_reader :log
|
78
|
+
|
79
|
+
def init_logger(level = nil)
|
80
|
+
@log = Logging.logger[self]
|
81
|
+
@log.level = level || :debug # your lowest level
|
82
|
+
@log.add_appenders(
|
83
|
+
LOG_STDOUT,
|
84
|
+
LOG_FILE_PATH
|
85
|
+
)
|
86
|
+
@log
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# class Item
|
2
|
+
#
|
3
|
+
# end
|
4
|
+
#
|
5
|
+
# class Collection
|
6
|
+
# attr_accessor :tags
|
7
|
+
# attr_accessor :title, :comments
|
8
|
+
# attr_accessor :items
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# class Feature < Collection
|
12
|
+
# attr_accessor :background
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class Background < Collection
|
16
|
+
#
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# class Scenario < Collection
|
20
|
+
#
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# class ScenarioOutline < Scenario
|
24
|
+
# attr_accessor :examples
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# class Step < Item
|
28
|
+
# attr_accessor :keyword, :line
|
29
|
+
# attr_accessor :table # optional
|
30
|
+
# end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# class Item
|
2
|
+
# attr_accessor :content
|
3
|
+
# end
|
4
|
+
#
|
5
|
+
# class Step < Item
|
6
|
+
# attr_accessor :keyword, :line
|
7
|
+
# attr_accessor :table # optional
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# class Comment < Item
|
11
|
+
#
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class InlineComment < Comment
|
15
|
+
#
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# class Tag < Item
|
19
|
+
#
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# class Row < Item
|
23
|
+
#
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# class Collection < Item
|
27
|
+
# attr_accessor :items
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# class Tags < Collection
|
31
|
+
#
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# class Table < Collection
|
35
|
+
#
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# class Example < Table
|
39
|
+
#
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# class SimpleGherkinCollection < Collection
|
43
|
+
# attr_accessor :title, :comments
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# class Background < SimpleGherkinCollection
|
47
|
+
#
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# class TaggedGherkinCollection < SimpleGherkinCollection
|
51
|
+
# attr_accessor :tags
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# class Feature < TaggedGherkinCollection
|
55
|
+
# attr_accessor :background
|
56
|
+
# # attr_accessor :collections
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# class Scenario < TaggedGherkinCollection
|
60
|
+
#
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# class ScenarioOutline < Scenario
|
64
|
+
# attr_accessor :examples
|
65
|
+
# end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
class Item
|
2
|
+
attr_accessor :content
|
3
|
+
|
4
|
+
def initialize content_str
|
5
|
+
@content = content_str
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
@content
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Step < Item
|
14
|
+
attr_accessor :keyword, :line
|
15
|
+
attr_accessor :table # optional
|
16
|
+
end
|
17
|
+
|
18
|
+
class Comment < Item
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class InlineComment < Comment
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
class Tag < Item
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class TableRow < Item
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class Collection < Item
|
35
|
+
attr_accessor :items
|
36
|
+
attr_reader :keyword
|
37
|
+
|
38
|
+
def initialize content_str
|
39
|
+
super content_str
|
40
|
+
@items = []
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
([super] + items.map(&:to_s)).join "\n"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Tags < Collection
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
class Table < Collection
|
53
|
+
attr_accessor :title_row, :table_rows
|
54
|
+
def initialize content_str
|
55
|
+
super content_str
|
56
|
+
@table_rows = []
|
57
|
+
@title_row = @items[0]
|
58
|
+
@table_rows = @items[1..-1]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class Examples < Table
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class SimpleGherkinCollection < Collection
|
68
|
+
attr_accessor :title, :comments
|
69
|
+
|
70
|
+
def initialize content_str, keyword
|
71
|
+
super content_str
|
72
|
+
@title = parse_title content_str, keyword
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_title content, keyword
|
76
|
+
match = content[/^\s*#{keyword}(.*)$/, 1]
|
77
|
+
warn "no matches for '#{keyword}' in '#{content}'" unless match
|
78
|
+
match
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Background < SimpleGherkinCollection
|
83
|
+
def initialize content_str
|
84
|
+
@keyword = "Background:"
|
85
|
+
super content_str, keyword
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class TaggedGherkinCollection < SimpleGherkinCollection
|
90
|
+
attr_accessor :tags
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
class Feature < TaggedGherkinCollection
|
95
|
+
attr_accessor :background
|
96
|
+
|
97
|
+
def initialize content_str
|
98
|
+
@keyword = "Feature:"
|
99
|
+
super content_str, keyword
|
100
|
+
#todo: think about item ordering
|
101
|
+
end
|
102
|
+
|
103
|
+
def comments= content
|
104
|
+
@items << content
|
105
|
+
@comments = content
|
106
|
+
end
|
107
|
+
|
108
|
+
def tags= content
|
109
|
+
@items << content
|
110
|
+
@tags = content
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
class Scenario < TaggedGherkinCollection
|
116
|
+
attr_accessor :steps
|
117
|
+
|
118
|
+
def initialize content_str, keyword = "Scenario:"
|
119
|
+
@steps = []
|
120
|
+
@keyword = keyword
|
121
|
+
super content_str, @keyword
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class ScenarioOutline < Scenario
|
126
|
+
attr_accessor :examples
|
127
|
+
|
128
|
+
def initialize content_str, keyword = "Scenario Outline:"
|
129
|
+
@keyword = keyword
|
130
|
+
super content_str, @keyword
|
131
|
+
end
|
132
|
+
end
|