cucumber_converter 0.0.1
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/bin/cucumber_convert +3 -0
- data/lib/background.rb +12 -0
- data/lib/config.rb +17 -0
- data/lib/cucumber_converter.rb +20 -0
- data/lib/feature.rb +51 -0
- data/lib/file_writer.rb +16 -0
- data/lib/given.rb +17 -0
- data/lib/scenario.rb +22 -0
- data/lib/setup.rb +24 -0
- data/lib/step_capture.rb +17 -0
- data/lib/step_container.rb +29 -0
- data/lib/step_converter.rb +17 -0
- data/lib/step_definition.rb +96 -0
- data/lib/tag_parser.rb +6 -0
- data/lib/templates/background.erb +5 -0
- data/lib/templates/feature.erb +6 -0
- data/lib/templates/scenario.erb +5 -0
- data/lib/templates/step_definition.erb +5 -0
- data/lib/templates/step_definitions_file.erb +5 -0
- metadata +62 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e724f4801bff3904058cfe06e7422f9f08fce8ad
|
|
4
|
+
data.tar.gz: b1f1c3ed1ec67fb7d6b0ffcc2134c0d34581bb8c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 70173f93eb47117f642d25e41d05a3d73ffa9fa873776a07d7103f0517ca9800bee3a270e263a2504cc0989e043067266a0712c85f396f4f271a25b2a6fc9cf7
|
|
7
|
+
data.tar.gz: 66d9aad618734b1925cc531a19e120a5a02178c2bad27425f3e0499bda012be656a613a739dcc61d382fa8e378ecdb21cd3f8aace34ca4fc09250d2d46139e09
|
data/lib/background.rb
ADDED
data/lib/config.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Configuration
|
|
2
|
+
class << self
|
|
3
|
+
def default_config
|
|
4
|
+
{
|
|
5
|
+
step_path_base: File.expand_path("features/step_definitions", WD),
|
|
6
|
+
feature_path_base: File.expand_path("features", WD),
|
|
7
|
+
tags: { "@javascript" => "js: true" }
|
|
8
|
+
}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def config(config_file)
|
|
12
|
+
OpenStruct.new(default_config.merge(
|
|
13
|
+
File.exists?(config_file) ? YAML.load_file(config_file) : {}
|
|
14
|
+
))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'setup'
|
|
2
|
+
|
|
3
|
+
# load all step definitions to be captured
|
|
4
|
+
# having redifined 'Given' in the main object, loading these files in the main scope
|
|
5
|
+
# should call our definition, which has a reference to our step capturer to capture these calls.
|
|
6
|
+
Dir.glob("#{Config.step_path_base}/**/*.rb").each(&method(:load))
|
|
7
|
+
|
|
8
|
+
# Beep Boop Beep -- now we have code for step definitions
|
|
9
|
+
steps = step_capturer.post_process!
|
|
10
|
+
|
|
11
|
+
# Write those files!
|
|
12
|
+
step_definitions = StepDefinition.parse_steps(steps, Config.step_path_base)
|
|
13
|
+
FileWriter.write_files(step_definitions)
|
|
14
|
+
|
|
15
|
+
# convert feature files
|
|
16
|
+
# use gherkin parser to get an object representation of a feature file,
|
|
17
|
+
# and write it in rspec syntax
|
|
18
|
+
feature_files = Dir.glob("#{Config.feature_path_base}/**/*.feature")
|
|
19
|
+
features = Feature.parse_features(feature_files, Gherkin::Parser.new, steps)
|
|
20
|
+
FileWriter.write_files(features)
|
data/lib/feature.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class Feature
|
|
2
|
+
include StepContainer
|
|
3
|
+
|
|
4
|
+
attr_accessor :gherkin
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def parse_features(feature_files, parser, steps)
|
|
8
|
+
feature_files.each_with_object({}) do |filename, memo|
|
|
9
|
+
gherkin_document = parser.parse(File.read(filename))
|
|
10
|
+
memo[new_filename(filename)] = new(gherkin_document, steps)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def new_filename(filename)
|
|
15
|
+
FileWriter
|
|
16
|
+
.write_path(Config.feature_path_base, "cucumber_to_rspec/features/", WD, filename)
|
|
17
|
+
.gsub('.feature', '.rb')
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize(gherkin, step_data)
|
|
22
|
+
@gherkin = gherkin
|
|
23
|
+
@step_data = step_data
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def feature_name
|
|
29
|
+
@feature_name ||= gherkin[:feature][:name]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def feature_tags
|
|
33
|
+
tag_parser.format_tags(gherkin[:feature][:tags])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def scenarios
|
|
37
|
+
@scenarios ||= gherkin[:feature][:children].select { |child|
|
|
38
|
+
child[:type] == :Scenario
|
|
39
|
+
}.map{ |child| Scenario.new(child, step_data) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def background
|
|
43
|
+
@background ||= gherkin[:feature][:children].select { |child|
|
|
44
|
+
child[:type] == :Background
|
|
45
|
+
}.map{ |child| Background.new(child, step_data) }.first
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def template_path
|
|
49
|
+
File.expand_path('./templates/feature.erb', GEM_PATH)
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/file_writer.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module FileWriter
|
|
2
|
+
class << self
|
|
3
|
+
def write_path(base_path, write_path, wd, filename)
|
|
4
|
+
File.expand_path(filename.gsub(base_path, File.expand_path(write_path, wd)))
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def write_file(file_path, file_contents)
|
|
8
|
+
response = FileUtils.mkdir_p(File.dirname(file_path))
|
|
9
|
+
File.open(file_path, 'w+') { |f| f.write(file_contents) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def write_files(files)
|
|
13
|
+
files.each(&method(:write_file))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/given.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module GivenDefinition
|
|
2
|
+
# Define Given, Then, When, And to record all step definitions.
|
|
3
|
+
|
|
4
|
+
attr_reader :step_capturer
|
|
5
|
+
|
|
6
|
+
def set_step_capturer(step_capturer)
|
|
7
|
+
@step_capturer = step_capturer
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def Given(regex, &block)
|
|
11
|
+
step_capturer.capture!(regex, &block)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
alias Then Given
|
|
15
|
+
alias And Given
|
|
16
|
+
alias When Given
|
|
17
|
+
end
|
data/lib/scenario.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class Scenario
|
|
2
|
+
include StepContainer
|
|
3
|
+
|
|
4
|
+
attr_accessor :name
|
|
5
|
+
|
|
6
|
+
def initialize(gherkin, step_data)
|
|
7
|
+
@name = gherkin[:name]
|
|
8
|
+
@steps = gherkin[:steps] || []
|
|
9
|
+
@tags = gherkin[:tags]
|
|
10
|
+
@step_data = step_data
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def scenario_tags
|
|
16
|
+
tag_parser.format_tags(@tags)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def template_path
|
|
20
|
+
File.expand_path('./templates/scenario.erb', GEM_PATH)
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/setup.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require "ostruct"
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'erb'
|
|
5
|
+
require 'gherkin/parser'
|
|
6
|
+
require 'gherkin/pickles/compiler'
|
|
7
|
+
require_relative 'config'
|
|
8
|
+
require_relative 'step_capture'
|
|
9
|
+
require_relative 'file_writer'
|
|
10
|
+
require_relative 'step_container'
|
|
11
|
+
require_relative 'step_definition'
|
|
12
|
+
require_relative 'step_converter'
|
|
13
|
+
require_relative 'feature'
|
|
14
|
+
require_relative 'background'
|
|
15
|
+
require_relative 'scenario'
|
|
16
|
+
require_relative 'tag_parser'
|
|
17
|
+
require 'given'
|
|
18
|
+
|
|
19
|
+
WD = `pwd`.chomp
|
|
20
|
+
GEM_PATH = File.dirname(File.expand_path(__FILE__))
|
|
21
|
+
Config = Configuration.config(File.expand_path('.cucumber_converter.yml', WD))
|
|
22
|
+
|
|
23
|
+
include GivenDefinition
|
|
24
|
+
set_step_capturer(StepCapturer.new)
|
data/lib/step_capture.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class StepCapturer
|
|
2
|
+
attr_accessor :step_definitions
|
|
3
|
+
|
|
4
|
+
def initialize
|
|
5
|
+
@step_definitions = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def capture!(regex, &block)
|
|
9
|
+
step_definitions << StepDefinition.new(regex, &block)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def post_process!
|
|
13
|
+
@step_definitions = step_definitions.map do |step|
|
|
14
|
+
step.process!(step_definitions)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module StepContainer
|
|
2
|
+
attr_accessor :steps, :step_data
|
|
3
|
+
|
|
4
|
+
def to_s
|
|
5
|
+
template.result(binding)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def tag_parser
|
|
11
|
+
@tag_parser ||= TagParser.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def step_converter
|
|
15
|
+
@step_converter ||= StepConverter.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse_step(step)
|
|
19
|
+
step_converter.convert(step[:text], step_data)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def parsed_steps
|
|
23
|
+
steps.map(&method(:parse_step))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def template
|
|
27
|
+
ERB.new(File.read(template_path), nil, '->')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class StepConverter
|
|
2
|
+
def convert(step_line, step_definitions)
|
|
3
|
+
matched = matched_step(step_line, step_definitions)
|
|
4
|
+
if matched
|
|
5
|
+
arguments = matched.regex.match(step_line)[1..-1]
|
|
6
|
+
"#{matched.method_name}(#{arguments.map(&:inspect).join(", ")})"
|
|
7
|
+
else
|
|
8
|
+
"# #{step_line} -- no method matched"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def matched_step(step_line, step_definitions)
|
|
13
|
+
step_definitions.find do |step_definition|
|
|
14
|
+
step_definition.regex.match(step_line)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'method_source'
|
|
2
|
+
|
|
3
|
+
class StepDefinition
|
|
4
|
+
WRITE_PATH = "cucumber_to_rspec/step_definitions/"
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def parse_steps(steps, base_path)
|
|
8
|
+
self.steps_by_file(steps).each_with_object({}) do |(filename, file_steps), memo|
|
|
9
|
+
memo[self.new_file_path(filename, base_path)] = self.render_template(file_steps)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def steps_by_file(steps)
|
|
14
|
+
steps.group_by(&:location)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def new_file_path(filename, base_path)
|
|
18
|
+
FileWriter.write_path(base_path, WRITE_PATH, WD, filename)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def render_template(file_steps)
|
|
22
|
+
self.template.result(binding)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def template
|
|
26
|
+
ERB.new(File.read(self.template_path), nil, '->')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def template_path
|
|
30
|
+
File.expand_path('./templates/step_definitions_file.erb', GEM_PATH)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attr_accessor :regex, :block, :location, :method_name, :processed_code
|
|
35
|
+
|
|
36
|
+
def step_converter
|
|
37
|
+
@step_converter ||= StepConverter.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def initialize(regex, &block)
|
|
41
|
+
@regex = regex
|
|
42
|
+
@method_name = method_name_from_regex(regex)
|
|
43
|
+
@block = block
|
|
44
|
+
@location = block.source_location.first
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def method_name_from_regex(regex)
|
|
48
|
+
regex
|
|
49
|
+
.inspect[1..-2]
|
|
50
|
+
.gsub(/\s/,"_")
|
|
51
|
+
.gsub(/\W|\d/,"")
|
|
52
|
+
.gsub(/_$/,"")
|
|
53
|
+
.gsub(/_+/,"_")
|
|
54
|
+
.downcase
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_s
|
|
58
|
+
template.result(binding)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def template_path
|
|
62
|
+
File.expand_path('./templates/step_definition.erb', GEM_PATH)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def template
|
|
66
|
+
ERB.new(File.read(template_path), nil, '->')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def block_source
|
|
70
|
+
@block_source ||= block.source
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def method_definition
|
|
74
|
+
return @method_definition if @method_definition
|
|
75
|
+
match = block_source.split("\n").first.match(/(?:And|When|Then|Given)\(.*\)[\s]do[\s]?(?:\|(.*)\|)?/)
|
|
76
|
+
@method_definition = match ? method_name + ('(%s)' % match[1]) : method_name
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def method_body
|
|
80
|
+
@method_body || raise("Method not processed")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# this is specifically looking to references to other steps, by way of the 'step' call. If it finds these lines
|
|
84
|
+
# it will substitute a direct method call, like we do with the features
|
|
85
|
+
def process!(step_definitions)
|
|
86
|
+
@method_body = block_source.split("\n")[1..-2].map do |line|
|
|
87
|
+
step_method_call_match = line.match(/^(\s*)step "(.*)"/)
|
|
88
|
+
if step_method_call_match
|
|
89
|
+
step_method_call_match[1] + step_converter.convert(step_method_call_match[2], step_definitions)
|
|
90
|
+
else
|
|
91
|
+
line
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
return self
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/tag_parser.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cucumber_converter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tracy Meade
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-07-28 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Converts cucumber tests to Rspec Features
|
|
14
|
+
email: meade.tracy@gmail.com
|
|
15
|
+
executables:
|
|
16
|
+
- cucumber_convert
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- bin/cucumber_convert
|
|
21
|
+
- lib/background.rb
|
|
22
|
+
- lib/config.rb
|
|
23
|
+
- lib/cucumber_converter.rb
|
|
24
|
+
- lib/feature.rb
|
|
25
|
+
- lib/file_writer.rb
|
|
26
|
+
- lib/given.rb
|
|
27
|
+
- lib/scenario.rb
|
|
28
|
+
- lib/setup.rb
|
|
29
|
+
- lib/step_capture.rb
|
|
30
|
+
- lib/step_container.rb
|
|
31
|
+
- lib/step_converter.rb
|
|
32
|
+
- lib/step_definition.rb
|
|
33
|
+
- lib/tag_parser.rb
|
|
34
|
+
- lib/templates/background.erb
|
|
35
|
+
- lib/templates/feature.erb
|
|
36
|
+
- lib/templates/scenario.erb
|
|
37
|
+
- lib/templates/step_definition.erb
|
|
38
|
+
- lib/templates/step_definitions_file.erb
|
|
39
|
+
homepage:
|
|
40
|
+
licenses: []
|
|
41
|
+
metadata: {}
|
|
42
|
+
post_install_message:
|
|
43
|
+
rdoc_options: []
|
|
44
|
+
require_paths:
|
|
45
|
+
- lib
|
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '0'
|
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
56
|
+
requirements: []
|
|
57
|
+
rubyforge_project:
|
|
58
|
+
rubygems_version: 2.4.5.1
|
|
59
|
+
signing_key:
|
|
60
|
+
specification_version: 4
|
|
61
|
+
summary: Converts cucumber tests to Rspec Features
|
|
62
|
+
test_files: []
|