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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30f3679548cc23945e25fe8752233c60bd2af5fe
4
- data.tar.gz: 9a7369666c42c652ca0311d87bbf10d5430af47c
3
+ metadata.gz: ad0d60a1d2e31c32f13ef5818453e0b1f6132339
4
+ data.tar.gz: 7101c556ec29a301315d734f2386a2416eb71129
5
5
  SHA512:
6
- metadata.gz: e4cf41d025eacb2900a37fd594f70448195d77ad672234307f69b24cc7094d6f2f90f927b77490f8eca32db7f76b1cb3c8faa5389b889c733c60828bb498ec38
7
- data.tar.gz: 5e2d0bf8c276f76f634c8c31f6e53bd262559203f968856141f44a82bbea4023c94fcd4854e775fc1437d361f2dfadba4e2f8f160868350c15c664f3db5742ef
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
+ ![output sample](https://github.com/crowdworks/captureful_formatter/blob/master/sample.png)
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
@@ -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
- @examples = {}
18
- @group_level = 0
19
- @group_examples = []
13
+ @features = []
20
14
  end
21
15
 
22
16
  def example_group_started notification
23
- @should_capture = CapturefulFormatter.configuration.target_type.include? notification.group.metadata[:type]
24
- @group_level += 1
25
- @group_examples.push notification.group.description
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
- @should_capture = false
30
- @group_level -= 1
31
- @group_examples.pop
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
- save_step_sessions notification.description
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
- @examples[@current_example_hash].status = :passed
46
+
47
+ @current_scenario.status = :passed
47
48
  end
48
49
 
49
50
  def example_pending notification
50
51
  return unless @should_capture
51
- @examples[@current_example_hash].status = :pending
52
+ @current_scenario.status = :pending
52
53
  end
53
54
 
54
55
  def example_failed notification
55
56
  return unless @should_capture
56
- @examples[@current_example_hash].status = :failed
57
- @examples[@current_example_hash].fail_info = FailInfo.new(notification.exception.to_s, notification.formatted_backtrace.dup)
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 step_description
75
+ def save_step_sessions
75
76
  return unless @should_capture
76
- current_count = @examples[@current_example_hash].steps.size
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 @examples
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 examples
26
+ def print(features)
27
27
  path = template_path
28
28
  params = {
29
- title: "test report",
30
- examples: examples
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
@@ -1,3 +1,3 @@
1
1
  module CapturefulFormatter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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
- <h2 id="index">index</h2>
20
- <ul>
21
- <% examples.each do |example_hash, example| %>
22
- <li class="<%= background_by_status example.status %>"><a href="#<%= example_hash %>"><%= example.groups.join(" - ") %></a></li>
23
- <% end %>
24
- </ul>
25
- </div>
26
- </div>
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
- </div>
53
- </div><!-- row -->
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
- <hr />
56
- <% end %>
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.1
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-21 00:00:00.000000000 Z
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