uicov 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d5c6a7f053f39807b5f5ab5da31b18117ce0c718
|
4
|
+
data.tar.gz: 9fce20843493441f4d8aad9f06899fdbf1879f3f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 255f4841e978db2715df5d7f563562abeee17ee5dcab15e54498264b4016f270419b2af657b395dd257c4cad153703a1bc1283cfb708aa6f2cd5eab734d4c21e
|
7
|
+
data.tar.gz: efede2b63b4a16cde4182e790ef43b547337501c14a467a35bb2b9033fdc4f0e10510df8095e9a609c433fd577ec7070a66fee3ec072a42f33e7967ed063742b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Alexey Lyanguzov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Uicov
|
2
|
+
UICov is a tool to calculate coverage of automated tests made with Selenium WebDriver, Calabash, Appium or other tools.
|
3
|
+
|
4
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/uicov`. To experiment with that code, run `bin/console` for an interactive prompt.
|
5
|
+
|
6
|
+
TODO: Delete this and the text above, and describe your gem
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'uicov'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install uicov
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
TODO: Write usage instructions here
|
27
|
+
|
28
|
+
## Development
|
29
|
+
|
30
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
31
|
+
|
32
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
33
|
+
|
34
|
+
## Contributing
|
35
|
+
|
36
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/uicov.
|
37
|
+
|
38
|
+
|
39
|
+
## License
|
40
|
+
|
41
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
42
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "uicov"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/bin/uicov
ADDED
data/lib/uicov.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
require 'logger'
|
6
|
+
require 'pp'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
module UICov
|
10
|
+
GEM_HOME = File.expand_path("#{File.dirname(__FILE__)}/..")
|
11
|
+
$LOAD_PATH.unshift GEM_HOME
|
12
|
+
require 'lib/uicov/consts'
|
13
|
+
|
14
|
+
def self.gather_coverage(opts={})
|
15
|
+
UICoverage.new.gather_coverage(opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
###########################
|
20
|
+
# E N T R Y P O I N T
|
21
|
+
############################
|
22
|
+
if __FILE__ == $0
|
23
|
+
opts = {
|
24
|
+
:log => 'logPM.txt',
|
25
|
+
:model => "#{UICov::GEM_TESTS_DATA_DIR}/model1.puml",
|
26
|
+
:current_screen => /\s+<==\s+([^ ]+)\s+is set as current screen/,
|
27
|
+
:transition => /Transition '([^ ]+)'.*from '([^ ]+)'.*to '([^ ]+)'/
|
28
|
+
}
|
29
|
+
cov = UICov.gather_coverage(opts)
|
30
|
+
cov.to_puml('log.puml')
|
31
|
+
pp cov
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class Command
|
7
|
+
COMMAND_PREFIX = "#{$0} #{ARGV[0]}"
|
8
|
+
def do_job(args)
|
9
|
+
Log.fatal "Method #{__method__} is not overridden in class #{self.class.name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def usage(err_msg='', cmd_usage_info='')
|
13
|
+
msg = %Q^
|
14
|
+
\rERROR: #{err_msg}\n
|
15
|
+
\rUsage:
|
16
|
+
\r\t#{COMMAND_PREFIX} #{cmd_usage_info}
|
17
|
+
^
|
18
|
+
|
19
|
+
Log.fatal msg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,171 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
$default_screen = :DefaultScreen
|
6
|
+
|
7
|
+
module UICov
|
8
|
+
class LogPatterns
|
9
|
+
class << self
|
10
|
+
attr_accessor :current_screen, :transition, :action, :check, :element
|
11
|
+
|
12
|
+
alias :set_current_screen :current_screen=
|
13
|
+
alias :set_transition :transition=
|
14
|
+
alias :set_action :action=
|
15
|
+
alias :set_check :check=
|
16
|
+
alias :set_element :element=
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
LogPatterns.current_screen = /Set ([^ ]+) as current screen/
|
21
|
+
LogPatterns.transition = /Transition ([^ ]+) from ([^ ]+) to ([^ ]+)/
|
22
|
+
LogPatterns.action = /Action '([^ ]+)' is done on screen ([^ ]+)/
|
23
|
+
LogPatterns.check = /Check '([^ ]+)' is done on screen ([^ ]+)/
|
24
|
+
LogPatterns.element = /(?:Click on| Type text .* in) '([^ ]+)' element/
|
25
|
+
|
26
|
+
class Gather < Command
|
27
|
+
DEFAULT_FILENAME = 'coverage.uic'
|
28
|
+
OPTIONS = {
|
29
|
+
'--coverage-file=FILE' => "File to store coverage info [default is '#{DEFAULT_FILENAME}']",
|
30
|
+
'--pattern-file=FILE' => 'Path to pattern file to override default patterns',
|
31
|
+
# '--no-transitions' => 'Do not gather transitions coverage',
|
32
|
+
# '--no-actions ' => 'Do not gather actions coverage',
|
33
|
+
# '--no-checks ' => 'Do not gather checks coverage',
|
34
|
+
# '--no-elements ' => 'Do not gather elements coverage'
|
35
|
+
}
|
36
|
+
USAGE_INFO = %Q^[options] file1.log [file2.log ... fileN.log]
|
37
|
+
\n\rWhere options are:
|
38
|
+
#{OPTIONS.inject([]){|a, e| a << "\r\t#{e[0]}\t- #{e[1]}"; a}.join("\n")}
|
39
|
+
^
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@coverage_file = DEFAULT_FILENAME
|
43
|
+
end
|
44
|
+
|
45
|
+
def do_job(args)
|
46
|
+
usage 'Missed log file', USAGE_INFO if args.empty?
|
47
|
+
@cd = CovData.new
|
48
|
+
log_files = process_args args
|
49
|
+
parse_logs log_files
|
50
|
+
@cd.set_processing_date
|
51
|
+
@cd.type = CoverageDataType::COVERAGE
|
52
|
+
@cd.save(@coverage_file)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def process_args(args)
|
57
|
+
coverage_file_option = args.grep(/--coverage-file=.*/)[0]
|
58
|
+
if coverage_file_option
|
59
|
+
@coverage_file = File.expand_path coverage_file_option.gsub(/.*=(.+)/, '\1')
|
60
|
+
args.delete_if { |e| e == coverage_file_option }
|
61
|
+
end
|
62
|
+
pattern_file_option = args.grep(/--pattern-file=.*/)[0]
|
63
|
+
if pattern_file_option
|
64
|
+
@pattern_file = File.expand_path pattern_file_option.gsub(/.*=(.+)/, '\1')
|
65
|
+
Log.fatal "File #{@pattern_file} does not exist" unless File.exist? @pattern_file
|
66
|
+
load @pattern_file
|
67
|
+
args.delete_if { |e| e == pattern_file_option }
|
68
|
+
end
|
69
|
+
return args
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_logs(log_files)
|
73
|
+
Log.debug "Will parse log files #{log_files}"
|
74
|
+
log_files.each { |lf| parse lf }
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse(log)
|
78
|
+
log_file = File.expand_path log
|
79
|
+
|
80
|
+
LogPatterns.instance_variables.each { |e| Log.debug "#{e}=#{LogPatterns.instance_variable_get e}" }
|
81
|
+
|
82
|
+
File.open(log_file) do |f|
|
83
|
+
begin
|
84
|
+
current_screen = $default_screen
|
85
|
+
expected_current_screen = nil
|
86
|
+
last_transition = nil
|
87
|
+
cur_screen_data = nil
|
88
|
+
while (line = f.readline.chomp)
|
89
|
+
case line
|
90
|
+
when LogPatterns.current_screen
|
91
|
+
name = $~[1] # $~ - is MatchData of the latest regexp match
|
92
|
+
current_screen = name
|
93
|
+
cur_screen_data = @cd.add_covered_screen name
|
94
|
+
|
95
|
+
when LogPatterns.transition
|
96
|
+
name, from, to = $~[1..3]
|
97
|
+
unless current_screen == from
|
98
|
+
Log.error %Q^
|
99
|
+
Transition #{name} is done from screen #{from} but current screen is #{current_screen}
|
100
|
+
Found in log #{log_file} at line #{f.lineno}
|
101
|
+
^
|
102
|
+
end
|
103
|
+
if cur_screen_data.nil?
|
104
|
+
Log.error %Q^
|
105
|
+
Wrong model: Transition #{name} is done from unknown screen.
|
106
|
+
Found in log #{log_file} at line #{f.lineno}
|
107
|
+
^
|
108
|
+
else
|
109
|
+
expected_current_screen = to
|
110
|
+
last_transition = name
|
111
|
+
cur_screen_data.add_covered_transition name, to
|
112
|
+
end
|
113
|
+
|
114
|
+
when LogPatterns.action
|
115
|
+
name, screen = $~[1..2]
|
116
|
+
unless current_screen == screen
|
117
|
+
Log.error %Q^
|
118
|
+
Action #{name} is done on screen #{screen} but current screen is #{current_screen}
|
119
|
+
Found in log #{log_file} at line #{f.lineno}
|
120
|
+
^
|
121
|
+
end
|
122
|
+
if cur_screen_data.nil?
|
123
|
+
Log.error %Q^
|
124
|
+
Wrong model: Action #{name} is done on unknown screen.
|
125
|
+
Found in log #{log_file} at line #{f.lineno}
|
126
|
+
^
|
127
|
+
else
|
128
|
+
cur_screen_data.add_covered_action name
|
129
|
+
end
|
130
|
+
|
131
|
+
when LogPatterns.check
|
132
|
+
name, screen = $~[1..2]
|
133
|
+
unless current_screen == screen
|
134
|
+
Log.error %Q^
|
135
|
+
Check #{name} is done on screen #{screen} but current screen is #{current_screen}
|
136
|
+
Found in log #{log_file} at line #{f.lineno}
|
137
|
+
^
|
138
|
+
end
|
139
|
+
if cur_screen_data.nil?
|
140
|
+
Log.error %Q^
|
141
|
+
Wrong model: Action #{name} is done on unknown screen.
|
142
|
+
Found in log #{log_file} at line #{f.lineno}
|
143
|
+
^
|
144
|
+
else
|
145
|
+
cur_screen_data.add_covered_check name
|
146
|
+
end
|
147
|
+
|
148
|
+
when LogPatterns.element
|
149
|
+
name = $~[1]
|
150
|
+
if cur_screen_data.nil?
|
151
|
+
Log.error %Q^
|
152
|
+
Wrong model: Action #{name} is done on unknown screen.
|
153
|
+
Found in log #{log_file} at line #{f.lineno}
|
154
|
+
^
|
155
|
+
else
|
156
|
+
cur_screen_data.add_covered_element name
|
157
|
+
end
|
158
|
+
|
159
|
+
else
|
160
|
+
# Log.debug "No match: '#{line}'"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
rescue EOFError => err
|
164
|
+
# it's ok
|
165
|
+
end
|
166
|
+
end
|
167
|
+
@cd.add_input_file log_file, File.mtime(log_file).strftime('%F %R:%S.%3N')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#=======
|
2
|
+
# Author: Alexey Lyanguzov (budabum@gmail.com)
|
3
|
+
#=======
|
4
|
+
|
5
|
+
module UICov
|
6
|
+
class ModelPatterns
|
7
|
+
class << self
|
8
|
+
attr_accessor :current_screen_start, :current_screen_end, :transition, :action, :check, :element
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
ModelPatterns.current_screen_start = /\s*class\s+([^ ]+)\{\s*/
|
13
|
+
ModelPatterns.current_screen_end = /\s*}\s*/
|
14
|
+
ModelPatterns.transition = /\s*Transition\s+([^ ]+)\s*\((\s*[^ ]+\s*)\)\s*/
|
15
|
+
ModelPatterns.action = /\s*Action\s+([^ ]+)\s*/
|
16
|
+
ModelPatterns.check = /\s*Check\s+([^ ]+)\s*/
|
17
|
+
ModelPatterns.element = /\s*Element\s+([^ ]+)\s*/
|
18
|
+
|
19
|
+
class Gentpl < Command
|
20
|
+
DEFAULT_FILENAME = 'template.uic'
|
21
|
+
OPTIONS = {
|
22
|
+
'--template-file=FILE' => "File to store coverage template [default is '#{DEFAULT_FILENAME}']",
|
23
|
+
# '--puml=DIR ' => 'Folder where Plant UML model files are',
|
24
|
+
# '--no-transitions' => 'Do not include transitions templates',
|
25
|
+
# '--no-actions ' => 'Do not include actions templates',
|
26
|
+
# '--no-checks ' => 'Do not include checks templates',
|
27
|
+
# '--no-elements ' => 'Do not include elements templates'
|
28
|
+
}
|
29
|
+
USAGE_INFO = %Q^[options] model-file1.puml [model-file2.puml ... model-fileN.puml]
|
30
|
+
\n\rWhere options are:
|
31
|
+
#{OPTIONS.inject([]){|a, e| a << "\r\t#{e[0]}\t- #{e[1]}"; a}.join("\n")}
|
32
|
+
^
|
33
|
+
# or
|
34
|
+
# \r\t#{COMMAND_PREFIX} [options] --puml=DIR
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@template_file = DEFAULT_FILENAME
|
38
|
+
end
|
39
|
+
|
40
|
+
def do_job(args)
|
41
|
+
@cd = CovData.new
|
42
|
+
model_files = process_args args
|
43
|
+
usage 'Missed model file', USAGE_INFO if model_files.empty?
|
44
|
+
parse_models model_files
|
45
|
+
@cd.set_processing_date
|
46
|
+
@cd.type = CoverageDataType::TEMPLATE
|
47
|
+
@cd.save(@template_file)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def process_args(args)
|
53
|
+
template_file_option = args.grep(/--template-file=.*/)[0]
|
54
|
+
if template_file_option
|
55
|
+
@template_file = File.expand_path template_file_option.gsub(/.*=(.+)/, '\1')
|
56
|
+
args.delete_if { |e| e == template_file_option }
|
57
|
+
end
|
58
|
+
return args
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_models(model_files)
|
62
|
+
Log.debug "Will parse model files #{model_files}"
|
63
|
+
model_files.each { |lf| parse lf }
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse(model)
|
67
|
+
model_file = File.expand_path model
|
68
|
+
File.open(model_file) do |f|
|
69
|
+
begin
|
70
|
+
current_screen = $default_screen
|
71
|
+
curr_screen_data = nil
|
72
|
+
while (line = f.readline.chomp)
|
73
|
+
case line
|
74
|
+
when ModelPatterns.current_screen_start
|
75
|
+
name = $~[1] # $~ - is MatchData of the latest regexp match
|
76
|
+
current_screen = name
|
77
|
+
cur_screen_data = @cd.add_screen name
|
78
|
+
|
79
|
+
when ModelPatterns.current_screen_end
|
80
|
+
current_screen = nil
|
81
|
+
|
82
|
+
when ModelPatterns.transition
|
83
|
+
name, to = $~[1..2]
|
84
|
+
if current_screen.nil?
|
85
|
+
Log.error %Q^
|
86
|
+
Wrong model: Transition #{name} is done from unknown screen.
|
87
|
+
Found in model #{model_file} at line #{f.lineno}
|
88
|
+
^
|
89
|
+
end
|
90
|
+
cur_screen_data.add_transition name, to
|
91
|
+
|
92
|
+
when ModelPatterns.action
|
93
|
+
name = $~[1]
|
94
|
+
if current_screen.nil?
|
95
|
+
Log.error %Q^
|
96
|
+
Wrong model: Action #{name} is done on unknown screen.
|
97
|
+
Found in model #{model_file} at line #{f.lineno}
|
98
|
+
^
|
99
|
+
end
|
100
|
+
cur_screen_data.add_action name
|
101
|
+
|
102
|
+
when ModelPatterns.check
|
103
|
+
name = $~[1]
|
104
|
+
if current_screen.nil?
|
105
|
+
Log.error %Q^
|
106
|
+
Wrong model: Action #{name} is done on unknown screen.
|
107
|
+
Found in model #{model_file} at line #{f.lineno}
|
108
|
+
^
|
109
|
+
end
|
110
|
+
cur_screen_data.add_check name
|
111
|
+
|
112
|
+
when ModelPatterns.element
|
113
|
+
name = $~[1]
|
114
|
+
cur_screen_data.add_element name
|
115
|
+
|
116
|
+
else
|
117
|
+
#d line
|
118
|
+
end
|
119
|
+
end
|
120
|
+
rescue EOFError => err
|
121
|
+
# it's ok
|
122
|
+
end
|
123
|
+
end
|
124
|
+
@cd.add_input_file model_file, File.mtime(model_file).strftime('%F %R:%S.%3N')
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|