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.
@@ -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
@@ -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
+
@@ -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,7 @@
1
+ #=======
2
+ # Author: Alexey Lyanguzov (budabum@gmail.com)
3
+ #=======
4
+
5
+ module UICov
6
+ ScreenInfo = Class.new(CoverageInfo)
7
+ end
@@ -0,0 +1,11 @@
1
+ #=======
2
+ # Author: Alexey Lyanguzov (budabum@gmail.com)
3
+ #=======
4
+
5
+ module UICov
6
+ class TransitionInfo < CoverageInfo
7
+ def self.key(from, to, name)
8
+ [from.to_sym, to.to_sym, name.to_sym]
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ #=======
2
+ # Author: Alexey Lyanguzov (budabum@gmail.com)
3
+ #=======
4
+
5
+ module Uicov
6
+ VERSION = "0.0.1"
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = FileList['test/test*.rb']
6
+ end
7
+
@@ -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: []