lucid 0.2.1 → 0.3.0
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/HISTORY.md +13 -0
- data/bin/lucid +1 -7
- data/lib/lucid/ast/doc_string.rb +1 -1
- data/lib/lucid/ast/step_invocation.rb +2 -2
- data/lib/lucid/cli/app.rb +6 -2
- data/lib/lucid/cli/configuration.rb +18 -5
- data/lib/lucid/cli/options.rb +56 -53
- data/lib/lucid/core_ext/instance_exec.rb +1 -2
- data/lib/lucid/core_ext/proc.rb +2 -2
- data/lib/lucid/errors.rb +3 -3
- data/lib/lucid/formatter/ansicolor.rb +20 -21
- data/lib/lucid/formatter/console.rb +1 -1
- data/lib/lucid/formatter/progress.rb +1 -1
- data/lib/lucid/generators/project.rb +1 -7
- data/lib/lucid/generators/project/browser-fluent.rb +0 -1
- data/lib/lucid/generators/project/events-fluent.rb +1 -4
- data/lib/lucid/interface_rb/matcher.rb +7 -7
- data/lib/lucid/interface_rb/rb_lucid.rb +2 -0
- data/lib/lucid/interface_rb/rb_step_definition.rb +5 -6
- data/lib/lucid/interface_rb/rb_world.rb +2 -3
- data/lib/lucid/platform.rb +3 -3
- data/lib/lucid/runtime/facade.rb +9 -11
- data/lib/lucid/runtime/orchestrator.rb +2 -3
- data/lib/lucid/runtime/results.rb +0 -2
- data/lib/lucid/spec_file.rb +1 -3
- data/spec/lucid/ansicolor_spec.rb +31 -0
- data/spec/lucid/app_spec.rb +73 -4
- data/spec/lucid/ast/background_spec.rb +128 -0
- data/spec/lucid/ast/doc_string_spec.rb +36 -0
- data/spec/lucid/ast/feature_spec.rb +66 -0
- data/spec/lucid/ast/outline_table_spec.rb +21 -0
- data/spec/lucid/ast/scenario_outline_spec.rb +81 -0
- data/spec/lucid/ast/specs_spec.rb +48 -0
- data/spec/lucid/ast/step_invocation_spec.rb +45 -0
- data/spec/lucid/ast/step_spec.rb +72 -0
- data/spec/lucid/ast/table_spec.rb +265 -0
- data/spec/lucid/ast/tdl_factory.rb +78 -0
- data/spec/lucid/ast/tdl_walker_spec.rb +21 -0
- data/spec/lucid/configuration_spec.rb +163 -8
- data/spec/lucid/duration_spec.rb +22 -0
- data/spec/lucid/facade_spec.rb +31 -0
- data/spec/lucid/matcher_spec.rb +127 -0
- data/spec/lucid/options_spec.rb +223 -3
- data/spec/lucid/orchestrator_spec.rb +117 -0
- data/spec/lucid/pending_spec.rb +45 -0
- data/spec/lucid/progress_spec.rb +34 -0
- data/spec/lucid/rb_step_definition_spec.rb +127 -0
- data/spec/lucid/rb_transform_spec.rb +24 -0
- data/spec/lucid/regexp_argument_matcher_spec.rb +19 -0
- data/spec/lucid/results_spec.rb +81 -0
- data/spec/lucid/runtime_spec.rb +1 -1
- data/spec/lucid/step_match_spec.rb +55 -0
- data/spec/spec_helper.rb +11 -5
- metadata +51 -7
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/lib/lucid/generators/project/lucid-fluent.yml +0 -6
@@ -210,7 +210,7 @@ module Lucid
|
|
210
210
|
profiles_sentence = profiles.size == 1 ? profiles.first :
|
211
211
|
"#{profiles[0...-1].join(', ')} and #{profiles.last}"
|
212
212
|
|
213
|
-
@io.puts "Using the #{profiles_sentence} profile#{'s' if profiles.size> 1}
|
213
|
+
@io.puts "Using the #{profiles_sentence} profile#{'s' if profiles.size> 1}...\n\n"
|
214
214
|
end
|
215
215
|
|
216
216
|
private
|
@@ -9,7 +9,7 @@ module Lucid
|
|
9
9
|
attr_reader :runtime
|
10
10
|
|
11
11
|
def initialize(runtime, path_or_io, options)
|
12
|
-
@runtime, @io, @options = runtime, ensure_io(path_or_io,
|
12
|
+
@runtime, @io, @options = runtime, ensure_io(path_or_io, 'progress'), options
|
13
13
|
end
|
14
14
|
|
15
15
|
def before_features(features)
|
@@ -7,7 +7,7 @@ Before('~@practice','~@sequence') do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
AfterStep('@pause') do
|
10
|
-
print
|
10
|
+
print 'Press ENTER to continue...'
|
11
11
|
STDIN.getc
|
12
12
|
end
|
13
13
|
|
@@ -24,9 +24,6 @@ After do |scenario|
|
|
24
24
|
encoded_img = @browser.driver.screenshot_as(:base64)
|
25
25
|
embed("data:image/png;base64,#{encoded_img}", 'image/png')
|
26
26
|
end
|
27
|
-
|
28
|
-
# This is an alternative way to embed.
|
29
|
-
#embed screenshot, 'image/png'
|
30
27
|
end
|
31
28
|
Fluent::Browser.stop
|
32
29
|
end
|
@@ -41,11 +41,11 @@ module Lucid
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def do_block
|
44
|
-
do_block =
|
44
|
+
do_block = ''
|
45
45
|
do_block << "do#{arguments}\n"
|
46
46
|
do_block << multiline_comment if multiline_argument_class?
|
47
47
|
do_block << " pending\n"
|
48
|
-
do_block <<
|
48
|
+
do_block << 'end'
|
49
49
|
do_block
|
50
50
|
end
|
51
51
|
|
@@ -56,7 +56,7 @@ module Lucid
|
|
56
56
|
block_args << multiline_argument_class.default_arg_name
|
57
57
|
end
|
58
58
|
|
59
|
-
block_args.empty? ?
|
59
|
+
block_args.empty? ? '' : " |#{block_args.join(", ")}|"
|
60
60
|
end
|
61
61
|
|
62
62
|
def multiline_comment
|
@@ -68,7 +68,7 @@ module Lucid
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def self.example
|
71
|
-
new(
|
71
|
+
new('Given', 'some phrase', nil).step
|
72
72
|
end
|
73
73
|
|
74
74
|
end
|
@@ -79,7 +79,7 @@ module Lucid
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def self.description
|
82
|
-
|
82
|
+
'Matchers with parentheses.'
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -89,7 +89,7 @@ module Lucid
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def self.description
|
92
|
-
|
92
|
+
'Matchers without parentheses.'
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -99,7 +99,7 @@ module Lucid
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def self.description
|
102
|
-
|
102
|
+
'Matchers with delimited regexp.'
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -50,6 +50,8 @@ module Lucid
|
|
50
50
|
RbLucid.build_rb_world_factory(domain_modules, proc)
|
51
51
|
end
|
52
52
|
|
53
|
+
alias_method :World, :Domain
|
54
|
+
|
53
55
|
# Registers a proc that will run before each Scenario. You can register as many
|
54
56
|
# as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
|
55
57
|
def Before(*tag_expressions, &proc)
|
@@ -5,13 +5,12 @@ require 'lucid/interface_rb/regexp_argument_matcher'
|
|
5
5
|
|
6
6
|
module Lucid
|
7
7
|
module InterfaceRb
|
8
|
-
# A Ruby
|
9
|
-
# by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt
|
10
|
-
# in the <tt>step_definitions</tt> ruby files. See also RbLucid.
|
8
|
+
# A Ruby test definition holds a Regexp and a Proc, and is created
|
9
|
+
# by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt>.
|
11
10
|
#
|
12
11
|
# Example:
|
13
12
|
#
|
14
|
-
# Given /
|
13
|
+
# Given /there are (\d+) lucid tests to run/ do
|
15
14
|
# # some code here
|
16
15
|
# end
|
17
16
|
#
|
@@ -19,7 +18,7 @@ module Lucid
|
|
19
18
|
|
20
19
|
class MissingProc < StandardError
|
21
20
|
def message
|
22
|
-
|
21
|
+
'Test definitions must always have a proc or symbol'
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
@@ -59,7 +58,7 @@ module Lucid
|
|
59
58
|
when Symbol
|
60
59
|
lambda { self.send(target) }
|
61
60
|
else
|
62
|
-
lambda { raise ArgumentError,
|
61
|
+
lambda { raise ArgumentError, 'Target must be a symbol or a proc' }
|
63
62
|
end
|
64
63
|
end
|
65
64
|
end
|
@@ -99,14 +99,14 @@ module Lucid
|
|
99
99
|
end
|
100
100
|
|
101
101
|
# Mark the matched step as pending.
|
102
|
-
def pending(message =
|
102
|
+
def pending(message = 'TODO')
|
103
103
|
if block_given?
|
104
104
|
begin
|
105
105
|
yield
|
106
106
|
rescue Exception
|
107
107
|
raise Pending.new(message)
|
108
108
|
end
|
109
|
-
raise Pending.new("Expected pending '#{message}' to fail. No
|
109
|
+
raise Pending.new("Expected pending '#{message}' to fail. No error was raised. No longer pending?")
|
110
110
|
else
|
111
111
|
raise Pending.new(message)
|
112
112
|
end
|
@@ -121,7 +121,6 @@ module Lucid
|
|
121
121
|
sprintf("#<%s:0x%x>", modules.join('+'), self.object_id)
|
122
122
|
end
|
123
123
|
|
124
|
-
# see {#inspect}
|
125
124
|
def to_s
|
126
125
|
inspect
|
127
126
|
end
|
data/lib/lucid/platform.rb
CHANGED
@@ -2,11 +2,11 @@ require 'rbconfig'
|
|
2
2
|
|
3
3
|
module Lucid
|
4
4
|
unless defined?(Lucid::VERSION)
|
5
|
-
VERSION = '0.
|
5
|
+
VERSION = '0.3.0'
|
6
6
|
BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/lucid')
|
7
7
|
LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
8
8
|
JRUBY = defined?(JRUBY_VERSION)
|
9
|
-
IRONRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE ==
|
9
|
+
IRONRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby'
|
10
10
|
WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
11
11
|
OS_X = RbConfig::CONFIG['host_os'] =~ /darwin/
|
12
12
|
WINDOWS_MRI = WINDOWS && !JRUBY && !IRONRUBY
|
@@ -18,7 +18,7 @@ module Lucid
|
|
18
18
|
class << self
|
19
19
|
attr_accessor :use_full_backtrace
|
20
20
|
|
21
|
-
def file_mode(m, encoding=
|
21
|
+
def file_mode(m, encoding='UTF-8')
|
22
22
|
"#{m}:#{encoding}"
|
23
23
|
end
|
24
24
|
end
|
data/lib/lucid/runtime/facade.rb
CHANGED
@@ -4,7 +4,7 @@ module Lucid
|
|
4
4
|
class Runtime
|
5
5
|
# This is what a programming language will consider to be a runtime.
|
6
6
|
#
|
7
|
-
# It's a thin class that directs the
|
7
|
+
# It's a thin class that directs the specific methods needed by the
|
8
8
|
# programming languages to the right place.
|
9
9
|
class Facade
|
10
10
|
extend Forwardable
|
@@ -25,21 +25,20 @@ module Lucid
|
|
25
25
|
:invoke,
|
26
26
|
:load_code_language
|
27
27
|
|
28
|
-
# Returns a Lucid::AST::Table
|
29
|
-
# be a String:
|
28
|
+
# Returns a Lucid::AST::Table which can either be a String:
|
30
29
|
#
|
31
30
|
# table(%{
|
32
|
-
# |
|
33
|
-
# |
|
34
|
-
# |
|
31
|
+
# | study | phase |
|
32
|
+
# | Test-01 | I |
|
33
|
+
# | Test-02 | II |
|
35
34
|
# })
|
36
35
|
#
|
37
36
|
# or a 2D Array:
|
38
37
|
#
|
39
38
|
# table([
|
40
|
-
# %w{
|
41
|
-
# %w{
|
42
|
-
# %w{
|
39
|
+
# %w{ study phase },
|
40
|
+
# %w{ Test-01 I },
|
41
|
+
# %w{ Test-02 II }
|
43
42
|
# ])
|
44
43
|
#
|
45
44
|
def table(text_or_table, file=nil, line_offset=0)
|
@@ -50,8 +49,7 @@ module Lucid
|
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
|
-
# Returns AST::DocString
|
54
|
-
#
|
52
|
+
# Returns AST::DocString
|
55
53
|
def doc_string(string_without_triple_quotes, content_type='', line_offset=0)
|
56
54
|
AST::DocString.new(string_without_triple_quotes,content_type)
|
57
55
|
end
|
@@ -44,8 +44,8 @@ module Lucid
|
|
44
44
|
# Invokes a series of steps +steps_text+. Example:
|
45
45
|
#
|
46
46
|
# invoke(%Q{
|
47
|
-
# Given
|
48
|
-
# Then
|
47
|
+
# Given lucid exists
|
48
|
+
# Then test specs can be executed
|
49
49
|
# })
|
50
50
|
def invoke_steps(steps_text, i18n, file_colon_line)
|
51
51
|
file, line = file_colon_line.split(':')
|
@@ -55,7 +55,6 @@ module Lucid
|
|
55
55
|
|
56
56
|
def invoke(step_name, multiline_argument=nil)
|
57
57
|
multiline_argument = Lucid::AST::MultilineArgument.from(multiline_argument)
|
58
|
-
# It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way.
|
59
58
|
begin
|
60
59
|
step_match(step_name).invoke(multiline_argument)
|
61
60
|
rescue Exception => e
|
data/lib/lucid/spec_file.rb
CHANGED
@@ -6,7 +6,7 @@ require 'gherkin/parser/parser'
|
|
6
6
|
module Lucid
|
7
7
|
class SpecFile
|
8
8
|
SPEC_PATTERN = /^([\w\W]*?):([\d:]+)$/ #:nodoc:
|
9
|
-
DEFAULT_ENCODING =
|
9
|
+
DEFAULT_ENCODING = 'UTF-8' #:nodoc:
|
10
10
|
NON_EXEC_PATTERN = /^\s*#|^\s*$/ #:nodoc:
|
11
11
|
ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/ #:nodoc:
|
12
12
|
|
@@ -74,8 +74,6 @@ module Lucid
|
|
74
74
|
STDOUT.puts ["\nYou don't have a 'specs' directory. This is the default specification",
|
75
75
|
"directory that Lucid will use if one is not specified. So either create",
|
76
76
|
"that directory or specify where your test repository is located.\n\n"].join("\n")
|
77
|
-
#e.message << "."
|
78
|
-
raise e
|
79
77
|
else
|
80
78
|
STDOUT.puts ["\nThere is no '#{@path}' directory. Since that is what you specified as",
|
81
79
|
"your spec repository, this directory must be present."].join("\n")
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module Lucid
|
4
|
+
module Formatter
|
5
|
+
describe ANSIColor do
|
6
|
+
include ANSIColor
|
7
|
+
|
8
|
+
it 'should wrap passed_param with bold green and reset to green' do
|
9
|
+
passed_param('test').should == "\e[32m\e[1mtest\e[0m\e[0m\e[32m"
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should wrap passed in green' do
|
13
|
+
passed('test').should == "\e[32mtest\e[0m"
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not reset passed if there are no arguments' do
|
17
|
+
passed.should == "\e[32m"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should wrap comments in grey' do
|
21
|
+
comment('test').should == "\e[90mtest\e[0m"
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not generate ansi codes when colors are disabled' do
|
25
|
+
::Lucid::Term::ANSIColor.coloring = false
|
26
|
+
passed('test').should == 'test'
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/spec/lucid/app_spec.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lucid/tdl_builder'
|
3
|
+
require 'gherkin/formatter/model'
|
2
4
|
|
3
5
|
module Lucid
|
4
6
|
module CLI
|
5
7
|
describe App do
|
6
|
-
|
8
|
+
|
7
9
|
let(:args) { [] }
|
8
10
|
let(:stdin) { StringIO.new }
|
9
11
|
let(:stdout) { StringIO.new }
|
10
12
|
let(:stderr) { StringIO.new }
|
11
13
|
let(:kernel) { double(:kernel) }
|
12
14
|
subject { App.new(args, stdin, stdout, stderr, kernel) }
|
13
|
-
|
15
|
+
|
14
16
|
describe 'start' do
|
15
17
|
context 'passed a runtime' do
|
16
18
|
let(:runtime) { double('runtime').as_null_object }
|
17
19
|
|
18
20
|
def do_start
|
19
|
-
subject.start(runtime)
|
21
|
+
subject.start!(runtime)
|
20
22
|
end
|
21
23
|
|
22
24
|
it 'configures the runtime' do
|
@@ -35,6 +37,73 @@ module Lucid
|
|
35
37
|
do_start
|
36
38
|
end
|
37
39
|
end
|
40
|
+
|
41
|
+
context 'execution is interrupted' do
|
42
|
+
after do
|
43
|
+
Lucid.wants_to_quit = false
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should register as a failure' do
|
47
|
+
results = double('results', :failure? => false)
|
48
|
+
runtime = Runtime.any_instance
|
49
|
+
runtime.stub(:run)
|
50
|
+
runtime.stub(:results).and_return(results)
|
51
|
+
|
52
|
+
Lucid.wants_to_quit = true
|
53
|
+
kernel.should_receive(:exit).with(1)
|
54
|
+
subject.start!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'verbose execution' do
|
60
|
+
before(:each) do
|
61
|
+
b = Lucid::Parser::TDLBuilder.new('specs/test.spec')
|
62
|
+
b.feature(Gherkin::Formatter::Model::Feature.new([], [], 'Feature', 'Testing', '', 99, ''))
|
63
|
+
b.language = double
|
64
|
+
@empty_feature = b.result
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should show the spec files that were parsed' do
|
68
|
+
cli = App.new(%w{--verbose test.spec}, stdin, stdout, stderr, kernel)
|
69
|
+
cli.stub(:require)
|
70
|
+
|
71
|
+
Lucid::SpecFile.stub(:new).and_return(double('spec file', :parse => @empty_feature))
|
72
|
+
kernel.should_receive(:exit).with(0)
|
73
|
+
|
74
|
+
cli.start!
|
75
|
+
|
76
|
+
stdout.string.should include('test.spec')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '--format with a formatter' do
|
81
|
+
it 'should fail if it cannot resolve a Formatter class' do
|
82
|
+
cli = App.new(%w{--format ZooModule::MonkeyFormatterClass}, stdin, stdout, stderr, kernel)
|
83
|
+
mock_module = double('module')
|
84
|
+
Object.stub(:const_defined?).and_return(true)
|
85
|
+
mock_module.stub(:const_defined?).and_return(true)
|
86
|
+
|
87
|
+
f = double('formatter').as_null_object
|
88
|
+
|
89
|
+
Object.should_receive(:const_get).with('ZooModule', false).and_return(mock_module)
|
90
|
+
mock_module.should_receive(:const_get).with('MonkeyFormatterClass', false).and_return(double('formatter class', :new => f))
|
91
|
+
|
92
|
+
kernel.should_receive(:exit).with(1)
|
93
|
+
cli.start!
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'handling exceptions' do
|
98
|
+
[ProfilesNotDefinedError, YmlLoadError, ProfileNotFound].each do |exception_class|
|
99
|
+
it "rescues #{exception_class}, prints the message to the error stream" do
|
100
|
+
Configuration.stub(:new).and_return(configuration = double('configuration'))
|
101
|
+
configuration.stub(:parse).and_raise(exception_class.new('error message'))
|
102
|
+
|
103
|
+
subject.start!
|
104
|
+
stderr.string.should == "error message\n"
|
105
|
+
end
|
106
|
+
end
|
38
107
|
end
|
39
108
|
|
40
109
|
end
|