greenpepper-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/greenpepperize +71 -0
- data/bin/greenpepperrails +33 -0
- data/bin/greenpepperruby +15 -0
- data/data/greenpepper.rake +37 -0
- data/data/helper.rb +32 -0
- data/data/tags +6 -0
- data/lib/greenpepper/argumentparser.rb +161 -0
- data/lib/greenpepper/common/loadpath.rb +7 -0
- data/lib/greenpepper/context/htmlcontext.rb +26 -0
- data/lib/greenpepper/converter.rb +347 -0
- data/lib/greenpepper/core.rb +152 -0
- data/lib/greenpepper/example/collectionexample.rb +305 -0
- data/lib/greenpepper/example/dowithexample.rb +192 -0
- data/lib/greenpepper/example/exampleheader.rb +41 -0
- data/lib/greenpepper/example/examplewithfixture.rb +73 -0
- data/lib/greenpepper/example/executionresults.rb +160 -0
- data/lib/greenpepper/example/fieldaccessor.rb +36 -0
- data/lib/greenpepper/example/freetextexample.rb +51 -0
- data/lib/greenpepper/example/importexample.rb +39 -0
- data/lib/greenpepper/example/nameresolver.rb +69 -0
- data/lib/greenpepper/example/ruleforexample.rb +117 -0
- data/lib/greenpepper/example/setupexample.rb +79 -0
- data/lib/greenpepper/example/silentexample.rb +14 -0
- data/lib/greenpepper/example/unknownexample.rb +17 -0
- data/lib/greenpepper/exception/greenpepperexception.rb +57 -0
- data/lib/greenpepper/executionunit.rb +39 -0
- data/lib/greenpepper/factory/collectionexamplefactory.rb +59 -0
- data/lib/greenpepper/factory/dowithexamplefactory.rb +71 -0
- data/lib/greenpepper/factory/examplefactory.rb +14 -0
- data/lib/greenpepper/factory/freetextexamplefactory.rb +29 -0
- data/lib/greenpepper/factory/htmlexamplefactory.rb +49 -0
- data/lib/greenpepper/factory/importexamplefactory.rb +27 -0
- data/lib/greenpepper/factory/ruleforexamplefactory.rb +46 -0
- data/lib/greenpepper/factory/setupexamplefactory.rb +31 -0
- data/lib/greenpepper/factory/silentexamplefactory.rb +21 -0
- data/lib/greenpepper/factory/unknownexamplefactory.rb +16 -0
- data/lib/greenpepper/freetext.rb +164 -0
- data/lib/greenpepper/grammar/array.treetop +51 -0
- data/lib/greenpepper/grammar/arrayparser.rb +14 -0
- data/lib/greenpepper/greenpepperconfig.rb +19 -0
- data/lib/greenpepper/greenpeppertask.rb +60 -0
- data/lib/greenpepper/logger.rb +45 -0
- data/lib/greenpepper/parser/freetextparser.rb +96 -0
- data/lib/greenpepper/parser/htmlparser.rb +70 -0
- data/lib/greenpepper/parser/scenario.rb +25 -0
- data/lib/greenpepper/parser/table.rb +37 -0
- data/lib/greenpepper/parser/wikiparser.rb +26 -0
- data/lib/greenpepper/pass/freetextpass.rb +24 -0
- data/lib/greenpepper/pass/greenpepperpass.rb +92 -0
- data/lib/greenpepper/pass/tablepass.rb +38 -0
- data/lib/greenpepper/railsargumentparser.rb +46 -0
- data/lib/greenpepper/redpeppertask.rb +89 -0
- data/lib/greenpepper/repository/atlassianrepository.rb +100 -0
- data/lib/greenpepper/writer/consolewriter.rb +21 -0
- data/lib/greenpepper/writer/freetextresult.rb +233 -0
- data/lib/greenpepper/writer/freetextwriter.rb +44 -0
- data/lib/greenpepper/writer/html.rb +14 -0
- data/lib/greenpepper/writer/htmldocwriter.rb +82 -0
- data/lib/greenpepper/writer/htmlresult.rb +192 -0
- data/lib/greenpepper/writer/htmlwriter.rb +112 -0
- data/lib/greenpepper/writer/output.rb +26 -0
- data/lib/greenpepper/writer/result.rb +35 -0
- data/lib/greenpepper/writer/xmlwriter.rb +32 -0
- data/test/coreseedstest.rb +39 -0
- data/test/greenpepper/argumentparsertest.rb +162 -0
- data/test/greenpepper/common/loadpathtest.rb +24 -0
- data/test/greenpepper/common/stattest.rb +186 -0
- data/test/greenpepper/convertertest.rb +371 -0
- data/test/greenpepper/coretest.rb +159 -0
- data/test/greenpepper/example/collectionexampletest.rb +484 -0
- data/test/greenpepper/example/dowithexampletest.rb +148 -0
- data/test/greenpepper/example/exampletest.rb +28 -0
- data/test/greenpepper/example/freetextexampletest.rb +151 -0
- data/test/greenpepper/example/importexampletest.rb +79 -0
- data/test/greenpepper/example/nameresolvertest.rb +56 -0
- data/test/greenpepper/example/ruleforexampletest.rb +225 -0
- data/test/greenpepper/example/setupexampletest.rb +140 -0
- data/test/greenpepper/example/silentexampletest.rb +17 -0
- data/test/greenpepper/example/unknownexampletest.rb +17 -0
- data/test/greenpepper/factory/collectionexamplefactorytest.rb +51 -0
- data/test/greenpepper/factory/dowithexamplefactorytest.rb +48 -0
- data/test/greenpepper/factory/examplefactorytest.rb +88 -0
- data/test/greenpepper/factory/freetextexamplefactorytest.rb +54 -0
- data/test/greenpepper/factory/importexamplefactorytest.rb +40 -0
- data/test/greenpepper/factory/ruleforexamplefactorytest.rb +55 -0
- data/test/greenpepper/factory/setupexamplefactorytest.rb +29 -0
- data/test/greenpepper/factory/silentexamplefactorytest.rb +38 -0
- data/test/greenpepper/freetexttest.rb +222 -0
- data/test/greenpepper/grammar/arrayparsertest.rb +45 -0
- data/test/greenpepper/loggertest.rb +26 -0
- data/test/greenpepper/parser/freetextparsertest.rb +124 -0
- data/test/greenpepper/parser/htmlparsertest.rb +77 -0
- data/test/greenpepper/parser/wikiparsertest.rb +21 -0
- data/test/greenpepper/pass/freetextpasstest.rb +54 -0
- data/test/greenpepper/pass/greenpepperpasstest.rb +47 -0
- data/test/greenpepper/pass/tablepasstest.rb +23 -0
- data/test/greenpepper/repository/atlassionrepositorytest.rb +85 -0
- data/test/greenpepper/writer/freetextwritertest.rb +301 -0
- data/test/greenpepper/writer/htmlcollectionwritertest.rb +145 -0
- data/test/greenpepper/writer/htmldowithwritertest.rb +87 -0
- data/test/greenpepper/writer/htmlruleforwritertest.rb +147 -0
- data/test/greenpepper/writer/htmlsetupwritertest.rb +107 -0
- data/test/greenpepper/writer/htmlstatresulttest.rb +118 -0
- data/test/greenpepper/writer/htmlwriterpositiontest.rb +53 -0
- data/test/greenpepper/writer/writertest.rb +33 -0
- data/test/greenpepper/writer/xmlwritertest.rb +34 -0
- data/test/integration/collectionexampleintegrationtest.rb +64 -0
- data/test/integration/errorhandlingintegrationtest.rb +68 -0
- data/test/integration/freetextexampleintegrationtest.rb +75 -0
- data/test/integration/greenpepperexecutableintegrationtest.rb +22 -0
- data/test/integration/importexampleintegrationtest.rb +41 -0
- data/test/integration/interpretationordertest.rb +48 -0
- data/test/integration/ruleforexampleintegrationtest.rb +102 -0
- data/test/integration/securityintegrationtest.rb +30 -0
- data/test/integration/setupexampleintegrationtest.rb +31 -0
- data/test/integration/silentexampleintegrationtest.rb +29 -0
- data/test/task/greenpeppertasktest.rb +96 -0
- data/test/task/redpeppertasktest.rb +120 -0
- data/vendor/accents.rb +85 -0
- metadata +234 -0
data/bin/greenpepperize
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Greenpepperize the folder by deploying rake tasks
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module GreenPepper
|
7
|
+
module Deploy
|
8
|
+
FOLDERS = ["greenpepper/specifications", "greenpepper/results",
|
9
|
+
"greenpepper/fixtures", "lib/tasks"]
|
10
|
+
|
11
|
+
def self.deploy
|
12
|
+
no_argument_error if ARGV.size != 1
|
13
|
+
deploy_path = File.expand_path ARGV[0]
|
14
|
+
inexistant_path_error if !File.exists? deploy_path
|
15
|
+
return if !confirm? deploy_path
|
16
|
+
|
17
|
+
gem_data_dir = File.join(File.dirname(__FILE__), '..', 'data')
|
18
|
+
|
19
|
+
# Create folders
|
20
|
+
FOLDERS.each{ |folder| FileUtils.mkdir_p File.join(deploy_path, folder)}
|
21
|
+
|
22
|
+
# Deploy files
|
23
|
+
FileUtils.cp File.join(gem_data_dir, 'greenpepper.rake'),
|
24
|
+
File.join(deploy_path, 'lib/tasks')
|
25
|
+
FileUtils.cp File.join(gem_data_dir, 'helper.rb'),
|
26
|
+
File.join(deploy_path, 'greenpepper')
|
27
|
+
|
28
|
+
print_info
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def self.confirm? path
|
33
|
+
puts "Do you want to deploy GreenPepper to \"#{path}\"? [y/n]"
|
34
|
+
begin
|
35
|
+
answer = STDIN.gets.chomp
|
36
|
+
end while answer != "y" && answer != "n"
|
37
|
+
answer == "y" ? true : false
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.no_argument_error
|
41
|
+
puts "Invalid argument specified."
|
42
|
+
print_usage
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.inexistant_path_error
|
47
|
+
puts "Inexistant path specified."
|
48
|
+
print_usage
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.print_usage
|
53
|
+
puts "usage: greenpepperize PATH"
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.print_info
|
57
|
+
puts "The directory has been greenpeperized.\n\n" +
|
58
|
+
"The following rake tasks are now available: \n" +
|
59
|
+
" gp:all [name=\"spec\"] - Download and run one or all" +
|
60
|
+
" specifications\n" +
|
61
|
+
" gp:download [name=\"spec\"] - Download one or all specifications" +
|
62
|
+
" from RedPepper server\n" +
|
63
|
+
" gp:run [name=\"spec\"] - Execute one or all specifications" +
|
64
|
+
" from greenpepper/specification\n\n" +
|
65
|
+
"The greenpepper/helper.rb file can be used to configure the tasks.\n"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
GreenPepper::Deploy.deploy
|
71
|
+
exit 0
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
author : S�bastien Boisclair (sebastien.boisclair2@usherbrooke.ca)
|
4
|
+
date: November 26, 2009
|
5
|
+
=end
|
6
|
+
|
7
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
8
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../bin")
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'greenpepper/railsargumentparser'
|
12
|
+
require 'greenpepper/freetext'
|
13
|
+
args = RailsArgumentParser.extract_args
|
14
|
+
|
15
|
+
if !args[:env]
|
16
|
+
RAILS_ENV = "test"
|
17
|
+
else
|
18
|
+
RAILS_ENV = args[:env]
|
19
|
+
end
|
20
|
+
|
21
|
+
if args[:rails]
|
22
|
+
require File.join(args[:rails], 'config/environment.rb')
|
23
|
+
requires = Dir.glob File.join(args[:rails], "greenpepper", "fixtures",
|
24
|
+
"*.rb")
|
25
|
+
requires.each { |req| require req }
|
26
|
+
end
|
27
|
+
|
28
|
+
index = ARGV.index('--help')
|
29
|
+
if ARGV.length == 0 || index != nil
|
30
|
+
RailsArgumentParser.usage
|
31
|
+
end
|
32
|
+
|
33
|
+
load 'greenpepperruby'
|
data/bin/greenpepperruby
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
author : Martin Provencher (martin.provencher@usherbrooke.ca)
|
4
|
+
date: March 11, 2009
|
5
|
+
=end
|
6
|
+
|
7
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
|
8
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../../common")
|
9
|
+
|
10
|
+
require 'greenpepper/core.rb'
|
11
|
+
|
12
|
+
core = GreenPepper::GreenPepperCore.new
|
13
|
+
ret = core.run ARGV
|
14
|
+
|
15
|
+
exit(ret) if ret.is_a? Fixnum
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Tasks to download and execute GreenPepper specifications against the Rails
|
2
|
+
# application. Tasks configuration file is located in greenpepper/helper.rb
|
3
|
+
require 'greenpepper/greenpeppertask'
|
4
|
+
require 'greenpepper/redpeppertask'
|
5
|
+
|
6
|
+
# Load the configuration file
|
7
|
+
load 'greenpepper/helper.rb'
|
8
|
+
|
9
|
+
# Global GreenPepper namespace
|
10
|
+
namespace :gp do
|
11
|
+
|
12
|
+
# Download and run all specifications
|
13
|
+
task :all do
|
14
|
+
Rake::Task["gp:download"].execute
|
15
|
+
Rake::Task["gp:run"].execute
|
16
|
+
end
|
17
|
+
|
18
|
+
# Download all the specifications hosted by the RedPepper server defined
|
19
|
+
# in the config file
|
20
|
+
GreenPepper::RedPepperTask.new(:download) do |t|
|
21
|
+
# Get the spec name, if any
|
22
|
+
t.spec_name = ENV['name']
|
23
|
+
end
|
24
|
+
|
25
|
+
# Execute all specifications in greenpepper/specifications
|
26
|
+
GreenPepper::GreenPepperTask.new(:run) do |t|
|
27
|
+
# Require Rails environment
|
28
|
+
require "config/environment"
|
29
|
+
|
30
|
+
# Require fixtures in greenpepper/fixtures
|
31
|
+
requires = Dir.glob File.join("greenpepper", "fixtures", "*.rb")
|
32
|
+
requires.each { |req| require req }
|
33
|
+
|
34
|
+
# Get the spec name, if any
|
35
|
+
t.spec_name = ENV['name'] + '.html'
|
36
|
+
end
|
37
|
+
end
|
data/data/helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# GreenPepper rake tasks configuration file. Change this file to customize
|
2
|
+
# the behavior of the gp:all, gp:download and gp:run tasks.
|
3
|
+
require 'greenpepper/greenpepperconfig'
|
4
|
+
|
5
|
+
# Include the freetext DSL.
|
6
|
+
require 'greenpepper/freetext'
|
7
|
+
|
8
|
+
GreenPepper::GreenPepperConfig.configure do |config|
|
9
|
+
|
10
|
+
### RedPepper ###
|
11
|
+
#################
|
12
|
+
# Defines the RedPepper server URL from which to fetch the specifications
|
13
|
+
config.server = "http://greenpepper.kicks-ass.org/server"
|
14
|
+
|
15
|
+
# The directory to save the downloaded specifications to.
|
16
|
+
# Default : "greenpepper/specifications"
|
17
|
+
#config.path = "path/specifications"
|
18
|
+
|
19
|
+
### Specification ###
|
20
|
+
#####################
|
21
|
+
# The directory from which to execute the specifications
|
22
|
+
# Default : "greenpepper/specifications"
|
23
|
+
#config.spec_dir = "/my/spec/dir"
|
24
|
+
|
25
|
+
# The execution result directory.
|
26
|
+
# Defaut : "greenpepper/results"
|
27
|
+
#config.result_dir = "path/results"
|
28
|
+
|
29
|
+
# The path of the GreenPepper core. If not specified, it searches for it in
|
30
|
+
# the ruby loadpath.
|
31
|
+
#config.greenpepper_path = "/my/core/path"
|
32
|
+
end
|
data/data/tags
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
2
|
+
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
3
|
+
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
4
|
+
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
5
|
+
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
6
|
+
!_TAG_PROGRAM_VERSION 5.7 //
|
@@ -0,0 +1,161 @@
|
|
1
|
+
=begin
|
2
|
+
author: Martin Provencher (martin.provencher@usherbrooke.ca)
|
3
|
+
date: March 24, 2008
|
4
|
+
=end
|
5
|
+
module GreenPepper
|
6
|
+
|
7
|
+
class ArgumentParser
|
8
|
+
|
9
|
+
attr_reader :execution_context, :writer_context
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
@execution_context = {:html_results_output => true,
|
13
|
+
:xml_output => false,
|
14
|
+
:console_output => "",
|
15
|
+
:repository => nil,
|
16
|
+
:load_path => Array.new,
|
17
|
+
:input_document => nil,
|
18
|
+
:output_document => nil}
|
19
|
+
|
20
|
+
@writer_context = {:no_exception_stack => false}
|
21
|
+
|
22
|
+
if args.empty?
|
23
|
+
@execution_context[:console_output] = ArgumentParser.usage
|
24
|
+
else
|
25
|
+
@parsed = parse_args args
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_args(argv)
|
30
|
+
argv = [argv] unless argv.is_a? Array
|
31
|
+
args = argv.dup
|
32
|
+
arg_regex = /^\s*-.+\s*/
|
33
|
+
return false if args.size < 1
|
34
|
+
|
35
|
+
while arg = args.shift
|
36
|
+
if arg =~ arg_regex
|
37
|
+
case arg
|
38
|
+
when "--no-html-results" #Not in doc
|
39
|
+
@execution_context[:html_results_output] = false
|
40
|
+
when "--no-exception-stack"
|
41
|
+
@writer_context[:no_exception_stack] = true
|
42
|
+
when "--help"
|
43
|
+
@execution_context[:console_output] = ArgumentParser.usage
|
44
|
+
return
|
45
|
+
when "--version"
|
46
|
+
@execution_context[:console_output] =
|
47
|
+
"#{$APP_NAME} version : #{$VERSION}"
|
48
|
+
return
|
49
|
+
when "--xml"
|
50
|
+
@execution_context[:xml_output] = true
|
51
|
+
@execution_context[:output_document] = args.shift unless
|
52
|
+
args[0] =~ arg_regex || args.size == 0
|
53
|
+
#Output to the specified output. If no specified output,
|
54
|
+
#outputting to INPUTFILENAME_output.xml
|
55
|
+
when "-r"
|
56
|
+
if args[0] =~ arg_regex || args.size == 0
|
57
|
+
@execution_context[:console_output] = ArgumentParser.usage
|
58
|
+
return
|
59
|
+
else
|
60
|
+
@execution_context[:repository] = args.shift
|
61
|
+
end
|
62
|
+
when "--loadpath"
|
63
|
+
if args[0] =~ arg_regex || args.size == 0
|
64
|
+
@execution_context[:console_output] = ArgumentParser.usage
|
65
|
+
return
|
66
|
+
else
|
67
|
+
while !(args[0] =~ arg_regex || args.size == 0)
|
68
|
+
@execution_context[:load_path] << args.shift
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
else
|
73
|
+
@execution_context[:console_output] =
|
74
|
+
"#{arg.to_s} option is not recognize\n#{ArgumentParser.usage}"
|
75
|
+
return
|
76
|
+
end
|
77
|
+
else
|
78
|
+
if @execution_context[:input_document].nil?
|
79
|
+
@execution_context[:input_document] = arg
|
80
|
+
elsif @execution_context[:output_document].nil?
|
81
|
+
@execution_context[:output_document] = arg
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if (@execution_context[:input_document].nil?)
|
87
|
+
@execution_context[:console_output] = ArgumentParser.usage
|
88
|
+
return
|
89
|
+
else
|
90
|
+
if(@execution_context[:output_document].nil?)
|
91
|
+
extension_name = File.extname @execution_context[:input_document]
|
92
|
+
base_name = File.basename @execution_context[:input_document]
|
93
|
+
base_name.gsub!(extension_name, "")
|
94
|
+
extension_name = '.xml' if @execution_context[:xml_output]
|
95
|
+
|
96
|
+
@execution_context[:output_document] =
|
97
|
+
"#{base_name}_output#{extension_name}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.usage
|
103
|
+
str = "Usage: ruby greenpepper.rb input_document "
|
104
|
+
str += "[ouput_document] [options]\n\n"
|
105
|
+
str += "--help Display the help.\n"
|
106
|
+
str += "--version Output version information.\n"
|
107
|
+
str += "-r CLASS;ARGS The url of the repository of the" +
|
108
|
+
str += " specifications.\n"
|
109
|
+
str += "--no-html-results This option will not print result in output.\n"
|
110
|
+
str += "--xml [output_document] Generate XML report (default is plain text)."
|
111
|
+
str += " If output_document is specified, the xml report will outputed"
|
112
|
+
str += " in the specified file.\n"
|
113
|
+
str += "--no-exception-stack Disable outputting of exception stack when"
|
114
|
+
str += " execution exception are raised.\n"
|
115
|
+
str += "--load_path path1 [pathX] List of path to include for execution."
|
116
|
+
str
|
117
|
+
end
|
118
|
+
|
119
|
+
=begin
|
120
|
+
This doc came from greenpeppersoftware.com ... this will be needed to fill self.usage
|
121
|
+
|
122
|
+
Usage: greenpepper [options] input [ouput]
|
123
|
+
Run the input specification and produce a report in output file or in directory specified by -o
|
124
|
+
|
125
|
+
Options:
|
126
|
+
Ignore :-l, --locale LANG Set application language (en, fr, ...)
|
127
|
+
#-f, --sud CLASS;ARGS Use CLASS as the system under development and instantiate it with ARGS
|
128
|
+
#-o DIRECTORY Produce reports in DIRECTORY (defaults to current directory)
|
129
|
+
#-r CLASS;ARGS Use CLASS as the document repository and instantiate it with ARGS (defaults to com.greenpepper.repository.FileSystemRepository)
|
130
|
+
#-s, --suite Run a suite rather than a single test (output must refer to a directory)
|
131
|
+
-t SECTIONS Filter input specification to only execute SECTIONS (comma separated list of sections)
|
132
|
+
-a ARGS Semicolon seperated list of assemblies fullName
|
133
|
+
|
134
|
+
Ignore : --selector CLASS Use CLASS as the interpreter selector (defaults to com.greenpepper.document.GreenPepperInterpreterSelector)
|
135
|
+
# --lazy Set greenpepper in lazy mode for document execution
|
136
|
+
# --xml Generate XML report (defaults to plain)
|
137
|
+
# --help Display this help and exit
|
138
|
+
# --version Output version information and exit
|
139
|
+
Don't implement for now : --debug Enable debug mode
|
140
|
+
# --stop Stop the execution of the specification on the first failure
|
141
|
+
|
142
|
+
When no option is given, GreenPepper defaults to the following rules:
|
143
|
+
|
144
|
+
* Input is a single specification, not a suite
|
145
|
+
* If output is not specified, reports are produced in the current directory
|
146
|
+
* Report is in plain format
|
147
|
+
* The operating system locale is used
|
148
|
+
Not in story * The input specification is not filtered
|
149
|
+
* The specification file must be located on the file system
|
150
|
+
* Fixtures are created using the default built-in mechanism
|
151
|
+
* Tables use GreenPepper formalism
|
152
|
+
* Lazy mode is disabled
|
153
|
+
* Debug mode is disabled
|
154
|
+
* Will not stop the execution on first failure
|
155
|
+
|
156
|
+
Any of the rules above can be overridden using command line switches.
|
157
|
+
|
158
|
+
=end
|
159
|
+
end
|
160
|
+
|
161
|
+
end #module GreenPepper
|
@@ -0,0 +1,26 @@
|
|
1
|
+
=begin
|
2
|
+
author: Martin Provencher (mprovencher86@gmail.com)
|
3
|
+
date: September 3, 2009
|
4
|
+
=end
|
5
|
+
|
6
|
+
module GreenPepper
|
7
|
+
|
8
|
+
class ExampleContext
|
9
|
+
attr_accessor :index
|
10
|
+
|
11
|
+
def initialize(index = 0)
|
12
|
+
@index = index
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class HtmlContext < ExampleContext
|
17
|
+
attr_accessor :nb_table, :first_table_index
|
18
|
+
|
19
|
+
def initialize(index = 0, first_table_index = 0, nb_table = 1)
|
20
|
+
super(index)
|
21
|
+
@first_table_index = first_table_index
|
22
|
+
@nb_table = nb_table
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end #module GreenPepper
|
@@ -0,0 +1,347 @@
|
|
1
|
+
=begin
|
2
|
+
authors: Simon Mathieu (simon.math@gmail.com)
|
3
|
+
Sebastien Boisclair (sebboisclair@gmail.com)
|
4
|
+
date: March 3, 2009
|
5
|
+
=end
|
6
|
+
module GreenPepper
|
7
|
+
|
8
|
+
require 'singleton'
|
9
|
+
require 'date'
|
10
|
+
require 'greenpepper/grammar/arrayparser'
|
11
|
+
|
12
|
+
class TypeConverter
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@converters = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def convert_string(string)
|
20
|
+
@converters.each { |type|
|
21
|
+
if type.can_parse? string
|
22
|
+
return type.convert.call(string)
|
23
|
+
end
|
24
|
+
}
|
25
|
+
string
|
26
|
+
end
|
27
|
+
|
28
|
+
def format_object(expected_string_format, object)
|
29
|
+
@converters.each { |type|
|
30
|
+
if type.can_parse? expected_string_format
|
31
|
+
return type.format.call(object, expected_string_format)
|
32
|
+
end
|
33
|
+
}
|
34
|
+
object.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
#Encapsulate all the type conversion logic for fixtures
|
38
|
+
def auto_convert_string(fixture, name, string)
|
39
|
+
parse_f = conversion_func name
|
40
|
+
if fixture.respond_to?(parse_f)
|
41
|
+
if string.is_a? Array
|
42
|
+
return fixture.send(parse_f, *string)
|
43
|
+
else
|
44
|
+
return fixture.send(parse_f, string)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
if string.is_a? Array
|
48
|
+
return string.collect{|s| convert_string s}
|
49
|
+
else
|
50
|
+
return convert_string(string)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def auto_convert_object(fixture, name, expected_format, object)
|
56
|
+
format_f = format_func name
|
57
|
+
if fixture.respond_to?(format_f)
|
58
|
+
return fixture.send(format_f, object)
|
59
|
+
else
|
60
|
+
return format_object(expected_format, object)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_conversion_type(type)
|
65
|
+
@converters << type
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def conversion_func(name)
|
70
|
+
("parse_" + NameResolver.format_column_name(name)).to_sym
|
71
|
+
end
|
72
|
+
|
73
|
+
def format_func(name)
|
74
|
+
("format_" + NameResolver.format_column_name(name)).to_sym
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class TypeBase
|
79
|
+
def TypeBase.inherited(subclass)
|
80
|
+
TypeConverter.instance.add_conversion_type subclass
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.can_parse?(str)
|
84
|
+
regex === str
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.format
|
88
|
+
Proc.new{|object,expected_format| object.to_s}
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
class ErrorType < TypeBase
|
94
|
+
|
95
|
+
def self.regex
|
96
|
+
/^[\s]*error[\s]*$/i
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.convert
|
100
|
+
Proc.new{|s| Exception.new}
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.format
|
104
|
+
Proc.new{|object, expected_format|
|
105
|
+
if object.is_a? Exception
|
106
|
+
expected_format
|
107
|
+
else
|
108
|
+
object.to_s
|
109
|
+
end
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class IntType < TypeBase
|
115
|
+
|
116
|
+
def self.regex
|
117
|
+
/^\s*-?[0-9]+\s*$/
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.convert
|
121
|
+
Proc.new{|s| s.to_i}
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
class FloatType < TypeBase
|
127
|
+
|
128
|
+
def self.regex
|
129
|
+
/^\s*-?[0-9]*\.[0-9]+\s*$/
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.convert
|
133
|
+
Proc.new{|s| s.to_f}
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.format
|
137
|
+
Proc.new{ |b, expected_format|
|
138
|
+
if expected_format.match /^.[0-9]+$/
|
139
|
+
b.to_s[1..-1]
|
140
|
+
else
|
141
|
+
b.to_s
|
142
|
+
end
|
143
|
+
}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class BoolType < TypeBase
|
148
|
+
def self.regex
|
149
|
+
/^\s*(true|false|yes|no)\s*$/i
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.convert
|
153
|
+
Proc.new{ |s|
|
154
|
+
(/true|yes/i =~ s) != nil
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.format
|
159
|
+
Proc.new{ |b,expected_format|
|
160
|
+
yes = "yes"
|
161
|
+
no = "no"
|
162
|
+
|
163
|
+
case expected_format
|
164
|
+
when /^True|False$/
|
165
|
+
b.to_s.capitalize
|
166
|
+
when /^yes|no$/
|
167
|
+
b ? yes : no
|
168
|
+
when /^Yes|No$/
|
169
|
+
b ? yes.capitalize : no.capitalize
|
170
|
+
else
|
171
|
+
b.to_s
|
172
|
+
end
|
173
|
+
}
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class BlankStringType < TypeBase
|
178
|
+
def self.regex
|
179
|
+
/^\s*blank\s*$/i
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.convert
|
183
|
+
Proc.new{ |s|
|
184
|
+
""
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.format
|
189
|
+
Proc.new{ |s,expected_format|
|
190
|
+
expected_format
|
191
|
+
}
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class NilType < TypeBase
|
196
|
+
def self.regex
|
197
|
+
/^\s*(nil|null|none|nothing|\s*)\s*$/i
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.convert
|
201
|
+
Proc.new{ |s|
|
202
|
+
nil
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.format
|
207
|
+
Proc.new{ |n,expected_format|
|
208
|
+
#The server return some weird unicode char when a cell is
|
209
|
+
#empty and since ruby 1.8 doesn't like unicode in regex, we
|
210
|
+
#have to do this ugly path here.
|
211
|
+
if /^\s*$/ === expected_format || expected_format[0] == 194
|
212
|
+
n.to_s
|
213
|
+
else
|
214
|
+
expected_format
|
215
|
+
end
|
216
|
+
}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
class IsoDate < TypeBase
|
221
|
+
def self.regex
|
222
|
+
/^\s*(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])(\D?([01]\d|2[0-3])\D?([0-5]\d)\D?([0-5]\d)?\D?(\d{3})?([zZ]|([\+-])([01]\d|2[0-3])\D?([0-5]\d)?)?)?\s*$/
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.convert
|
226
|
+
Proc.new{ |s|
|
227
|
+
begin
|
228
|
+
DateTime.parse(s)
|
229
|
+
rescue ArgumentError => exception
|
230
|
+
raise(GreenPepperTypeError.new,"Can't parse date #{s}")
|
231
|
+
end
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.format
|
236
|
+
Proc.new{ |d,expected_format|
|
237
|
+
date_base_slash = d.year.to_s.rjust(4,"0") + "-" +
|
238
|
+
d.month.to_s.rjust(2,"0") + "-" + d.day.to_s.rjust(2,"0")
|
239
|
+
date_base_frontslash = d.year.to_s.rjust(4,"0") + "/" +
|
240
|
+
d.month.to_s.rjust(2,"0") + "/" + d.day.to_s.rjust(2,"0")
|
241
|
+
date_hour_min = d.hour.to_s.rjust(2,"0") + ":" +
|
242
|
+
d.min.to_s.rjust(2,"0")
|
243
|
+
date_extension = "Z"
|
244
|
+
|
245
|
+
case expected_format
|
246
|
+
when /^(\d+)\-(\d+)\-(\d+)\w(\d+):(\d+)\w$/
|
247
|
+
date_base_slash + "T" + date_hour_min + date_extension
|
248
|
+
when /^(\d+)\-(\d+)\-(\d+)\s(\d+):(\d+)$/
|
249
|
+
date_base_slash + " " + date_hour_min
|
250
|
+
when /^(\d+)\-(\d+)\-(\d+)\s(\d+):(\d+)\w$/
|
251
|
+
date_base_slash + " " + date_hour_min + date_extension
|
252
|
+
when /^(\d+)\-(\d+)\-(\d+)$/
|
253
|
+
date_base_slash
|
254
|
+
when /^(\d+)\/(\d+)\/(\d+)\w(\d+):(\d+)\w$/
|
255
|
+
date_base_frontslash + "T" + date_hour_min + date_extension
|
256
|
+
when /^(\d+)\/(\d+)\/(\d+)\s(\d+):(\d+)$/
|
257
|
+
date_base_frontslash + " " + date_hour_min
|
258
|
+
when /^(\d+)\/(\d+)\/(\d+)\s(\d+):(\d+)\w$/
|
259
|
+
date_base_frontslash + " " + date_hour_min + date_extension
|
260
|
+
when /^(\d+)\/(\d+)\/(\d+)$/
|
261
|
+
date_base_frontslash
|
262
|
+
else
|
263
|
+
d.to_s
|
264
|
+
end
|
265
|
+
}
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class ExplicitStringType < TypeBase
|
270
|
+
def self.regex
|
271
|
+
/^\s*["'].*["']\s*$/
|
272
|
+
end
|
273
|
+
|
274
|
+
def self.convert
|
275
|
+
Proc.new{ |s| s[1..-2] }
|
276
|
+
end
|
277
|
+
|
278
|
+
def self.format
|
279
|
+
Proc.new{ |str,expected_format|
|
280
|
+
if (expected_format.index("'") == 0)
|
281
|
+
"'" + str.to_s + "'"
|
282
|
+
else
|
283
|
+
"\"" + str.to_s + "\""
|
284
|
+
end
|
285
|
+
}
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
class EmptyArrayType < TypeBase
|
290
|
+
def self.regex
|
291
|
+
/^\s*empty\s*$/i
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.convert
|
295
|
+
Proc.new{ |s| [] }
|
296
|
+
end
|
297
|
+
|
298
|
+
def self.format
|
299
|
+
Proc.new{ |a,expected_format|
|
300
|
+
expected_format
|
301
|
+
}
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
class ArrayType < TypeBase
|
306
|
+
def self.regex
|
307
|
+
/^\s*(\[([^,]*,?)*\])|(([^,]+,)+[^,]+,?)\s*$/
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.convert
|
311
|
+
Proc.new{ |s|
|
312
|
+
data = ArrayGrammarModule.parse(s)
|
313
|
+
|
314
|
+
data.collect{ |x|
|
315
|
+
TypeConverter.instance.convert_string x
|
316
|
+
}
|
317
|
+
}
|
318
|
+
end
|
319
|
+
|
320
|
+
def self.format
|
321
|
+
Proc.new{ |a,expected_format|
|
322
|
+
if a != nil
|
323
|
+
expected = ArrayGrammarModule.parse(expected_format)
|
324
|
+
|
325
|
+
a.each_index{|i|
|
326
|
+
a[i] = TypeConverter.instance.format_object expected[i],
|
327
|
+
a[i]
|
328
|
+
}
|
329
|
+
|
330
|
+
case expected_format
|
331
|
+
when /^\[([^,]*,)*\]$/
|
332
|
+
"[" + a.join(",") + ",]"
|
333
|
+
when /^\[([^,]*,?)*\]$/
|
334
|
+
"[" + a.join(",") + "]"
|
335
|
+
when /^([^,]+,)+[^,]+,$/
|
336
|
+
a.join(",") + ","
|
337
|
+
else
|
338
|
+
a.join(",")
|
339
|
+
end
|
340
|
+
else
|
341
|
+
""
|
342
|
+
end
|
343
|
+
}
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
end #module GreenPepper
|