uicov 0.0.1
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 +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +20 -0
- data/LICENSE +22 -0
- data/README.md +42 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/bin/uicov +6 -0
- data/lib/uicov.rb +33 -0
- data/lib/uicov/commands/command.rb +23 -0
- data/lib/uicov/commands/gather.rb +171 -0
- data/lib/uicov/commands/gentpl.rb +129 -0
- data/lib/uicov/commands/merge.rb +95 -0
- data/lib/uicov/commands/report.rb +119 -0
- data/lib/uicov/consts.rb +78 -0
- data/lib/uicov/coverage/action_data.rb +8 -0
- data/lib/uicov/coverage/check_data.rb +8 -0
- data/lib/uicov/coverage/data.rb +45 -0
- data/lib/uicov/coverage/element_data.rb +8 -0
- data/lib/uicov/coverage/member_data.rb +18 -0
- data/lib/uicov/coverage/screen_data.rb +109 -0
- data/lib/uicov/coverage/transition_data.rb +18 -0
- data/lib/uicov/coverage/types.rb +13 -0
- data/lib/uicov/coverage_data.rb +72 -0
- data/lib/uicov/coverage_info.rb +27 -0
- data/lib/uicov/main.rb +53 -0
- data/lib/uicov/opts.rb +28 -0
- data/lib/uicov/ruby_patches.rb +36 -0
- data/lib/uicov/screen_info.rb +7 -0
- data/lib/uicov/transition_info.rb +11 -0
- data/lib/uicov/ui_coverage.rb +91 -0
- data/lib/uicov/version.rb +7 -0
- data/rakefile +7 -0
- data/uicov.gemspec +32 -0
- metadata +110 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class TransitionData < MemberData
|
7
|
+
def self.get_key(transition_name, to)
|
8
|
+
"#{transition_name}(#{to})"
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(transition_name, to)
|
12
|
+
@name = transition_name
|
13
|
+
@to = to
|
14
|
+
@display_name = self.class.get_key @name, @to
|
15
|
+
@hits = 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class CoverageDataType
|
7
|
+
COVERAGE = :COVERAGE # Gathered coverage
|
8
|
+
TEMPLATE = :TEMPLATE # Coverage template
|
9
|
+
FULL = :FULL # Merged template and coverage data
|
10
|
+
UNKNOWN = :UNKNOWN # Unknown (set by default)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class CoverageData
|
7
|
+
def screens
|
8
|
+
@screens ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def transitions
|
12
|
+
@transitions ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def str_puml(msg=nil, nl=1)
|
16
|
+
@str_puml ||= ""
|
17
|
+
unless msg.nil?
|
18
|
+
@str_puml << "#{msg}" + "\n" * nl
|
19
|
+
end
|
20
|
+
return @str_puml
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_screen(name)
|
24
|
+
screens[name.to_sym] = ScreenInfo.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def hit_screen(name)
|
28
|
+
name = name.to_sym
|
29
|
+
info = screens.fetch(name, ScreenInfo.new(true))
|
30
|
+
screens[name] = info.hit
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_transition(from, to, name)
|
34
|
+
transitions[TransitionInfo.key(from, to, name)] = TransitionInfo.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def hit_transition(from, to, name)
|
38
|
+
key = TransitionInfo.key(from, to, name)
|
39
|
+
info = transitions.fetch(key, TransitionInfo.new(true))
|
40
|
+
transitions[key] = info.hit
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_puml(file_name=nil)
|
44
|
+
str_puml '@startuml'
|
45
|
+
str_puml SKIN_PARAMS, 0
|
46
|
+
str_puml LEGEND if Opts::Puml[:add_legend]
|
47
|
+
|
48
|
+
screens.each_pair do |screen_name, screen_info|
|
49
|
+
stereotype = ''
|
50
|
+
stereotype = "<<#{Opts::Puml[:covered_class_stereotype]}>>" if screen_info.covered?
|
51
|
+
stereotype = "<<#{Opts::Puml[:missed_class_stereotype]}>>" if screen_info.missed?
|
52
|
+
str_puml "state #{screen_name}#{stereotype}"
|
53
|
+
mm = transitions.map{|pair| pair if pair[0][0] == screen_name}.compact.each do |transition, transition_info|
|
54
|
+
#str_puml transition
|
55
|
+
str_puml "#{transition[0]} --> #{transition[1]} : #{transition[2]}"
|
56
|
+
#str_puml "#{transition}"
|
57
|
+
end
|
58
|
+
|
59
|
+
str_puml ''
|
60
|
+
end
|
61
|
+
|
62
|
+
str_puml '@enduml'
|
63
|
+
|
64
|
+
if file_name.nil?
|
65
|
+
return str_puml
|
66
|
+
else
|
67
|
+
Log.unknown "Storing results in file #{File.expand_path(file_name)}"
|
68
|
+
File.open(file_name, 'w') {|f| f.write str_puml}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class CoverageInfo
|
7
|
+
attr_reader :hits
|
8
|
+
|
9
|
+
def initialize(missed = false)
|
10
|
+
@hits = 0
|
11
|
+
@missed = missed
|
12
|
+
end
|
13
|
+
|
14
|
+
def missed?
|
15
|
+
@missed
|
16
|
+
end
|
17
|
+
|
18
|
+
def covered?
|
19
|
+
0 < hits
|
20
|
+
end
|
21
|
+
|
22
|
+
def hit
|
23
|
+
@hits = hits.succ
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/uicov/main.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
def self.patterns_override(target, &blk)
|
7
|
+
case target
|
8
|
+
when :log
|
9
|
+
LogPatterns.class_exec &blk
|
10
|
+
else
|
11
|
+
Log.fatal "Unknown target '#{target}' in pattern file '#{caller[0]}'"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Main
|
16
|
+
COMMANDS = {
|
17
|
+
gentpl: 'Generate coverage template file',
|
18
|
+
gather: 'Gather coverage information from log file',
|
19
|
+
report: 'Generate coverage report',
|
20
|
+
merge: 'Merge coverage files',
|
21
|
+
}
|
22
|
+
|
23
|
+
COMMANDS.keys.each { |k| require_relative "commands/#{k}" }
|
24
|
+
|
25
|
+
def self.do_command(args)
|
26
|
+
if args.empty?
|
27
|
+
usage "Command is not specified"
|
28
|
+
else
|
29
|
+
cmd_name = args[0]
|
30
|
+
usage "Wrong command '#{cmd_name}'" unless COMMANDS.keys.include? cmd_name.to_sym
|
31
|
+
class_type = UICov.const_get cmd_name.capitalize
|
32
|
+
class_type.new.do_job args[1..-1]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.usage(err_msg)
|
37
|
+
msg = %Q^
|
38
|
+
\rERROR: #{err_msg}\n
|
39
|
+
\rUsage:
|
40
|
+
\r\t#{$0} command [command_arguments]\n
|
41
|
+
\rCommands are:
|
42
|
+
#{COMMANDS.inject([]){|a, e| a << "\r\t#{e[0]}\t- #{e[1]}"; a}.join("\n")}
|
43
|
+
|
44
|
+
\rTo see command usage run:
|
45
|
+
\r\t#{$0} command\n
|
46
|
+
\rFor instance:
|
47
|
+
\r\t#{$0} gather\n
|
48
|
+
^
|
49
|
+
Log.fatal msg
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/lib/uicov/opts.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class Opts
|
7
|
+
Patterns = {
|
8
|
+
:current_screen => nil,
|
9
|
+
:transition => nil,
|
10
|
+
:transition_from => 2,
|
11
|
+
:transition_to => 3,
|
12
|
+
:transition_name => 1,
|
13
|
+
:model_screen => /^state\s+([^ ]+)$/,
|
14
|
+
:model_transition => /^([^ ]+)\s+([-]+\>)\s+([^ ]+)\s+:\s+([^ ]+)$/,
|
15
|
+
}
|
16
|
+
|
17
|
+
Files = {
|
18
|
+
:log => nil,
|
19
|
+
:model => nil,
|
20
|
+
}
|
21
|
+
|
22
|
+
Puml = {
|
23
|
+
:add_legend => true,
|
24
|
+
:missed_class_stereotype => 'Missed',
|
25
|
+
:covered_class_stereotype => 'Covered',
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
class Logger
|
6
|
+
class Formatter
|
7
|
+
MyFormat = "[%s] %s: %s: %s\n"
|
8
|
+
def call(severity, time, progname, msg)
|
9
|
+
@datetime_format ||= "%H:%M:%S.%5N"
|
10
|
+
MyFormat % [format_datetime(time), severity, progname, msg2str(msg)]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
alias :_add :add
|
15
|
+
alias :_fatal :fatal
|
16
|
+
|
17
|
+
def add(severity, message, progname, &blk)
|
18
|
+
progname_orig = self.progname
|
19
|
+
self.progname = get_caller
|
20
|
+
_add(severity, message, progname, &blk)
|
21
|
+
self.progname = progname_orig
|
22
|
+
end
|
23
|
+
|
24
|
+
def fatal(*args, &blk)
|
25
|
+
_fatal(*args, &blk)
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def get_caller(idx=2)
|
31
|
+
caller[idx].sub(/.*\//, '')
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_count(severity) ; end # TODO count warnings and errors
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class UICoverage
|
7
|
+
def cov_data
|
8
|
+
@cd ||= CoverageData.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def init(opts={})
|
12
|
+
# if PATTERN_FILE.nil? or !File.exists?(PATTERN_FILE)
|
13
|
+
# usage "Patterns file is not provided or it's absent by path: '#{PATTERN_FILE}'"
|
14
|
+
# end
|
15
|
+
input_log = (Opts::Files[:log] = opts[:log])
|
16
|
+
if input_log.nil? or !File.exists?(input_log)
|
17
|
+
UICov.usage "Input log file is not provided or it's absent by path: '#{input_log}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
model_file = (Opts::Files[:model] = opts[:model])
|
21
|
+
if model_file.nil? or !File.exists?(model_file)
|
22
|
+
Log.warn "\n\n\tModel file is not provided or it's absent by path: '#{model_file}'" +
|
23
|
+
"\n\tYou won't be able to see uncovered metrics as well as all hits will be" +
|
24
|
+
"reported not as 'covered' but as 'missed in model'\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
Opts::Patterns.keys.each {|key| Opts::Patterns[key] = opts[key] unless opts[key].nil?}
|
28
|
+
|
29
|
+
#d "Using pattern file: #{PATTERN_FILE}"
|
30
|
+
#d "Unsing model file: #{MODEL_FILE}"
|
31
|
+
Log.debug "Parsing log file: #{Opts::Files[:log]}"
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_model
|
36
|
+
model_file = Opts::Files[:model]
|
37
|
+
return if model_file.nil?
|
38
|
+
|
39
|
+
Log.debug "Loading model file: #{model_file}"
|
40
|
+
|
41
|
+
File.open(model_file).each do |line|
|
42
|
+
case line.chomp
|
43
|
+
when /^['@]/ # Do nothing
|
44
|
+
when /^\s*$/ # Do nothing
|
45
|
+
when Opts::Patterns[:model_screen]
|
46
|
+
name = $~[1] # $~ - is MatchData of the latest regexp match
|
47
|
+
cov_data.add_screen name
|
48
|
+
when Opts::Patterns[:model_transition]
|
49
|
+
from, to, name = $~[1], $~[3], $~[4]
|
50
|
+
cov_data.add_transition from, to, name
|
51
|
+
cov_data.add_screen from
|
52
|
+
cov_data.add_screen to
|
53
|
+
else
|
54
|
+
Log.warn "Unable to parse model line: #{line}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# %w[HomeScreen CheckoutScreen OneMoreScreen].each do |name|
|
59
|
+
# cov_data.add_screen name
|
60
|
+
# end
|
61
|
+
# [%w[HomeScreen CheckoutScreen checkout], %w[CheckoutScreen OneMoreScreen one_more],
|
62
|
+
# %w[OneMoreScreen CheckoutScreen checkout], %w[HomeScreen OneMoreScreen more]].each do |from, to, name|
|
63
|
+
# cov_data.add_transition from, to, name
|
64
|
+
# end
|
65
|
+
return self
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_log
|
69
|
+
transition_indexes = %w[from to name].map{|e| Opts::Patterns["transition_#{e}".to_sym]}
|
70
|
+
File.open(Opts::Files[:log]).each do |line|
|
71
|
+
case line
|
72
|
+
when Opts::Patterns[:current_screen]
|
73
|
+
name = $~[1] # $~ - is MatchData of the latest regexp match
|
74
|
+
cov_data.hit_screen name
|
75
|
+
when Opts::Patterns[:transition]
|
76
|
+
from, to, name = transition_indexes.map{|i| $~[i]}
|
77
|
+
cov_data.hit_transition from, to, name
|
78
|
+
else
|
79
|
+
#d line
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def gather_coverage(opts={})
|
85
|
+
init opts
|
86
|
+
parse_model
|
87
|
+
parse_log
|
88
|
+
return cov_data
|
89
|
+
end
|
90
|
+
end # of UICoverage class
|
91
|
+
end
|
data/rakefile
ADDED
data/uicov.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'uicov/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'uicov'
|
8
|
+
spec.version = Uicov::VERSION
|
9
|
+
spec.authors = ['Alexey Lyanguzov']
|
10
|
+
spec.email = ['budabum@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{Tool to measure UI autotests coverage.}
|
13
|
+
spec.description = %q{Tool is applicable for any autotest's language becuase it parses log files.}
|
14
|
+
spec.homepage = 'https://github.com/budabum/uicov'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = 'http://RubyGems.org'
|
21
|
+
# else
|
22
|
+
# raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = 'bin'
|
27
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: uicov
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexey Lyanguzov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Tool is applicable for any autotest's language becuase it parses log
|
42
|
+
files.
|
43
|
+
email:
|
44
|
+
- budabum@gmail.com
|
45
|
+
executables:
|
46
|
+
- console
|
47
|
+
- setup
|
48
|
+
- uicov
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- ".gitignore"
|
53
|
+
- Gemfile
|
54
|
+
- Gemfile.lock
|
55
|
+
- LICENSE
|
56
|
+
- README.md
|
57
|
+
- bin/console
|
58
|
+
- bin/setup
|
59
|
+
- bin/uicov
|
60
|
+
- lib/uicov.rb
|
61
|
+
- lib/uicov/commands/command.rb
|
62
|
+
- lib/uicov/commands/gather.rb
|
63
|
+
- lib/uicov/commands/gentpl.rb
|
64
|
+
- lib/uicov/commands/merge.rb
|
65
|
+
- lib/uicov/commands/report.rb
|
66
|
+
- lib/uicov/consts.rb
|
67
|
+
- lib/uicov/coverage/action_data.rb
|
68
|
+
- lib/uicov/coverage/check_data.rb
|
69
|
+
- lib/uicov/coverage/data.rb
|
70
|
+
- lib/uicov/coverage/element_data.rb
|
71
|
+
- lib/uicov/coverage/member_data.rb
|
72
|
+
- lib/uicov/coverage/screen_data.rb
|
73
|
+
- lib/uicov/coverage/transition_data.rb
|
74
|
+
- lib/uicov/coverage/types.rb
|
75
|
+
- lib/uicov/coverage_data.rb
|
76
|
+
- lib/uicov/coverage_info.rb
|
77
|
+
- lib/uicov/main.rb
|
78
|
+
- lib/uicov/opts.rb
|
79
|
+
- lib/uicov/ruby_patches.rb
|
80
|
+
- lib/uicov/screen_info.rb
|
81
|
+
- lib/uicov/transition_info.rb
|
82
|
+
- lib/uicov/ui_coverage.rb
|
83
|
+
- lib/uicov/version.rb
|
84
|
+
- rakefile
|
85
|
+
- uicov.gemspec
|
86
|
+
homepage: https://github.com/budabum/uicov
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.4.8
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Tool to measure UI autotests coverage.
|
110
|
+
test_files: []
|