captureful_formatter 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +5 -0
- data/lib/captureful_formatter.rb +4 -0
- data/lib/captureful_formatter/formatter.rb +24 -25
- data/lib/captureful_formatter/printer.rb +3 -3
- data/lib/captureful_formatter/structures.rb +71 -0
- data/lib/captureful_formatter/version.rb +1 -1
- data/sample.png +0 -0
- data/spec/captureful_formatter/formatter_spec.rb +2 -0
- data/templates/test_report.html.erb +71 -39
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad0d60a1d2e31c32f13ef5818453e0b1f6132339
|
4
|
+
data.tar.gz: 7101c556ec29a301315d734f2386a2416eb71129
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 825b0041593dce90b6a20eea8da9a9471dadd904a658ea0c8183e3a3faf11b2f8301355ba290f3c1aaa94165c7b343ec226c0517f26f798e526290c0b92c27fd
|
7
|
+
data.tar.gz: 49f2d534da1914cd3ef48e1798d5a63ca6d296548a834798e0436379799b23acd64d58383fc2ba54a6f15051ee2e3c119897592d3d938bdd7fbff4c6421c69de
|
data/README.md
CHANGED
@@ -29,10 +29,15 @@ Run this command.
|
|
29
29
|
|
30
30
|
$ rspec
|
31
31
|
|
32
|
+
## Sample
|
33
|
+
|
34
|
+

|
35
|
+
|
32
36
|
## Configuration
|
33
37
|
|
34
38
|
```ruby
|
35
39
|
CapturefulFormatter.configure do |config|
|
40
|
+
c.project_name = "Your Project" # Title of test report
|
36
41
|
c.output_directory = "./.captureful_formatter" # The path to where the test report is saved.
|
37
42
|
c.template_path = "path/to/template" # your custom template file path.
|
38
43
|
end
|
data/lib/captureful_formatter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'captureful_formatter/formatter'
|
2
2
|
require 'captureful_formatter/notifications'
|
3
3
|
require 'captureful_formatter/printer'
|
4
|
+
require 'captureful_formatter/structures'
|
4
5
|
require 'captureful_formatter/version'
|
5
6
|
require 'logger'
|
6
7
|
|
@@ -20,6 +21,8 @@ module CapturefulFormatter
|
|
20
21
|
end
|
21
22
|
|
22
23
|
class Configuration
|
24
|
+
attr_accessor :project_name
|
25
|
+
|
23
26
|
attr_accessor :output_directory
|
24
27
|
|
25
28
|
# what types to take screenshot
|
@@ -45,6 +48,7 @@ module CapturefulFormatter
|
|
45
48
|
end
|
46
49
|
|
47
50
|
CapturefulFormatter.configure do |c|
|
51
|
+
c.project_name = "Your Project"
|
48
52
|
c.output_directory = "./.captureful_formatter"
|
49
53
|
c.target_type = [:feature]
|
50
54
|
c.template_path = File.join(File.dirname(__FILE__), "/../templates/test_report.html.erb")
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'capybara'
|
2
|
-
require 'digest/md5'
|
3
2
|
require 'fileutils'
|
4
3
|
require 'rspec/core'
|
5
4
|
require "rspec/core/formatters/base_formatter"
|
@@ -9,52 +8,54 @@ module CapturefulFormatter
|
|
9
8
|
::RSpec::Core::Formatters.register self, :start, :example_group_started, :example_group_finished,
|
10
9
|
:example_started, :step_started, :example_passed, :example_pending, :example_failed, :stop
|
11
10
|
|
12
|
-
Example = Struct.new("Example", :groups, :steps, :status, :fail_info)
|
13
|
-
FailInfo = Struct.new("FailInfo", :exception, :backtraces)
|
14
|
-
|
15
11
|
def start notification
|
16
12
|
@should_capture = false
|
17
|
-
@
|
18
|
-
@group_level = 0
|
19
|
-
@group_examples = []
|
13
|
+
@features = []
|
20
14
|
end
|
21
15
|
|
22
16
|
def example_group_started notification
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
if notification.group.metadata[:parent_example_group].nil?
|
18
|
+
@should_capture = CapturefulFormatter.configuration.target_type.include? notification.group.metadata[:type]
|
19
|
+
@current_feature = CapturefulFormatter::Structures::Feature.new(notification)
|
20
|
+
else
|
21
|
+
@current_scenario = CapturefulFormatter::Structures::Scenario.new(notification)
|
22
|
+
end
|
26
23
|
end
|
27
24
|
|
28
25
|
def example_group_finished(notification)
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
if notification.group.metadata[:parent_example_group].nil?
|
27
|
+
@features.push @current_feature
|
28
|
+
@should_capture = false
|
29
|
+
else
|
30
|
+
@current_feature.scenarios.push @current_scenario
|
31
|
+
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def example_started notification
|
35
35
|
return unless @should_capture
|
36
|
-
@current_example_hash = Digest::MD5.hexdigest(@group_examples.join())
|
37
|
-
@examples[@current_example_hash] = Example.new(@group_examples.dup, [] , nil, nil)
|
38
36
|
end
|
39
37
|
|
40
38
|
def step_started notification
|
41
|
-
|
39
|
+
return unless @should_capture
|
40
|
+
@current_scenario.steps.push CapturefulFormatter::Structures::Step.new(notification)
|
41
|
+
save_step_sessions
|
42
42
|
end
|
43
43
|
|
44
44
|
def example_passed notification
|
45
45
|
return unless @should_capture
|
46
|
-
|
46
|
+
|
47
|
+
@current_scenario.status = :passed
|
47
48
|
end
|
48
49
|
|
49
50
|
def example_pending notification
|
50
51
|
return unless @should_capture
|
51
|
-
@
|
52
|
+
@current_scenario.status = :pending
|
52
53
|
end
|
53
54
|
|
54
55
|
def example_failed notification
|
55
56
|
return unless @should_capture
|
56
|
-
@
|
57
|
-
@
|
57
|
+
@current_scenario.status = :failed
|
58
|
+
@current_scenario.exception = notification.exception
|
58
59
|
end
|
59
60
|
|
60
61
|
def stop notification
|
@@ -71,18 +72,16 @@ module CapturefulFormatter
|
|
71
72
|
@dir ||= Pathname.new(Dir.mktmpdir ["d", self.object_id.to_s ])
|
72
73
|
end
|
73
74
|
|
74
|
-
def save_step_sessions
|
75
|
+
def save_step_sessions
|
75
76
|
return unless @should_capture
|
76
|
-
|
77
|
-
@examples[@current_example_hash].steps << step_description
|
78
|
-
filename_base = report_save_dir.join("#{@current_example_hash}-#{current_count.to_s}")
|
77
|
+
filename_base = report_save_dir.join("#{@current_scenario.hash}-#{@current_scenario.step_count.to_s}")
|
79
78
|
Capybara.current_session.save_page filename_base.sub_ext(".html")
|
80
79
|
Capybara.current_session.save_screenshot filename_base.sub_ext(".png")
|
81
80
|
end
|
82
81
|
|
83
82
|
def publish_reports
|
84
83
|
FileUtils.copy_entry report_save_dir, CapturefulFormatter.configuration.output_directory
|
85
|
-
CapturefulFormatter::Printer.print @
|
84
|
+
CapturefulFormatter::Printer.print @features
|
86
85
|
end
|
87
86
|
|
88
87
|
def cleanup_reports
|
@@ -23,11 +23,11 @@ module CapturefulFormatter
|
|
23
23
|
class << self
|
24
24
|
attr_accessor :title
|
25
25
|
|
26
|
-
def print
|
26
|
+
def print(features)
|
27
27
|
path = template_path
|
28
28
|
params = {
|
29
|
-
title:
|
30
|
-
|
29
|
+
title: CapturefulFormatter.configuration.project_name,
|
30
|
+
features: features
|
31
31
|
}
|
32
32
|
template = Template.new(params)
|
33
33
|
filename = File.join(CapturefulFormatter.configuration.output_directory, "/index.html")
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module CapturefulFormatter
|
4
|
+
|
5
|
+
# Data Structures for template files.
|
6
|
+
module Structures
|
7
|
+
class Feature
|
8
|
+
attr_accessor :scenarios
|
9
|
+
attr_accessor :description
|
10
|
+
|
11
|
+
# [notification]
|
12
|
+
# GroupNotification
|
13
|
+
def initialize(notification)
|
14
|
+
@description = notification.group.description
|
15
|
+
@scenarios = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def all_passed
|
19
|
+
@scenarios.count == num_passed
|
20
|
+
end
|
21
|
+
|
22
|
+
def num_passed
|
23
|
+
@scenarios.count {|scenario| scenario.status == :passed }
|
24
|
+
end
|
25
|
+
|
26
|
+
def num_pending
|
27
|
+
@scenarios.count {|scenario| scenario.status == :pending }
|
28
|
+
end
|
29
|
+
|
30
|
+
def num_failed
|
31
|
+
@scenarios.count {|scenario| scenario.status == :failed }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Scenario
|
36
|
+
attr_accessor :steps
|
37
|
+
attr_accessor :description
|
38
|
+
attr_accessor :status
|
39
|
+
attr_accessor :exception
|
40
|
+
|
41
|
+
# [notification]
|
42
|
+
# ExampleNotification
|
43
|
+
def initialize(notification)
|
44
|
+
@steps = []
|
45
|
+
@status = nil
|
46
|
+
@description = notification.group.description
|
47
|
+
@exception = nil
|
48
|
+
feature_description = notification.group.metadata[:parent_example_group][:description]
|
49
|
+
@hash = Digest::MD5.hexdigest("#{feature_description}#{notification.group.description}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def hash
|
53
|
+
@hash
|
54
|
+
end
|
55
|
+
|
56
|
+
def step_count
|
57
|
+
@steps.size
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Step
|
62
|
+
attr_accessor :description
|
63
|
+
|
64
|
+
# [notification]
|
65
|
+
# StepNotification
|
66
|
+
def initialize(notification)
|
67
|
+
@description = notification.description
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/sample.png
ADDED
Binary file
|
@@ -44,6 +44,8 @@ describe CapturefulFormatter::Formatter do
|
|
44
44
|
before do
|
45
45
|
allow(RSpec::Core::ExampleGroup).to receive(:metadata).and_return({type: :feature})
|
46
46
|
formatter.example_group_started group_notification
|
47
|
+
allow(RSpec::Core::ExampleGroup).to receive(:metadata).and_return({type: :feature, parent_example_group: {description: "test feature"}})
|
48
|
+
formatter.example_group_started group_notification
|
47
49
|
end
|
48
50
|
|
49
51
|
describe "at step by steps" do
|
@@ -3,7 +3,10 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8">
|
5
5
|
<title><%= title %></title>
|
6
|
-
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
|
6
|
+
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
|
7
|
+
<style type="text/css">
|
8
|
+
body { background-color: #ececec; }
|
9
|
+
</style>
|
7
10
|
</head>
|
8
11
|
<body>
|
9
12
|
<nav class="navbar navbar-inverse navbar-static-top">
|
@@ -16,48 +19,77 @@
|
|
16
19
|
|
17
20
|
<div class="container">
|
18
21
|
<div class="row">
|
19
|
-
<
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
<div class="container">
|
29
|
-
<div class="row">
|
30
|
-
<h2>examples</h2>
|
31
|
-
<% examples.each do |example_hash, example| %>
|
32
|
-
<h3 id=<%= example_hash %>><%= example.groups.join(" - ") %></h3>
|
33
|
-
<% example.steps.each_with_index do |step, index| %>
|
34
|
-
<div class="row <%= (example.steps.size - 1 == index)? background_by_status(example.status) : "" %>">
|
35
|
-
<div class="col-md-5">
|
36
|
-
<a href="./<%= example_hash %>-<%= index %>.png">
|
37
|
-
<img class="img-rounded" height="256" wedth="320" src="./<%= example_hash %>-<%= index %>.png">
|
38
|
-
</a>
|
39
|
-
</div>
|
40
|
-
<div class="col-md-6">
|
41
|
-
<p><%= step %><p>
|
42
|
-
<% if example.steps.size - 1 == index %>
|
43
|
-
<% unless example.fail_info.nil? %>
|
44
|
-
<p><%= example.fail_info.exception %></p>
|
45
|
-
<ul>
|
46
|
-
<% example.fail_info.backtraces.each do |backtrace| %>
|
47
|
-
<li><%= backtrace %></li>
|
48
|
-
<% end %>
|
49
|
-
</ul>
|
50
|
-
<% end %>
|
22
|
+
<div class="col-md-3">
|
23
|
+
<ul class="nav nav-list affix">
|
24
|
+
<% features.each do |feature| %>
|
25
|
+
<li>
|
26
|
+
<a href="#<%= feature.description %>">
|
27
|
+
<%= feature.description %>
|
28
|
+
<% if feature.all_passed %>
|
29
|
+
<span class="label label-success">all passed</span>
|
51
30
|
<% end %>
|
52
|
-
|
53
|
-
|
31
|
+
<% if feature.num_failed > 0 %>
|
32
|
+
<span class="badge alert-danger"><%= feature.num_failed %></span>
|
33
|
+
<% end %>
|
34
|
+
<% if feature.num_pending > 0 %>
|
35
|
+
<span class="badge alert-warning"><%= feature.num_pending %></span>
|
36
|
+
<% end %>
|
37
|
+
</a>
|
38
|
+
</li>
|
39
|
+
<% end %>
|
40
|
+
</ul>
|
41
|
+
</div>
|
42
|
+
<div class="col-md-9">
|
43
|
+
<!-- Test Report -->
|
44
|
+
<div class="page-header">
|
45
|
+
<h1><%= title %> <small>test report</small></h1>
|
46
|
+
</div>
|
47
|
+
<% features.each do |feature| %>
|
48
|
+
<section id="<%= feature.description %>">
|
49
|
+
<h2><%= feature.description %></h2>
|
50
|
+
<ol>
|
51
|
+
<% feature.scenarios.each do |scenario| %>
|
52
|
+
<li>
|
53
|
+
<a href="#<%= scenario.hash %>">
|
54
|
+
<%= scenario.description %>
|
55
|
+
<% if scenario.status == :passed %>
|
56
|
+
<span class="label label-success">passed</span>
|
57
|
+
<% elsif scenario.status == :pending %>
|
58
|
+
<span class="label label-warning">pending</span>
|
59
|
+
<% else %>
|
60
|
+
<span class="label label-danger">failed</span>
|
61
|
+
<% end %>
|
62
|
+
</a>
|
63
|
+
</li>
|
64
|
+
<% end %>
|
65
|
+
</ol>
|
66
|
+
<% feature.scenarios.each do |scenario| %>
|
67
|
+
<section id="<%= scenario.hash %>">
|
68
|
+
<h3><%= scenario.description %></h3>
|
69
|
+
<% scenario.steps.each_with_index do |step, index| %>
|
70
|
+
<div class="row <%= (scenario.step_count - 1 == index)? background_by_status(scenario.status) : "" %>">
|
71
|
+
<div class="col-md-6">
|
72
|
+
<a href="./<%= scenario.hash %>-<%= index + 1 %>.png">
|
73
|
+
<img class="img-thumbnail" height="256" wedth="320" src="./<%= scenario.hash %>-<%= index + 1 %>.png">
|
74
|
+
</a>
|
75
|
+
</div>
|
76
|
+
<div class="col-md-6">
|
77
|
+
<p><%= step.description %><p>
|
78
|
+
<% if ((scenario.step_count - 1) == index) && scenario.status == :failed && !scenario.exception.nil? %>
|
79
|
+
<p><%= scenario.exception.to_s %></p>
|
80
|
+
<% end %>
|
81
|
+
</div>
|
82
|
+
</div><!-- row -->
|
83
|
+
<hr />
|
84
|
+
<% end %>
|
85
|
+
</section>
|
86
|
+
<% end %>
|
87
|
+
</section>
|
54
88
|
<% end %>
|
55
|
-
|
56
|
-
|
89
|
+
<!-- Test Report -->
|
90
|
+
</div>
|
57
91
|
</div>
|
58
92
|
</div>
|
59
|
-
|
60
|
-
|
61
93
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
62
94
|
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
|
63
95
|
</body>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: captureful_formatter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atsushi Yasuda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -100,8 +100,10 @@ files:
|
|
100
100
|
- lib/captureful_formatter/notifications.rb
|
101
101
|
- lib/captureful_formatter/printer.rb
|
102
102
|
- lib/captureful_formatter/rspec_ext/rspec_core_reporter.rb
|
103
|
+
- lib/captureful_formatter/structures.rb
|
103
104
|
- lib/captureful_formatter/turnip_ext/turnip_rspec_execute.rb
|
104
105
|
- lib/captureful_formatter/version.rb
|
106
|
+
- sample.png
|
105
107
|
- spec/captureful_formatter/formatter_spec.rb
|
106
108
|
- spec/captureful_formatter/printer_spec.rb
|
107
109
|
- spec/captureful_formatter_spec.rb
|