golden_rose 0.1.0
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 +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/DEVELOPMENT.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +65 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exe/golden_rose +5 -0
- data/golden_rose.gemspec +32 -0
- data/lib/golden_rose.rb +29 -0
- data/lib/golden_rose/child_item.rb +43 -0
- data/lib/golden_rose/cli/app.rb +20 -0
- data/lib/golden_rose/execution_details.rb +57 -0
- data/lib/golden_rose/generators/html_format.rb +26 -0
- data/lib/golden_rose/parent_item.rb +31 -0
- data/lib/golden_rose/parser.rb +58 -0
- data/lib/golden_rose/results_filterer.rb +67 -0
- data/lib/golden_rose/subtest_item.rb +17 -0
- data/lib/golden_rose/templates/index.haml +123 -0
- data/lib/golden_rose/version.rb +3 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 760134cb39e5e84e51797d064d8fc4b3d0e772c6
|
4
|
+
data.tar.gz: 8c7386d6714e8070b30dc08d171dc4b8ed0fecf0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7911d91360192b462d5bb6fb84caa94ec511325279cdea31b8510a4a0bc7a84ed0b155ccec786a567edf97be6c06100d10c39920d13b470efd1f91a9a57805bb
|
7
|
+
data.tar.gz: 14035a0968b6809fad19fd6845227cae7407cc46cf6f281144590f75afd813247ae0141ca8133e0201f31a8023150afe6da9092a7217a2ddd6dad3ee51794065
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
# Development
|
2
|
+
|
3
|
+
Run `bundle exec rake install` to install this gem onto your local machine. To release a new version, update the version number in `version.rb`, then run `bundle exec rake release`, which will create a git tag for the version, next push git commits and tags, and as the last step push the `.gem` file to [rubygems.org](https://rubygems.org).
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 PGS Software
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# GoldenRose
|
2
|
+
|
3
|
+
[](https://github.com/PGSSoft/GoldenRose/blob/master/LICENSE)
|
4
|
+
|
5
|
+
A tool for generating reports from Xcode results bundle.
|
6
|
+
|
7
|
+
<!-- One screenshot -->
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
```bash
|
12
|
+
sudo gem install golden_rose
|
13
|
+
```
|
14
|
+
|
15
|
+
## Quick start
|
16
|
+
|
17
|
+
GoldenRose creates UI Automation tests report from "results" bundle created by the Xcode during execution.
|
18
|
+
|
19
|
+
- Run UI Tests and save results bundle using `-resultBundlePath`:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
xcodebuild -workspace MyProject.xcworkspace \
|
23
|
+
-scheme MyApp \
|
24
|
+
-destination 'platform=iOS Simulator,name=iPad Air 2,OS=9.2' \
|
25
|
+
-resultBundlePath 'MyApp.test_result' test
|
26
|
+
```
|
27
|
+
|
28
|
+
- Generate reports with GoldenRose:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
golden_rose generate MyApp.test_result
|
32
|
+
```
|
33
|
+
|
34
|
+
The tool will generate a report in html format in the current directory.
|
35
|
+
|
36
|
+
## Features
|
37
|
+
|
38
|
+
- [x] UI Automation tests
|
39
|
+
- [x] Reading from ZIP files
|
40
|
+
- [ ] Unit tests reports
|
41
|
+
- [ ] Build logs
|
42
|
+
- [ ] Code coverage
|
43
|
+
- [ ] Fastlane integration
|
44
|
+
- [ ] JUnit reports
|
45
|
+
- [ ] And more
|
46
|
+
|
47
|
+
## Development
|
48
|
+
|
49
|
+
After checking out the repo, run `./bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` to start an interactive prompt that, which will enable you to experiment.
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/PGSSoft/GoldenRose](https://github.com/PGSSoft/GoldenRose).
|
54
|
+
|
55
|
+
|
56
|
+
## License
|
57
|
+
|
58
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
59
|
+
|
60
|
+
## About
|
61
|
+
The project maintained by [software development agency](https://pgs-soft.com) [PGS Software](https://pgs-soft.com).
|
62
|
+
See our other [open-source projects](https://github.com/PGSSoft) or [contact us](https://www.pgs-soft.com/contact-us/) to develop your product.
|
63
|
+
|
64
|
+
[](https://github.com/PGSSoft/GoldenRose)
|
65
|
+
[](https://twitter.com/pgssoftware)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "golden_rose"
|
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/exe/golden_rose
ADDED
data/golden_rose.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 'golden_rose/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "golden_rose"
|
8
|
+
spec.version = GoldenRose::VERSION
|
9
|
+
spec.authors = ["Róża Szylar (PGS Software)"]
|
10
|
+
spec.email = ["rszylar@pgs-soft.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A tool for generating reports from Xcode results bundle.}
|
13
|
+
spec.description = %q{A tool for generating reports from Xcode results bundle.
|
14
|
+
Analyze results bundle directory created by Xcode during building, testing, running and generates HTML report with results.}
|
15
|
+
spec.homepage = "https://github.com/PGSSoft/golden_rose"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = ["golden_rose"]
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "haml"
|
24
|
+
spec.add_dependency "plist"
|
25
|
+
spec.add_dependency "rubyzip"
|
26
|
+
spec.add_dependency "thor"
|
27
|
+
spec.add_dependency "tilt"
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec"
|
32
|
+
end
|
data/lib/golden_rose.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "golden_rose/version"
|
2
|
+
require "golden_rose/subtest_item"
|
3
|
+
require "golden_rose/parent_item"
|
4
|
+
require "golden_rose/child_item"
|
5
|
+
require "golden_rose/parser"
|
6
|
+
require "golden_rose/execution_details"
|
7
|
+
require "golden_rose/results_filterer"
|
8
|
+
require "golden_rose/generators/html_format"
|
9
|
+
require "golden_rose/cli/app"
|
10
|
+
|
11
|
+
module GoldenRose
|
12
|
+
def self.generate(folder_path, output_path, format: :html)
|
13
|
+
parsed_plist = Parser.new(folder_path).parse!
|
14
|
+
results = ResultsFilterer.new(parsed_plist).filter!
|
15
|
+
|
16
|
+
case format
|
17
|
+
when :html
|
18
|
+
Generators::HtmlFormat.new(results, output_path).output
|
19
|
+
else
|
20
|
+
raise GeneratingError, "Format not supported."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.root
|
25
|
+
File.dirname(__dir__)
|
26
|
+
end
|
27
|
+
|
28
|
+
class GeneratingError < StandardError; end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Used for setting single subtest details
|
2
|
+
# It represents last level of tests
|
3
|
+
|
4
|
+
module GoldenRose
|
5
|
+
class ChildItem < SubtestItem
|
6
|
+
attr_reader :status, :time, :failures
|
7
|
+
|
8
|
+
def initialize(source_subtest)
|
9
|
+
@status = source_subtest["TestStatus"].downcase
|
10
|
+
set_time(source_subtest)
|
11
|
+
set_failures(source_subtest)
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def set_time(source_subtest)
|
19
|
+
last_time = source_subtest["ActivitySummaries"].last["FinishTimeInterval"]
|
20
|
+
first_time = source_subtest["ActivitySummaries"].first["StartTimeInterval"]
|
21
|
+
|
22
|
+
return unless last_time && first_time
|
23
|
+
|
24
|
+
counted_time = last_time - first_time
|
25
|
+
@time = "#{counted_time.round(2)}s"
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_failures(source_subtest)
|
29
|
+
return unless source_subtest["FailureSummaries"]
|
30
|
+
@failures = source_subtest["FailureSummaries"].map do |failure|
|
31
|
+
{
|
32
|
+
message: failure["Message"],
|
33
|
+
file_name: failure["FileName"],
|
34
|
+
line_number: failure["LineNumber"]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def hashable_attributes
|
40
|
+
%i(name status time failures)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
module GoldenRose
|
4
|
+
module CLI
|
5
|
+
class App < Thor
|
6
|
+
desc "generate <path_to_folder_or_zip>", "Generate report from a folder"
|
7
|
+
method_option :output, type: :string, aliases: "-o"
|
8
|
+
|
9
|
+
def generate(folder_path)
|
10
|
+
say("Started formatting report...")
|
11
|
+
GoldenRose::generate(folder_path, options[:output])
|
12
|
+
say("Report generated in #{options[:output] || Dir.pwd}/index.html", :green)
|
13
|
+
rescue GoldenRose::GeneratingError => e
|
14
|
+
say(e.message, :yellow)
|
15
|
+
rescue StandardError => e
|
16
|
+
say("Error during running generator.", :red)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module GoldenRose
|
2
|
+
class ExecutionDetails
|
3
|
+
def initialize(parsed_plist, items)
|
4
|
+
@parsed_plist = parsed_plist
|
5
|
+
@items = items
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
@parsed_plist["TestableSummaries"].first['TestName']
|
10
|
+
end
|
11
|
+
|
12
|
+
def formatted_time
|
13
|
+
hours = total_time / (60 * 60)
|
14
|
+
minutes = (total_time / 60) % 60
|
15
|
+
seconds = total_time % 60
|
16
|
+
|
17
|
+
"".tap do |time|
|
18
|
+
time << "#{pluralized(hours, 'hour')}, " if hours > 0
|
19
|
+
time << "#{pluralized(minutes, 'minute')} and " if minutes > 0
|
20
|
+
time << "#{pluralized(seconds, 'second')}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def failures_count
|
25
|
+
@items.reduce(0) { |count, item| count + item[:failures_count].to_i }
|
26
|
+
end
|
27
|
+
|
28
|
+
def total_tests_count
|
29
|
+
@items.reduce(0) { |count, item| count + item[:subtests].count }
|
30
|
+
end
|
31
|
+
|
32
|
+
def passing_count
|
33
|
+
total_tests_count - failures_count
|
34
|
+
end
|
35
|
+
|
36
|
+
def model_name
|
37
|
+
@parsed_plist["RunDestination"]["TargetDevice"]["ModelName"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def os_version
|
41
|
+
@parsed_plist["RunDestination"]["TargetDevice"]["OperatingSystemVersion"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def total_time
|
45
|
+
@items.reduce(0) do |time, item|
|
46
|
+
subtests_time = item[:subtests].reduce(0) do |time, item|
|
47
|
+
time + item[:time].to_f
|
48
|
+
end
|
49
|
+
time + subtests_time
|
50
|
+
end.round
|
51
|
+
end
|
52
|
+
|
53
|
+
def pluralized(number, noun)
|
54
|
+
"#{number} #{noun}#{'s' if number != 1}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Generating html file from results using haml
|
2
|
+
|
3
|
+
require "haml"
|
4
|
+
require "tilt/haml"
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
module GoldenRose
|
8
|
+
module Generators
|
9
|
+
class HtmlFormat
|
10
|
+
def initialize(results, output_path = nil)
|
11
|
+
@details = results.details
|
12
|
+
@items = results.items
|
13
|
+
@output_path = output_path || ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def output
|
17
|
+
file_path = Pathname(@output_path) + "index.html"
|
18
|
+
file = File.new(file_path, "w+")
|
19
|
+
template_path = File.join(GoldenRose::root, "/lib/golden_rose/templates/index.haml")
|
20
|
+
template = Tilt::HamlTemplate.new(template_path)
|
21
|
+
file.puts template.render(self)
|
22
|
+
file.close
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Used for setting single subtest details
|
2
|
+
# It contains collection of child subtests
|
3
|
+
|
4
|
+
module GoldenRose
|
5
|
+
class ParentItem < SubtestItem
|
6
|
+
attr_accessor :subtests
|
7
|
+
|
8
|
+
# Used in html generator
|
9
|
+
def node_id
|
10
|
+
@node_id ||= "node_#{object_id}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def failures_count
|
14
|
+
@failures_count ||= failed_subtests? ? failed_subtests.size : nil
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def failed_subtests
|
20
|
+
subtests.select { |subtest| subtest[:status] == "failure" }
|
21
|
+
end
|
22
|
+
|
23
|
+
def failed_subtests?
|
24
|
+
failed_subtests.size > 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def hashable_attributes
|
28
|
+
%i(subtests name failures_count node_id)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# This class is responsible for parsing plist
|
2
|
+
# from zip file or folder
|
3
|
+
|
4
|
+
require "plist"
|
5
|
+
require "zip"
|
6
|
+
require "securerandom"
|
7
|
+
|
8
|
+
module GoldenRose
|
9
|
+
class Parser
|
10
|
+
FILE_NAME = "action_TestSummaries.plist"
|
11
|
+
|
12
|
+
attr_accessor :parsed_plist, :folder_path
|
13
|
+
|
14
|
+
def initialize(folder_path)
|
15
|
+
@folder_path = folder_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse!
|
19
|
+
archive? ? open_zip : open_directory
|
20
|
+
raise GeneratingError, "File 'TestSummaries.plist' was not found in the folder." unless @plist_file_path
|
21
|
+
@parsed_plist = Plist::parse_xml(@plist_file_path)
|
22
|
+
File.delete(@plist_file_path) if archive?
|
23
|
+
raise GeneratingError, "Could not parse plist correctly." unless parsed_plist
|
24
|
+
parsed_plist
|
25
|
+
|
26
|
+
rescue Zip::Error, Errno::ENOENT
|
27
|
+
raise GeneratingError, "Could not open the folder."
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def open_directory
|
33
|
+
@plist_file_path = Dir.glob("#{folder_path}/**/#{FILE_NAME}").first
|
34
|
+
end
|
35
|
+
|
36
|
+
def open_zip
|
37
|
+
Zip::File.open(folder_path) do |zip_file|
|
38
|
+
entry = zip_file.find do |entry|
|
39
|
+
file_name = File.basename(entry.name)
|
40
|
+
test_summaries?(file_name)
|
41
|
+
end
|
42
|
+
if entry
|
43
|
+
uuid = ::SecureRandom.uuid
|
44
|
+
@plist_file_path = File.join(GoldenRose::root, "/source_#{uuid}.plist")
|
45
|
+
entry.extract(@plist_file_path)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_summaries?(file_name)
|
51
|
+
file_name == FILE_NAME
|
52
|
+
end
|
53
|
+
|
54
|
+
def archive?
|
55
|
+
!(folder_path =~ /\.(?:rar|zip|tar.gz)$/).nil?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# This class is responsible for filtering results
|
2
|
+
# to include only subtests with needed details
|
3
|
+
|
4
|
+
module GoldenRose
|
5
|
+
class ResultsFilterer
|
6
|
+
attr_accessor :parsed_plist, :results
|
7
|
+
|
8
|
+
def initialize(parsed_plist)
|
9
|
+
@parsed_plist = parsed_plist
|
10
|
+
end
|
11
|
+
|
12
|
+
def filter!
|
13
|
+
raise GeneratingError, "Testable summaries not present." unless testable_summaries
|
14
|
+
raise GeneratingError, "Tests not present." unless tests
|
15
|
+
@results = Results.new(execution_details, items)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def iterate_subtests(items)
|
21
|
+
items.map do |subtest|
|
22
|
+
child_subtests = subtest["Subtests"]
|
23
|
+
next if child_subtests && child_subtests.empty?
|
24
|
+
|
25
|
+
if child_subtests
|
26
|
+
ParentItem.new(subtest).tap do |item|
|
27
|
+
item.subtests = iterate_subtests(child_subtests)
|
28
|
+
end.to_h
|
29
|
+
else
|
30
|
+
ChildItem.new(subtest).to_h
|
31
|
+
end
|
32
|
+
end.compact
|
33
|
+
end
|
34
|
+
|
35
|
+
def items
|
36
|
+
@items ||= compact_results(iterate_subtests(tests))
|
37
|
+
end
|
38
|
+
|
39
|
+
# This method simplify results structure,
|
40
|
+
# it sets only one level of nesting
|
41
|
+
# by leaving parents only with collection as child
|
42
|
+
def compact_results(items)
|
43
|
+
items.map do |subtest|
|
44
|
+
subtests = subtest[:subtests]
|
45
|
+
if subtests.size > 1
|
46
|
+
subtests
|
47
|
+
elsif subtests.size == 1
|
48
|
+
compact_results(subtests)
|
49
|
+
end
|
50
|
+
end.flatten.compact
|
51
|
+
end
|
52
|
+
|
53
|
+
def execution_details
|
54
|
+
ExecutionDetails.new(parsed_plist, items)
|
55
|
+
end
|
56
|
+
|
57
|
+
def testable_summaries
|
58
|
+
parsed_plist['TestableSummaries']
|
59
|
+
end
|
60
|
+
|
61
|
+
def tests
|
62
|
+
testable_summaries.first['Tests']
|
63
|
+
end
|
64
|
+
|
65
|
+
class Results < Struct.new(:details, :items); end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Used for setting single subtest details
|
2
|
+
|
3
|
+
module GoldenRose
|
4
|
+
class SubtestItem
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(source_subtest)
|
8
|
+
@name = source_subtest["TestName"]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_h
|
12
|
+
hashable_attributes.each_with_object({}) do |field, hash|
|
13
|
+
hash[field] = public_send(field) if public_send(field)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{:charset => "UTF-8"}
|
5
|
+
%title= @details.name
|
6
|
+
%link{:href => "https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600&subset=latin,latin-ext", :rel => "stylesheet", :type => "text/css"}
|
7
|
+
:css
|
8
|
+
body { font-family: 'Source Sans Pro', sans-serif; }
|
9
|
+
#container { max-width: 1170px; margin: auto;}
|
10
|
+
h1 {
|
11
|
+
color: #ff7726;
|
12
|
+
font-size: 48px;
|
13
|
+
font-weight: 600;
|
14
|
+
line-height: 18px;
|
15
|
+
text-align: left;
|
16
|
+
margin: 73px 0 24px 0;
|
17
|
+
}
|
18
|
+
#details {
|
19
|
+
color: #4e4e4e;
|
20
|
+
margin: 0 0 60px 0;
|
21
|
+
font-size: 18px;
|
22
|
+
line-height: 18px;
|
23
|
+
}
|
24
|
+
#results { margin-right: 34px; }
|
25
|
+
input[type=checkbox], input[type=checkbox] + ol > li { display: none; }
|
26
|
+
input[type=checkbox]:checked + ol > li { display: block; }
|
27
|
+
ol, li { position: relative; }
|
28
|
+
ol { margin: 0; padding: 0 0 0 34px; }
|
29
|
+
ol#collapsible { padding: 0; }
|
30
|
+
ol::before {
|
31
|
+
content: "▶";
|
32
|
+
position: absolute;
|
33
|
+
top: -33px; left: 15px;
|
34
|
+
font-size: 10px;
|
35
|
+
color: #ff7726;
|
36
|
+
}
|
37
|
+
ol#collapsible::before { display: none; }
|
38
|
+
input[type=checkbox]:checked + ol::before { content: "▼"; }
|
39
|
+
li { list-style: none; }
|
40
|
+
label { cursor: pointer; }
|
41
|
+
label, .success, .failure {
|
42
|
+
padding: 13.5px 0 13.5px 34px;
|
43
|
+
width: 100%;
|
44
|
+
display: block;
|
45
|
+
background: #f6f6f6;
|
46
|
+
border-bottom: 3px #fff solid;
|
47
|
+
color: #4e4e4e;
|
48
|
+
letter-spacing: -0.32px;
|
49
|
+
line-height: 18px;
|
50
|
+
}
|
51
|
+
.time, .failures-count {
|
52
|
+
float: right;
|
53
|
+
width: 90px;
|
54
|
+
}
|
55
|
+
.failures-count { color: #a80000; }
|
56
|
+
.success {
|
57
|
+
background: #ccffcc;
|
58
|
+
color: #005e37;
|
59
|
+
padding: 8.5px 0 8.5px 34px;
|
60
|
+
font-weight: 400;
|
61
|
+
}
|
62
|
+
.failure {
|
63
|
+
background: #ffcfcf;
|
64
|
+
color: #a80000;
|
65
|
+
}
|
66
|
+
.failure-message, .failure-details {
|
67
|
+
clear: both;
|
68
|
+
display: block;
|
69
|
+
font-size: 14px;
|
70
|
+
letter-spacing: -0.28px;
|
71
|
+
margin-right: 34px;
|
72
|
+
}
|
73
|
+
#footer {
|
74
|
+
color: #4e4e4e;
|
75
|
+
font-size: 14px;
|
76
|
+
margin-top: 40px;
|
77
|
+
}
|
78
|
+
.heart { color: #ff7726 }
|
79
|
+
#footer a { color: #ff7726; text-decoration: none }
|
80
|
+
%body
|
81
|
+
#container
|
82
|
+
%h1
|
83
|
+
= @details.name
|
84
|
+
#details
|
85
|
+
#{@details.total_tests_count} tests run on
|
86
|
+
%strong
|
87
|
+
#{@details.model_name} iOS #{@details.os_version}
|
88
|
+
with
|
89
|
+
%strong
|
90
|
+
#{@details.passing_count} passing
|
91
|
+
and
|
92
|
+
%strong
|
93
|
+
#{@details.failures_count} failing
|
94
|
+
in #{@details.formatted_time}
|
95
|
+
#results
|
96
|
+
%ol#collapsible
|
97
|
+
- @items.each do |item|
|
98
|
+
%li
|
99
|
+
%label(for="#{item[:node_id]}")
|
100
|
+
= item[:name]
|
101
|
+
- if item[:failures_count]
|
102
|
+
%span.failures-count
|
103
|
+
= "Failures: "
|
104
|
+
= item[:failures_count]
|
105
|
+
%input(type="checkbox" id="#{item[:node_id]}")
|
106
|
+
%ol
|
107
|
+
- item[:subtests].each do |subtest|
|
108
|
+
%li
|
109
|
+
%span(class="#{subtest[:status]}")
|
110
|
+
= subtest[:name]
|
111
|
+
%span.time
|
112
|
+
= subtest[:time]
|
113
|
+
- if subtest[:failures]
|
114
|
+
- subtest[:failures].each do |failure|
|
115
|
+
.failure-message
|
116
|
+
= failure[:message]
|
117
|
+
.failure-details
|
118
|
+
#{failure[:file_name]}:#{failure[:line_number]}
|
119
|
+
#footer
|
120
|
+
Made with
|
121
|
+
%span.heart ❤
|
122
|
+
by
|
123
|
+
%a(title="PGS Software" href="https://pgs-soft.com")PGS Software
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: golden_rose
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Róża Szylar (PGS Software)
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: haml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: plist
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubyzip
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: tilt
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.10'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '10.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: |-
|
126
|
+
A tool for generating reports from Xcode results bundle.
|
127
|
+
Analyze results bundle directory created by Xcode during building, testing, running and generates HTML report with results.
|
128
|
+
email:
|
129
|
+
- rszylar@pgs-soft.com
|
130
|
+
executables:
|
131
|
+
- golden_rose
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- ".gitignore"
|
136
|
+
- ".rspec"
|
137
|
+
- ".travis.yml"
|
138
|
+
- DEVELOPMENT.md
|
139
|
+
- Gemfile
|
140
|
+
- LICENSE.txt
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- bin/console
|
144
|
+
- bin/setup
|
145
|
+
- exe/golden_rose
|
146
|
+
- golden_rose.gemspec
|
147
|
+
- lib/golden_rose.rb
|
148
|
+
- lib/golden_rose/child_item.rb
|
149
|
+
- lib/golden_rose/cli/app.rb
|
150
|
+
- lib/golden_rose/execution_details.rb
|
151
|
+
- lib/golden_rose/generators/html_format.rb
|
152
|
+
- lib/golden_rose/parent_item.rb
|
153
|
+
- lib/golden_rose/parser.rb
|
154
|
+
- lib/golden_rose/results_filterer.rb
|
155
|
+
- lib/golden_rose/subtest_item.rb
|
156
|
+
- lib/golden_rose/templates/index.haml
|
157
|
+
- lib/golden_rose/version.rb
|
158
|
+
homepage: https://github.com/PGSSoft/golden_rose
|
159
|
+
licenses:
|
160
|
+
- MIT
|
161
|
+
metadata: {}
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
require_paths:
|
165
|
+
- lib
|
166
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
requirements: []
|
177
|
+
rubyforge_project:
|
178
|
+
rubygems_version: 2.4.5.1
|
179
|
+
signing_key:
|
180
|
+
specification_version: 4
|
181
|
+
summary: A tool for generating reports from Xcode results bundle.
|
182
|
+
test_files: []
|