launcuke 0.0.0 → 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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzI2M2UzMjhjNWFmZWY4ZGZjOTAyZmNmY2ZmODUyZDUxNDRjMjI3Zg==
4
+ ODgyNmIwNzBhOWJlNjk3NjYzN2E4NDlmOGNmZDczMDE4ZTM0ODY5OA==
5
5
  data.tar.gz: !binary |-
6
- NDVhOGY2YzQyODQ0NjNlN2JmNDgwYzM5MjJiZDUwOWZlNmFlZjUxZg==
6
+ YzdkOTBhNjFiZDliZDA4NzFlMmE5ODU2Y2Q0MmI3NTE2YzFmYzNlOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTA0Y2RiZWE1ODRhOGU4ZGMzNGFlNzEyODllNWQ1MGQ2YzA2OTEzYjYxZmE0
10
- Y2ZjOTQwYzAwOWJkYzRiMjRhZWJiMWIyODc5NTAzOTI4NDlmNzdkMzZkNWM0
11
- M2E5NGQ0ZGRiYjNlOWQ4ZWMzMjYxYzE2MjE4MGViZjUyMzAzZDY=
9
+ MjVjNWU2ZWFiM2I4MWIzYWE2MzdmZDc0NjQxOTQwODBlMDBlMWM3MjFlNTlh
10
+ Y2IwNTM1NTAyZDkzYWZmYTk0NTdhNDQxMDUyY2FkNzU3NmIwMThjM2M1MWFj
11
+ MWQ1NDlkOWQwZWQxMzM0MTliNzQzN2Q1Y2ZlN2FlN2UzYjRiNmI=
12
12
  data.tar.gz: !binary |-
13
- ODU1ZjMzZTc3OTEwYTUzZTI2YTQ3YzVhMWFmN2VkYWRiZTk2NWE0OGVjYjA3
14
- NTk4ZTk0NDg3YjY2NGYzYWI1NWJiNDNiYjJhYzhkNjY2NWZhOTc5MTUwZjdi
15
- NGEzZDIwOWFmY2MwYzRmMWU3YzNkYzE4MTZmZTY4YTM0NzljZDI=
13
+ MzkwZDBjYjI0OTEwNGI4OTYzNWE5MGM3NDY5YmY5ZTU4ZjIzODBmYjVjODJl
14
+ ZWY1Njc1Yzk3NTMxYTBhODgwNzg2NDI3ODk4ZWQ5NmE5ZTkzMzJiZmMwNTIx
15
+ NTRmNTY1MmQ0MzdkMGVhZmYyZmY0YzQ0Mjc4NzQ5MmQ0MTc5YTk=
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'cucumber'
4
+ gem 'rspec'
5
+ gem 'nokogiri'
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Launcuke
2
+
3
+ Run your cucumber test and generate a index html page to show all reports by feature.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'launcuke'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install launcuke
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/launcuke/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/launcuke.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/launcuke/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'launcuke'
6
+ s.date = '2014-11-24'
7
+ s.summary = "Launch cuke!"
8
+ s.description = "A simple cucumber runner gem"
9
+ s.authors = ["Yi MIN"]
10
+ s.email = 'tebat804@gmail.com'
11
+ s.files = ["lib/launcuke.rb"]
12
+ s.homepage =
13
+ 'http://rubygems.org/gems/launcuke'
14
+ s.files = `git ls-files`.split($\)
15
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ s.license = 'MIT'
17
+ s.require_paths = ["lib"]
18
+ s.version = Launcuke::VERSION
19
+ s.add_dependency 'cucumber'
20
+ s.add_dependency 'rspec'
21
+ s.add_dependency 'nokogiri'
22
+ end
@@ -0,0 +1,59 @@
1
+ module Launcuke
2
+
3
+ # Generate the index page reporting on the features and their status.
4
+ # Provides the links to the actual full Cucumber html reports.
5
+ class ReportsIndex
6
+
7
+ # Collection of ran features directories results used for reporting
8
+ attr_reader :features_dirs
9
+
10
+ # Full path for the index html file
11
+ attr_reader :index_path
12
+
13
+ def initialize(reports_path, features_dirs)
14
+ @features_dirs = features_dirs
15
+ @index_path = File.join(reports_path, "index.html")
16
+ end
17
+
18
+ def generate
19
+ index_file = File.new(index_path, "w")
20
+
21
+ b = Builder::XmlMarkup.new :target => index_file, :indent => 2
22
+ b.html {
23
+ b.head {
24
+ b.title("Cucumber Reports")
25
+ b.style(css_content)
26
+ }
27
+ b.body {
28
+ b.h2("Features")
29
+ b.ul {
30
+ features_dirs.each { |features_dir|
31
+ b.li(:class => (features_dir.failed? ? "failed" : "success")) {
32
+ b.a(features_dir.human_name, :href => "#{features_dir.dir_name}.html")
33
+ b.span("[#{features_dir.duration}]", :class => "duration")
34
+ b.span("Scenarios: #{features_dir.scenarios_results}, Steps: #{features_dir.steps_results}", :class => "result")
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ index_file.close
42
+ end
43
+
44
+ private
45
+
46
+ def css_content
47
+ <<-CSS
48
+ body {font-family: "Lucida Grande", Helvetica, sans-serif; margin: 2em 8em 2em 8em;}
49
+ ul {list-style-type: square;}
50
+ li {margin: 1em 0 1em 0;}
51
+ li span {float: right; margin-left: 1em; padding: 0 0.3em;}
52
+ li.failed span.result{background: #DC6E6E;}
53
+ li.success span.result{background: #C1E799;}
54
+ span.duration {color: #999999;}
55
+ CSS
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,197 @@
1
+ require 'launcuke/index'
2
+
3
+ module Launcuke
4
+
5
+ # Wrapper of {Kernel#system} method for test/mock
6
+ class SystemCommand
7
+
8
+ def run(full_command_as_array)
9
+ system *full_command_as_array
10
+ end
11
+
12
+ def exit(status = 0)
13
+ Kernel.exit(status == 0)
14
+ end
15
+
16
+ end
17
+
18
+ # Set of features under one specific directory
19
+ class FeaturesDir
20
+
21
+ # Directory name fo the features
22
+ attr_reader :dir_name
23
+
24
+ # Result string for passed/failed scenarios
25
+ attr_accessor :scenarios_results
26
+
27
+ # Result string for passed/failed steps
28
+ attr_accessor :steps_results
29
+
30
+ # Running time in ms for all features in this feature directory
31
+ attr_accessor :duration
32
+
33
+ # True if a scenario or step has failed for this set of features
34
+ attr_writer :failed
35
+
36
+ def initialize(directory_name)
37
+ @dir_name = directory_name
38
+ @failed = false
39
+ @scenarios_results = ""
40
+ @steps_results = ""
41
+ end
42
+
43
+ # True if one feature has failed
44
+ def failed?
45
+ (scenarios_results.include?"failed") || (steps_results.include?"failed")
46
+ end
47
+
48
+ # Human readable name used for index page (ex: user_logout --> User logout)
49
+ def human_name
50
+ dir_name.gsub(/[_-]/, " ").capitalize
51
+ end
52
+
53
+ end
54
+
55
+ # Actual clas that will spawn one command process per directory of features collected
56
+ # according to configuration
57
+ class Runner
58
+
59
+ # Root path to your features directory. Ex: your_project/features
60
+ attr_accessor :features_root_path
61
+
62
+ # Optional name for directory containing the reports. Default to 'cucumber_reports'
63
+ attr_accessor :output_dir_name
64
+
65
+ # Optional full path for generated reports. Default to ../{features_root_path}.
66
+ attr_accessor :output_path
67
+
68
+ # Optional regexp for name of features directories to exclude.
69
+ attr_accessor :excluded_dirs
70
+
71
+ # Optional only the features directories to be included
72
+ attr_accessor :included_only_dirs
73
+
74
+ # Array of extra options to pass to the command. Ex: ["-p", "my_profile", "--backtrace"]
75
+ attr_accessor :extra_options
76
+
77
+ # Define the size for the pool of forks. Default is 5
78
+ attr_accessor :forks_pool_size
79
+
80
+ # Full final path where html reports will be generated
81
+ attr_reader :reports_path
82
+
83
+ # Optional. If true will generate index file but not launch processes. Used for testing.
84
+ attr_accessor :dry_run
85
+
86
+ # Add cucumber --require option load *.rb files under features root path by default unless specified to false.
87
+ attr_accessor :require_features_root_option
88
+
89
+ # Delegate to a wrapper of system call in order mock/test
90
+ attr_accessor :system_command
91
+
92
+ def initialize(features_root)
93
+ @features_root_path = features_root
94
+ @extra_options ||= []
95
+ yield self if block_given?
96
+
97
+ @dry_run = false if dry_run.nil?
98
+ @forks_pool_size ||= 5
99
+ @require_features_root_option = true if require_features_root_option.nil?
100
+ @output_dir_name = "#{@extra_options[1]}" unless output_dir_name
101
+ @output_path = File.expand_path("../reports", output_dir_name) unless output_path
102
+ @excluded_dirs ||= []
103
+ @included_only_dirs ||= []
104
+
105
+ @reports_path = File.join(output_path, output_dir_name)
106
+ @system_command ||= SystemCommand.new
107
+ end
108
+
109
+ def start
110
+ FileUtils.mkdir_p reports_path
111
+ exit_status = launch_process_per_dir
112
+ collect_results
113
+ reports = ReportsIndex.new(reports_path, features_dirs).generate
114
+ puts "See reports index at #{reports.index_path}" if reports
115
+ system_command.exit(exit_status)
116
+ end
117
+
118
+ private
119
+
120
+ def launch_process_per_dir
121
+ if dry_run
122
+ 0
123
+ else
124
+
125
+ results = features_dirs.each { |features_dir|
126
+ report_file_path = File.join(reports_path, "#{features_dir.dir_name}.html")
127
+ feature_full_path = File.join(features_root_path, "#{features_dir.dir_name}")
128
+ main_command = %W[bundle exec cucumber #{feature_full_path}]
129
+ options = %W[--format html --out #{report_file_path}]
130
+ options.concat %W[--require #{features_root_path}] if require_features_root_option
131
+ full_command = main_command + options + extra_options
132
+ result = system_command.run full_command
133
+ puts "Features '#{features_dir.dir_name.upcase}' finished. #{result ? 'SUCCESS' : 'FAILURE'} (pid: #{Process.pid})"
134
+ result
135
+ }
136
+
137
+
138
+ global_exit_status = results.inject(0) { |acc, result|
139
+ result ? acc : acc +1
140
+ }
141
+ puts "Global exit status = #{global_exit_status}"
142
+ global_exit_status
143
+ end
144
+ end
145
+
146
+ def collect_results
147
+ features_dirs.each { |features_dir|
148
+ feature_file = File.join(reports_path, "#{features_dir.dir_name}.html")
149
+ File.open(feature_file) { |file|
150
+ content = file.read
151
+ duration_match = content.match(/Finished in\s+<\w+>(.*?)</)
152
+ duration = duration_match ? duration_match.captures.first : ""
153
+ scenarios_match = content.match(/\d+ scenarios? \((.*?)\)/)
154
+ scenarios = scenarios_match ? scenarios_match.captures.first : ""
155
+ steps_match = content.match(/\d+ steps? \((.*?)\)/)
156
+ steps = steps_match ? steps_match.captures.first : ""
157
+
158
+ features_dir.scenarios_results = scenarios
159
+ features_dir.steps_results = steps
160
+ features_dir.duration = duration
161
+ } if File.exists?(feature_file)
162
+ }
163
+ end
164
+
165
+ def features_dirs
166
+ @features_dirs ||= resolve_features_dirs_name
167
+ end
168
+
169
+ def resolve_features_dirs_name
170
+ Dir.glob(File.join(features_root_path, "*", "*.feature")).select{ |path|
171
+ configured_dir?(path)
172
+ }.map { |feature_path|
173
+ dir_name = File.basename(File.dirname(feature_path))
174
+ FeaturesDir.new(dir_name)
175
+ }.uniq { |feature_dir|
176
+ feature_dir.dir_name
177
+ }
178
+ end
179
+
180
+ def configured_dir?(path)
181
+ if included_only_dirs.empty?
182
+ included_dir?(path)
183
+ else
184
+ exact_word_match_expressions = included_only_dirs.map { |dir_name|
185
+ "\\b#{dir_name}\\b"
186
+ }
187
+ path.match(Regexp.new(exact_word_match_expressions.join("|")))
188
+ end
189
+ end
190
+
191
+ def included_dir?(path)
192
+ excluded_dirs.empty? || (not path.match(Regexp.new(excluded_dirs.join("|"))))
193
+ end
194
+
195
+ end
196
+
197
+ end
@@ -0,0 +1,3 @@
1
+ module Launcuke
2
+ VERSION = '0.0.2'
3
+ end
data/lib/launcuke.rb CHANGED
@@ -1,5 +1,6 @@
1
- class Launcuke
2
- def self.hi
3
- puts "Hello world!"
4
- end
5
- end
1
+ require "launcuke/version"
2
+ require "launcuke/runner"
3
+
4
+ require 'fileutils'
5
+ require 'builder'
6
+ require 'nokogiri'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: launcuke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yi MIN
@@ -9,14 +9,62 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2014-11-24 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cucumber
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: rspec
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: nokogiri
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'
13
55
  description: A simple cucumber runner gem
14
56
  email: tebat804@gmail.com
15
57
  executables: []
16
58
  extensions: []
17
59
  extra_rdoc_files: []
18
60
  files:
61
+ - Gemfile
62
+ - README.md
63
+ - launcuke.gemspec
19
64
  - lib/launcuke.rb
65
+ - lib/launcuke/index.rb
66
+ - lib/launcuke/runner.rb
67
+ - lib/launcuke/version.rb
20
68
  homepage: http://rubygems.org/gems/launcuke
21
69
  licenses:
22
70
  - MIT