uicov 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []