specify_html_reporter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 686bb5892af39dd3816a22c1187e20336a66e93ec399519ebf45735f7f06959f
4
+ data.tar.gz: f131e7e4cf200f2c94b08c7ca86b131c6c6a1d322eaf9413c812fba2bc220360
5
+ SHA512:
6
+ metadata.gz: 2398bee6ecec1c4e673599ae99dd8d8fe2e56d1eb907e7da956f71fa5591300b7f9ec506550d1a2ab8721ffebb8aa47105ddf8fd2bee4f47fcf9ffa22d81bf66
7
+ data.tar.gz: c1e348cdf3ec823f20993ab1502dffb038c33ac1c7222437b097e64f3b445385430dc21c7227c9c9b32dd561b86085db4c0af269bbdd3693e1edb552e04d9dab
data/.gitignore ADDED
@@ -0,0 +1,49 @@
1
+ # Ruby Generated
2
+
3
+ /Gemfile.lock
4
+ /.bundle/
5
+ /.yardoc
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /spec/coverage/
12
+ /tmp/
13
+
14
+ # Generated Reports
15
+ reports/
16
+
17
+ # Rspec Failure Tracking
18
+
19
+ .rspec_status
20
+
21
+ # IDE Files
22
+
23
+ .idea/
24
+ *.iml
25
+ *.iws
26
+ *.ipr
27
+ .vscode/
28
+ .settings/
29
+ .metadata
30
+ .classpath
31
+ .loadpath
32
+ .buildpath
33
+ .project
34
+
35
+ # OS Files
36
+
37
+ .DS_Store
38
+ .DS_Store?
39
+ ._*
40
+ .Spotlight-V100
41
+ .Trashes
42
+ ehthumbs.db
43
+ Thumbs.db
44
+ $RECYCLE.BIN/
45
+ Desktop.ini
46
+ *.tmp
47
+ *.bak
48
+ *.swp
49
+ *~.nib
data/.hound.yml ADDED
@@ -0,0 +1,73 @@
1
+ AllCops:
2
+ Exclude:
3
+ - specify_html_reporter.gemspec
4
+ - spec/**/*
5
+
6
+ # Removing need for frozen string literal comment.
7
+ Style/FrozenStringLiteralComment:
8
+ Enabled: false
9
+
10
+ # Removing the preference for string single quotes.
11
+ Style/StringLiterals:
12
+ Enabled: false
13
+
14
+ # Missing top-level module documentation comment.
15
+ Style/Documentation:
16
+ Enabled: false
17
+
18
+ # Prefer reduce over inject.
19
+ Style/CollectionMethods:
20
+ PreferredMethods:
21
+ reduce: 'inject'
22
+
23
+ # Use each_with_object instead of inject.
24
+ Style/EachWithObject:
25
+ Enabled: false
26
+
27
+ # Prefer fail over raise.
28
+ Style/SignalException:
29
+ Enabled: false
30
+
31
+ # This never works for validations.
32
+ Layout/AlignHash:
33
+ EnforcedLastArgumentHashStyle: ignore_implicit
34
+
35
+ # Align multi-line params with previous line.
36
+ Layout/AlignParameters:
37
+ EnforcedStyle: with_fixed_indentation
38
+
39
+ # Indent `when` clause one step from `case`.
40
+ Layout/CaseIndentation:
41
+ IndentOneStep: true
42
+
43
+ # Don't force bad var names for reduce/inject loops.
44
+ Style/SingleLineBlockParams:
45
+ Enabled: false
46
+
47
+ # For method chains, keep the dot with the method name.
48
+ Layout/DotPosition:
49
+ EnforcedStyle: leading
50
+
51
+ # Stop nesting so hard.
52
+ Metrics/BlockNesting:
53
+ Max: 2
54
+
55
+ # Encourage short methods.
56
+ Metrics/MethodLength:
57
+ Max: 15
58
+
59
+ # Encourage short (as possible) modules.
60
+ Metrics/ModuleLength:
61
+ Max: 100
62
+
63
+ # Encourage fewer parameters.
64
+ Metrics/ParameterLists:
65
+ Max: 4
66
+
67
+ # Remove execute permissions check.
68
+ Lint/ScriptPermission:
69
+ Enabled: false
70
+
71
+ # Specify HTML Reporter Additions
72
+ Metrics/AbcSize:
73
+ Max: 18
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --format documentation
2
+ --format SpecifyHtmlReport
3
+ --color
4
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ inherit_mode:
2
+ merge:
3
+ - Exclude
4
+
5
+ inherit_from:
6
+ - .hound.yml
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+
6
+ rvm:
7
+ - 2.5.1
8
+
9
+ before_install: gem install bundler
10
+
11
+ branches:
12
+ only:
13
+ - master
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at jeff.nyman@yello.co. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "coveralls", require: false
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Jeff Nyman
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,87 @@
1
+ # Specify HTML Reporter
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/specify_html_reporter.svg)](http://badge.fury.io/rb/specify_html_reporter)
4
+ [![Build Status](https://travis-ci.org/jeffnyman/specify_html_reporter.svg)](https://travis-ci.org/jeffnyman/specify_html_reporter)
5
+ [![License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jeffnyman/specify_html_reporter/blob/master/LICENSE.md)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/3a112fb395c56c961d87/maintainability)](https://codeclimate.com/github/jeffnyman/specify_html_reporter/maintainability)
7
+
8
+ This gem provides a custom formatter for RSpec execution that generates an HTML-based repository of results files.
9
+
10
+ While this projet was designed to augment my [Specify](https://github.com/jeffnyman/specify) tool, it will generate reports for any RSpec execution.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'specify_html_reporter'
18
+ ```
19
+
20
+ To get the latest code:
21
+
22
+ ```ruby
23
+ gem 'specify_html_reporter', git: 'https://github.com/jeffnyman/specify_html_reporter'
24
+ ```
25
+
26
+ After doing one of the above, execute the following command:
27
+
28
+ ```
29
+ $ bundle
30
+ ```
31
+
32
+ You can also install Specify HTML Reporter just as you would any other gem:
33
+
34
+ ```
35
+ $ gem install specify_html_reporter
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ The usage is fairly simple and follows the standard pattern you would use for any RSpec formatter. Make sure to require the gem in your `spec_helper.rb` file:
41
+
42
+ ```ruby
43
+ require "specify_html_reporter"
44
+ ```
45
+
46
+ Then, in your `.rspec` file, make sure the following line is in place:
47
+
48
+ ```ruby
49
+ --format SpecifyHtmlReport
50
+ ```
51
+
52
+ If you aren't using an `.rspec` file, just provide `--format SpecifyHtmlReport` as part of your `rspec` execution command.
53
+
54
+ With the above being done, upon execution of your RSpec suite, you should get a directory called `reports` and within that you'll find an `overview.html` file that serves as the entry point for all reporting. Each spec file is given its own report format and is linked to from the overview file.
55
+
56
+ ## Development
57
+
58
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec:all` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
59
+
60
+ To experiment with the code, run `bin/console` for an interactive prompt. If you want to make changes and see how they work as a gem installed on your local machine, run `bundle exec rake install`.
61
+
62
+ The default `rake` command will run all tests as well as a Rubocop analysis.
63
+
64
+ If you have rights to deploy a new version, make sure to update the version number in `version.rb`, and then run `bundle exec rake release`. This will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
65
+
66
+ ## Contributing
67
+
68
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/jeffnyman/specify_html_reporter](https://github.com/jeffnyman/specify_html_reporter). The testing ecosystem of Ruby is very large and this project is intended to be a welcoming arena for collaboration on yet another test-supporting tool. As such, contributors are very much welcome but are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) which is provided as a [code of conduct](https://github.com/jeffnyman/specify_html_reporter/blob/master/CODE_OF_CONDUCT.md).
69
+
70
+ The Specify HTML Reporter gem follows [semantic versioning](http://semver.org).
71
+
72
+ To contribute to Specify HTML Reporter:
73
+
74
+ 1. [Fork the project](http://gun.io/blog/how-to-github-fork-branch-and-pull-request/).
75
+ 2. Create your feature branch. (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes. (`git commit -am 'new feature'`)
77
+ 4. Push the branch. (`git push origin my-new-feature`)
78
+ 5. Create a new [pull request](https://help.github.com/articles/using-pull-requests).
79
+
80
+ ## Author
81
+
82
+ * [Jeff Nyman](http://testerstories.com)
83
+
84
+ ## License
85
+
86
+ Specify HTML Reporter is distributed under the [MIT](http://www.opensource.org/licenses/MIT) license.
87
+ See the [LICENSE](https://github.com/jeffnyman/specify_html_reporter/blob/master/LICENSE.md) file for details.
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rdoc/task"
5
+ require "rubocop/rake_task"
6
+ require "rspec/core/rake_task"
7
+
8
+ RuboCop::RakeTask.new
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+ namespace :spec do
13
+ desc 'Clean all generated reports'
14
+ task :clean do
15
+ system('rm -rf spec/reports')
16
+ system('rm -rf spec/coverage')
17
+ end
18
+
19
+ RSpec::Core::RakeTask.new(all: :clean) do |config|
20
+ options = %w[--color]
21
+ options += %w[--format documentation]
22
+ options += %w[--format SpecifyHtmlReport]
23
+ options += %w[--format html --out spec/reports/test-report.html]
24
+
25
+ config.rspec_opts = options
26
+ end
27
+ end
28
+
29
+ Rake::RDocTask.new do |rdoc|
30
+ rdoc.rdoc_dir = 'doc'
31
+ rdoc.main = 'README.md'
32
+ rdoc.title = "Specify HTML Reporter #{SpecifyHtmlReporter::VERSION}"
33
+ rdoc.rdoc_files.include('README*', 'lib/**/*.rb')
34
+ end
35
+
36
+ task default: ['spec:all', :rubocop]
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "specify_html_reporter"
5
+
6
+ require "pry"
7
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,120 @@
1
+ require "rouge"
2
+ require "active_support"
3
+ require "active_support/core_ext/numeric"
4
+
5
+ require "specify_html_reporter/problem"
6
+
7
+ class Example
8
+ attr_reader :duration, :status, :run_time, :exception, :file_path,
9
+ :metadata, :spec, :screen_grab, :video_record
10
+
11
+ def initialize(example)
12
+ @spec = nil
13
+ @example = example
14
+ setup_execution_result
15
+ setup_example_data
16
+ setup_metadata
17
+ setup_exception
18
+ end
19
+
20
+ def result_type(prefix = 'label-')
21
+ class_map = {
22
+ passed: "#{prefix}success",
23
+ failed: "#{prefix}danger",
24
+ pending: "#{prefix}warning"
25
+ }
26
+
27
+ class_map[@status.to_sym]
28
+ end
29
+
30
+ def example_title
31
+ full_title = @example_group.to_s.split('::') - %w[RSpec ExampleGroups]
32
+ full_title.push @description
33
+ full_title.join(' → ')
34
+ end
35
+
36
+ def exception?
37
+ !@exception.problem.nil?
38
+ end
39
+
40
+ def spec?
41
+ !@spec.nil?
42
+ end
43
+
44
+ def screen_grab?
45
+ !@screen_grab.nil? && !@screen_grab.empty?
46
+ end
47
+
48
+ def video_record?
49
+ !@video_record.nil?
50
+ end
51
+
52
+ def comment
53
+ ERB::Util.html_escape(@comment)
54
+ end
55
+
56
+ def comment?
57
+ !@comment.nil?
58
+ end
59
+
60
+ def create_spec_line(spec_text)
61
+ formatter = Rouge::Formatters::HTML.new(css_class: 'highlight')
62
+ lexer = Rouge::Lexers::Gherkin.new
63
+ @spec = formatter.format(lexer.lex(spec_text.gsub('#->', '')))
64
+ end
65
+
66
+ def self.load_spec_comments!(examples)
67
+ examples.group_by(&:file_path).each do |file_path, file_examples|
68
+ lines = File.readlines(file_path)
69
+
70
+ file_examples.zip(file_examples.rotate).each do |example, next_ex|
71
+ determine_lexical_next(example, next_ex)
72
+ process_spec_lines(example, next_ex, lines)
73
+ end
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ class << self
80
+ private
81
+
82
+ def determine_lexical_next(example, next_ex)
83
+ @lexical = next_ex &&
84
+ next_ex.file_path == example.file_path &&
85
+ next_ex.metadata[:line_number] > example.metadata[:line_number]
86
+ end
87
+
88
+ def process_spec_lines(example, next_ex, lines)
89
+ start_line = example.metadata[:line_number] - 1
90
+ next_start = (@lexical ? next_ex.metadata[:line_number] : lines.size) - 1
91
+ spec_lines = lines[start_line...next_start].select { |l| l.match(/#->/) }
92
+ example.create_spec_line(spec_lines.join) unless spec_lines.empty?
93
+ end
94
+ end
95
+
96
+ def setup_execution_result
97
+ @execution_result = @example.execution_result
98
+ @run_time = @execution_result.run_time.round(5)
99
+ @status = @execution_result.status.to_s
100
+ @duration = @execution_result.run_time.to_s(:rounded, precision: 5)
101
+ end
102
+
103
+ def setup_example_data
104
+ @example_group = @example.example_group.to_s
105
+ @description = @example.description
106
+ @full_description = @example.full_description
107
+ @metadata = @example.metadata
108
+ end
109
+
110
+ def setup_metadata
111
+ @file_path = @metadata[:file_path]
112
+ @comment = @metadata[:comment]
113
+ @screen_grab = @metadata[:screen_grab]
114
+ @video_record = @metadata[:video_record]
115
+ end
116
+
117
+ def setup_exception
118
+ @exception = Problem.new(@example, @file_path)
119
+ end
120
+ end
@@ -0,0 +1,93 @@
1
+ require "rouge"
2
+ require "rbconfig"
3
+
4
+ class Problem
5
+ attr_reader :problem, :explanation, :backtrace_message, :highlighted_source
6
+
7
+ def initialize(example, file_path)
8
+ @example = example
9
+ @file_path = file_path
10
+ @exception = @example.exception
11
+
12
+ return if @exception.nil?
13
+
14
+ @problem = @exception.class
15
+ @message = @exception.message.encode("utf-8")
16
+ @backtrace_message = format_backtrace
17
+ @highlighted_source = format_source
18
+ @explanation = format_message
19
+ end
20
+
21
+ def format_message
22
+ formatter = Rouge::Formatters::HTML.new(css_class: 'highlight')
23
+ lexer = Rouge::Lexers::Ruby.new
24
+ formatter.format(lexer.lex(@message))
25
+ end
26
+
27
+ def format_backtrace
28
+ formatted_backtrace(@example, @exception).map do |entry|
29
+ ERB::Util.html_escape(entry)
30
+ end
31
+ end
32
+
33
+ def formatted_backtrace(example, exception)
34
+ # This logic is in place to avoid an error in the format_backtrace method
35
+ # for the RSpec formatter. RSpec versions below 3.5 will throw an exception.
36
+ return [] unless example
37
+
38
+ formatter = RSpec.configuration.backtrace_formatter
39
+ formatter.format_backtrace(exception.backtrace, example.metadata)
40
+ end
41
+
42
+ def format_source
43
+ return '' if @backtrace_message.empty?
44
+
45
+ data = @backtrace_message.first.split(':')
46
+
47
+ return if data.empty?
48
+
49
+ if os == :windows
50
+ file_path = data[0] + ':' + data[1]
51
+ line_number = data[2].to_i
52
+ else
53
+ file_path = data.first
54
+ line_number = data[1].to_i
55
+ end
56
+
57
+ format_source_context(file_path, line_number)
58
+ end
59
+
60
+ def format_source_context(file_path, line_number)
61
+ lines = File.readlines(file_path)
62
+ start_line = line_number - 2
63
+ end_line = line_number + 3
64
+
65
+ source = lines[start_line..end_line].join("")
66
+
67
+ formatter = Rouge::Formatters::HTML.new(
68
+ css_class: 'highlight', line_numbers: true, start_line: start_line + 1
69
+ )
70
+
71
+ lexer = Rouge::Lexers::Ruby.new
72
+ formatter.format(lexer.lex(source.encode('utf-8')))
73
+ end
74
+
75
+ def os
76
+ @os ||= begin
77
+ host_os = RbConfig::CONFIG['host_os']
78
+
79
+ case host_os
80
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
81
+ :windows
82
+ when /darwin|mac os/
83
+ :macosx
84
+ when /linux/
85
+ :linux
86
+ when /solaris|bsd/
87
+ :unix
88
+ else
89
+ raise Exception, "Unknown operating system: #{host_os.inspect}"
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,3 @@
1
+ module SpecifyHtmlReporter
2
+ VERSION = "0.1.0".freeze
3
+ end