cuke4php 0.9.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.
- data/.document +3 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +54 -0
- data/Rakefile +75 -0
- data/VERSION +1 -0
- data/bin/cuke4php +22 -0
- data/cucumber.yml +1 -0
- data/cuke4php.gemspec +92 -0
- data/features/Cuke4Php.feature +42 -0
- data/features/step_definitions/Cuke4Php.wire +4 -0
- data/features/step_definitions/TestSteps.php +88 -0
- data/features/step_definitions/WireSteps.php +87 -0
- data/features/support/Env.php +13 -0
- data/lib/Cucumber.php +14 -0
- data/lib/CucumberScenario.php +122 -0
- data/lib/CucumberSteps.php +79 -0
- data/lib/Cuke4Php.php +242 -0
- data/php_bin/cuke4php_server +20 -0
- data/tests/lib/CucumberScenarioTest.php +161 -0
- data/tests/lib/Cuke4PhpTest.php +117 -0
- metadata +190 -0
data/.document
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010-2011 Kevin Olbrich, Alessandro Dal Grande
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
cuke4php
|
2
|
+
========
|
3
|
+
|
4
|
+
This project implements the cucumber wire protocol for PHP projects.
|
5
|
+
Information about the wire protocol: http://wiki.github.com/aslakhellesoy/cucumber/wire-protocol
|
6
|
+
|
7
|
+
Using this protocol it is possible to directly interact with PHP code at any level without the need for a web server. To accomplish this, when cucumber is running against a directory containing feature files and it cannot resolve a particular step definition, it will ask a known wire server (as defined in a .wire file) to interpret and run those steps.
|
8
|
+
|
9
|
+
Install
|
10
|
+
-------
|
11
|
+
To install Cuke4Php, follow these steps:
|
12
|
+
|
13
|
+
* clone
|
14
|
+
* install dependencies with bundler
|
15
|
+
* run rake build
|
16
|
+
* install gem under pkg/ folder
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----
|
20
|
+
* run 'cuke4php path/to/features' from the command line
|
21
|
+
* make sure your cucumber features has a 'Cuke4Php.wire' file containing the appropriate information (copy the one in cuke4php/features/step_definitions)
|
22
|
+
* you can write both Ruby and PHP steps
|
23
|
+
* you should load phpunit from a file in step_definitions/support/
|
24
|
+
|
25
|
+
Roadmap
|
26
|
+
-------
|
27
|
+
|
28
|
+
### bin/cuke4php
|
29
|
+
|
30
|
+
* support an option like 'cuke4php --init' which will generate the directory structure and support files necessary to use cuke4php with a php project.
|
31
|
+
* autodetect an available port and then use it to run the cuke4php server pass this on to cucumber by setting an environment variable (requires a modification to cucumber)
|
32
|
+
|
33
|
+
### Rakefile
|
34
|
+
|
35
|
+
* once the patch for erb templating in .wire files is released, we should set a minimum version for it
|
36
|
+
|
37
|
+
Dependencies
|
38
|
+
------------
|
39
|
+
* PHPUnit >= 3.0 (see http://www.phpunit.de/)
|
40
|
+
|
41
|
+
Goals
|
42
|
+
-----
|
43
|
+
This project utilizes PHPUnit because it has a robust set of assertions, has good mocking, and is widely used. This will facilitate adoption by developers who are already familiar with it.
|
44
|
+
|
45
|
+
This project was developed against the 5.2.x versions of PHP, to ensure compatibility with older PHP projects.
|
46
|
+
|
47
|
+
Support
|
48
|
+
-------
|
49
|
+
Support for this project was provided by iContact, inc. (http://www.icontact.com)
|
50
|
+
|
51
|
+
Contributors
|
52
|
+
------------
|
53
|
+
Kevin Olbrich, Ph.D. (kevin.olbrich+cuke4php@gmail.com)
|
54
|
+
Alessandro Dal Grande (aledelgrande@gmail.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "cuke4php"
|
8
|
+
gem.summary = %Q{Implementation of the Cucumber wire protocol for PHP projects}
|
9
|
+
gem.description = %Q{Using this protocol it is possible to directly interact with PHP code at any level without the need for a web server. To accomplish this, when cucumber is running against a directory containing feature files and it cannot resolve a particular step definition, it will ask a known wire server (as defined in a .wire file) to interpret and run those steps.}
|
10
|
+
gem.authors = ["Kevin Olbrich", "Alessandro Dal Grande"]
|
11
|
+
gem.email = ["kevin.olbrich+cuke4php@gmail.com", "aledalgrande@gmail.com"]
|
12
|
+
gem.homepage = "http://github.com/olbrich/cuke4php"
|
13
|
+
gem.executables = 'cuke4php'
|
14
|
+
gem.add_dependency('cucumber')
|
15
|
+
# TODO: once the patch for erb templating in the .wire files is released, we should set a minimum version for it
|
16
|
+
gem.add_development_dependency('bundler')
|
17
|
+
gem.add_development_dependency('jeweler')
|
18
|
+
gem.files.exclude 'phpdoc'
|
19
|
+
gem.has_rdoc = false
|
20
|
+
gem.requirements << "PHP 5.2+"
|
21
|
+
gem.requirements << "PHPUnit 3.0+"
|
22
|
+
gem.post_install_message =<<eos
|
23
|
+
********************************************************************************
|
24
|
+
|
25
|
+
Please install PHPUnit >= 3.0 if you've not already done it!
|
26
|
+
|
27
|
+
Add PEAR channels:
|
28
|
+
pear channel-discover pear.phpunit.de
|
29
|
+
pear channel-discover components.ez.no
|
30
|
+
pear channel-discover pear.symfony-project.com
|
31
|
+
|
32
|
+
Install PHPUnit:
|
33
|
+
pear install phpunit/PHPUnit
|
34
|
+
|
35
|
+
********************************************************************************
|
36
|
+
eos
|
37
|
+
end
|
38
|
+
Jeweler::GemcutterTasks.new
|
39
|
+
rescue LoadError
|
40
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'cucumber/rake/task'
|
44
|
+
#Cucumber::Rake::Task.new(:features)
|
45
|
+
|
46
|
+
task :default => [:features, :phpunit]
|
47
|
+
|
48
|
+
namespace :server do
|
49
|
+
|
50
|
+
desc "start cuke4php server"
|
51
|
+
task :start do
|
52
|
+
sh "#{File.dirname(__FILE__)}/php_bin/cuke4php #{ARGV.first ? ARGV.first : 'features'} &"
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "stop cuke4php server"
|
56
|
+
task :stop do
|
57
|
+
sh "echo 'quit' | nc #{ENV['SERVER'] || 'localhost'} #{ENV['PORT'] || 16816}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Run Cucumber features for Cuke4php"
|
62
|
+
task :features do
|
63
|
+
sh "bin/cuke4php -p #{ENV['PROFILE'] || 'default'} features"
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Generate PhpDocs -- requires PhpDocumentor"
|
67
|
+
task :phpdoc do
|
68
|
+
sh "rm -rf phpdoc/"
|
69
|
+
sh "phpdoc -f *.php -d ./lib -t phpdoc/ --title Cuke4Php -dn Cuke4Php -dc Cuke4Php -it @one,@two,@wire"
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Run PHPUnit tests"
|
73
|
+
task :phpunit do
|
74
|
+
sh "phpunit tests"
|
75
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.0
|
data/bin/cuke4php
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# TODO: support an option like 'cuke4php --init' which will generate the directory structure and support files necessary to use cuke4php with a php project.
|
4
|
+
|
5
|
+
# TODO: autodetect an available port and then use it to run the cuke4php server pass this on to cucumber by setting an environment variable (requires a modification to cucumber)
|
6
|
+
# see https://github.com/olbrich/cucumber/commit/0c11d206e08e8d5647e03bf78be93723d59529ef
|
7
|
+
|
8
|
+
# Note that changing the port number currently requires updating the Cuke4Php.wire file in your project's step_definitions
|
9
|
+
# or cucumber will look for the cuke4php server on the wrong port.
|
10
|
+
CUKE4PHP_PORT=ENV['CUKE4PHP_PORT'] || 16816
|
11
|
+
|
12
|
+
server = fork do
|
13
|
+
exec "#{File.dirname(__FILE__)}/../php_bin/cuke4php_server -p #{CUKE4PHP_PORT} #{ARGV.last ? ARGV.last : 'features'}"
|
14
|
+
end
|
15
|
+
#Process.detach(pid)
|
16
|
+
sleep 1
|
17
|
+
cucumber = fork do
|
18
|
+
exec "CUKE4PHP_PORT=#{CUKE4PHP_PORT} && cucumber #{ARGV.join(' ')}" #"; echo 'quit' | nc localhost #{CUKE4PHP_PORT}"
|
19
|
+
end
|
20
|
+
pid, status = Process.wait2(cucumber,0)
|
21
|
+
Process.kill("TERM",server)
|
22
|
+
exit status.exitstatus
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --format pretty
|
data/cuke4php.gemspec
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{cuke4php}
|
8
|
+
s.version = "0.9.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kevin Olbrich", "Alessandro Dal Grande"]
|
12
|
+
s.date = %q{2011-01-27}
|
13
|
+
s.default_executable = %q{cuke4php}
|
14
|
+
s.description = %q{Using this protocol it is possible to directly interact with PHP code at any level without the need for a web server. To accomplish this, when cucumber is running against a directory containing feature files and it cannot resolve a particular step definition, it will ask a known wire server (as defined in a .wire file) to interpret and run those steps.}
|
15
|
+
s.email = ["kevin.olbrich+cuke4php@gmail.com", "aledalgrande@gmail.com"]
|
16
|
+
s.executables = ["cuke4php"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.md"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"bin/cuke4php",
|
29
|
+
"cucumber.yml",
|
30
|
+
"cuke4php.gemspec",
|
31
|
+
"features/Cuke4Php.feature",
|
32
|
+
"features/step_definitions/Cuke4Php.wire",
|
33
|
+
"features/step_definitions/TestSteps.php",
|
34
|
+
"features/step_definitions/WireSteps.php",
|
35
|
+
"features/support/Env.php",
|
36
|
+
"lib/Cucumber.php",
|
37
|
+
"lib/CucumberScenario.php",
|
38
|
+
"lib/CucumberSteps.php",
|
39
|
+
"lib/Cuke4Php.php",
|
40
|
+
"php_bin/cuke4php_server",
|
41
|
+
"tests/lib/CucumberScenarioTest.php",
|
42
|
+
"tests/lib/Cuke4PhpTest.php"
|
43
|
+
]
|
44
|
+
s.homepage = %q{http://github.com/olbrich/cuke4php}
|
45
|
+
s.post_install_message = %q{********************************************************************************
|
46
|
+
|
47
|
+
Please install PHPUnit >= 3.0 if you've not already done it!
|
48
|
+
|
49
|
+
Add PEAR channels:
|
50
|
+
pear channel-discover pear.phpunit.de
|
51
|
+
pear channel-discover components.ez.no
|
52
|
+
pear channel-discover pear.symfony-project.com
|
53
|
+
|
54
|
+
Install PHPUnit:
|
55
|
+
pear install phpunit/PHPUnit
|
56
|
+
|
57
|
+
********************************************************************************
|
58
|
+
}
|
59
|
+
s.require_paths = ["lib"]
|
60
|
+
s.requirements = ["PHP 5.2+", "PHPUnit 3.0+"]
|
61
|
+
s.rubygems_version = %q{1.3.7}
|
62
|
+
s.summary = %q{Implementation of the Cucumber wire protocol for PHP projects}
|
63
|
+
|
64
|
+
if s.respond_to? :specification_version then
|
65
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
66
|
+
s.specification_version = 3
|
67
|
+
|
68
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
69
|
+
s.add_runtime_dependency(%q<cucumber>, [">= 0"])
|
70
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
71
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
72
|
+
s.add_runtime_dependency(%q<cucumber>, [">= 0"])
|
73
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
74
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
77
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
78
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
79
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
80
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
81
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
82
|
+
end
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
85
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
86
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
87
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
88
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
89
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
@wire
|
2
|
+
Feature: Interact with the Cuke4Php server
|
3
|
+
As a tester
|
4
|
+
I want to run step definitions in PHP
|
5
|
+
So that I can execute steps in PHP
|
6
|
+
|
7
|
+
Scenario: Cuke4Php runs the steps
|
8
|
+
Given some setup
|
9
|
+
When I take an action
|
10
|
+
Then something happens
|
11
|
+
And an undefined step with a "param"
|
12
|
+
And a step with a "parameter" and the following table:
|
13
|
+
| column 1 | data |
|
14
|
+
| apples | 10 |
|
15
|
+
| oranges | 20 |
|
16
|
+
And a step with a multiline string:
|
17
|
+
"""
|
18
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pulvinar,
|
19
|
+
est at molestie placerat, risus lectus dictum nulla, id blandit nunc metus at
|
20
|
+
ligula. Nam purus quam, consectetur ut pulvinar eu, elementum quis nibh. Curabitur
|
21
|
+
pellentesque sapien ut dolor commodo ultricies. Sed auctor convallis nunc, et
|
22
|
+
dapibus leo ullamcorper scelerisque. Vivamus nisi diam, vestibulum eget consequat
|
23
|
+
et, fringilla vitae ipsum. Nam et nisl est. Cras ac iaculis nisl. Quisque
|
24
|
+
condimentum tristique tellus, vitae fringilla nulla dictum vel. Proin varius congue
|
25
|
+
libero id facilisis. Etiam scelerisque mauris sit amet sem imperdiet a laoreet tellus
|
26
|
+
scelerisque. Curabitur vulputate congue malesuada. Aenean tempus viverra arcu, quis
|
27
|
+
posuere velit facilisis at. Sed nec rutrum turpis. Nunc mattis magna in ante tincidunt
|
28
|
+
fermentum. Donec dapibus porta ipsum, eget porttitor magna viverra vitae. Quisque suscipit,
|
29
|
+
metus sit amet placerat interdum, enim turpis imperdiet turpis, in placerat felis
|
30
|
+
orci at sem. Suspendisse sagittis, neque quis sodales ornare, dui purus posuere
|
31
|
+
lectus, id feugiat nunc lectus ac lectus.
|
32
|
+
"""
|
33
|
+
|
34
|
+
Scenario Outline: run several steps many times
|
35
|
+
Given I <verb> the <noun>
|
36
|
+
Then It should be <adjective>
|
37
|
+
|
38
|
+
Examples:
|
39
|
+
| verb | noun | adjective |
|
40
|
+
| shoot | messenger | dead |
|
41
|
+
| understand | meaning | clear |
|
42
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @package Cuke4Php
|
8
|
+
*/
|
9
|
+
class TestSteps extends CucumberSteps {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Given /^successful$/
|
13
|
+
**/
|
14
|
+
public function stepSuccessful() {}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Given /^incomplete$/
|
18
|
+
*/
|
19
|
+
public function stepIncomplete() {
|
20
|
+
self::markTestIncomplete('incomplete');
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Given /^skipped$/
|
25
|
+
*/
|
26
|
+
public function stepSkipped() {
|
27
|
+
self::markTestSkipped('skipped');
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Given /^pending$/
|
32
|
+
*/
|
33
|
+
public function stepPending() {
|
34
|
+
self::markPending('pending');
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Given /^a failed expectation$/
|
39
|
+
*/
|
40
|
+
public function stepFailed() {
|
41
|
+
self::assertEquals(true, false);
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Given /^an exception is thrown$/
|
46
|
+
*/
|
47
|
+
public function stepException() {
|
48
|
+
throw new TestException('Exception');
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Given /^"arg1" not equal to "arg2"$/
|
53
|
+
*/
|
54
|
+
public function stepNotEqual($arg1,$arg2) {
|
55
|
+
self::assertTrue($arg1 !== $arg2);
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @one
|
60
|
+
*/
|
61
|
+
public function afterWithOneTag() {
|
62
|
+
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
*
|
67
|
+
*/
|
68
|
+
public function afterWithNoTags() {
|
69
|
+
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @one
|
74
|
+
*/
|
75
|
+
public function beforeWithOneTag() {
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
*
|
81
|
+
*/
|
82
|
+
public function beforeWithNoTags() {
|
83
|
+
|
84
|
+
}
|
85
|
+
|
86
|
+
}
|
87
|
+
|
88
|
+
?>
|
@@ -0,0 +1,87 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @package Cuke4Php
|
7
|
+
*/
|
8
|
+
class WireSteps extends CucumberSteps {
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @wire
|
12
|
+
*/
|
13
|
+
function beforeWire() {
|
14
|
+
$this->aGlobals['before'] = 'beforeWire';
|
15
|
+
}
|
16
|
+
|
17
|
+
function beforeAll() {
|
18
|
+
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Given /^some setup$/
|
23
|
+
**/
|
24
|
+
public function stepSomeSetup() {
|
25
|
+
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* When /^I take an action$/
|
30
|
+
**/
|
31
|
+
public function stepITakeAnAction() {
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Then /^something happens$/
|
36
|
+
**/
|
37
|
+
public function stepSomethingHappens() {
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Then /^an undefined step with a "([^"]*)"$/
|
42
|
+
**/
|
43
|
+
public function stepAnUndefinedStepWithAParameter($arg1) {
|
44
|
+
self::assertEquals('param', $arg1);
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Then /^a step with a "([^"]*)" and the following table\:$/
|
49
|
+
**/
|
50
|
+
public function stepAStepWithAParameterAndTheFollowingTable($arg1, $table) {
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Given /^I shoot the messenger$/
|
55
|
+
**/
|
56
|
+
public function stepIShootTheMessenger() {
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Then /^It should be dead$/
|
61
|
+
**/
|
62
|
+
public function stepItShouldBeDead() {
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Given /^I understand the meaning$/
|
67
|
+
**/
|
68
|
+
public function stepIUnderstandTheMeaning() {
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Then /^It should be clear$/
|
73
|
+
**/
|
74
|
+
public function stepItShouldBeClear() {
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Then /^a step with a multiline string\:$/
|
79
|
+
**/
|
80
|
+
public function stepAStepWithAMultilineString($sString) {
|
81
|
+
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
}
|
86
|
+
|
87
|
+
?>
|
data/lib/Cucumber.php
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* load dependencies
|
8
|
+
*/
|
9
|
+
require_once "CucumberSteps.php";
|
10
|
+
|
11
|
+
/**
|
12
|
+
* class CucumberScenario
|
13
|
+
* Defines a Cucumber Scenario
|
14
|
+
* @package Cuke4Php
|
15
|
+
*/
|
16
|
+
class CucumberScenario {
|
17
|
+
|
18
|
+
// provide a place we can store data
|
19
|
+
public $aGlobals = array();
|
20
|
+
|
21
|
+
// the world holds the definitions for the before, after, and step definitions
|
22
|
+
private $aWorld;
|
23
|
+
|
24
|
+
static private $oMock;
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @param array $_aWorld
|
28
|
+
* @return void
|
29
|
+
*/
|
30
|
+
function __construct($_aWorld = array()) {
|
31
|
+
$this->aWorld = $_aWorld;
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @static
|
36
|
+
* @param $aWorld
|
37
|
+
* @return CucumberScenario
|
38
|
+
*/
|
39
|
+
static function getInstance($aWorld) {
|
40
|
+
if (self::$oMock) {
|
41
|
+
return self::$oMock;
|
42
|
+
} else {
|
43
|
+
return new CucumberScenario($aWorld);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @static
|
49
|
+
* @param $oMock
|
50
|
+
* @return void
|
51
|
+
*/
|
52
|
+
static function setInstance($oMock) {
|
53
|
+
self::$oMock = $oMock;
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @param $aTags
|
58
|
+
* @return array
|
59
|
+
* invokes all the before hooks defined that either have no tags or tags corresponding to this scenario's tags
|
60
|
+
*/
|
61
|
+
function invokeBeforeHooks($aTags) {
|
62
|
+
foreach ($this->aWorld['before'] as $aBeforeHook) {
|
63
|
+
if (array_key_exists('tags', $aBeforeHook))
|
64
|
+
if (count($aBeforeHook['tags']) == 0 || count(array_intersect($aTags, $aBeforeHook['tags'])) > 0) {
|
65
|
+
$oStep = CucumberSteps::getInstance($aBeforeHook['class'], $this->aGlobals);
|
66
|
+
$oResult = $oStep->invoke($aBeforeHook['method']);
|
67
|
+
if ($oResult === false) {
|
68
|
+
return array('failure');
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return array('success');
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @param $aTags
|
77
|
+
* @return array
|
78
|
+
* invoke all after hooks defined that either have no tags, or tags that match the tags of the current scenario
|
79
|
+
*/
|
80
|
+
function invokeAfterHooks($aTags) {
|
81
|
+
foreach ($this->aWorld['after'] as $aAfterHook) {
|
82
|
+
if (array_key_exists('tags', $aAfterHook))
|
83
|
+
if (count($aAfterHook['tags']) == 0 || count(array_intersect($aTags, $aAfterHook['tags'])) > 0) {
|
84
|
+
$oStep = CucumberSteps::getInstance($aAfterHook['class'], $this->aGlobals);
|
85
|
+
$oResult = $oStep->invoke($aAfterHook['method']);
|
86
|
+
if ($oResult === false) {
|
87
|
+
return array('failure');
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return array('success');
|
92
|
+
}
|
93
|
+
|
94
|
+
/**
|
95
|
+
* @param $iStepId
|
96
|
+
* @param $aArgs
|
97
|
+
* @return mixed
|
98
|
+
*
|
99
|
+
* Invokes a step. Steps can use PHPUnit assertions and will
|
100
|
+
* mark themselves as pending if the self::markTestIncomplete() or self:markTestSkipped()
|
101
|
+
* functions are called. Failed expectations are returned as messages while all other
|
102
|
+
* Exceptions are reported back as exceptions.
|
103
|
+
*/
|
104
|
+
function invoke($iStepId, $aArgs) {
|
105
|
+
$aStep = $this->aWorld['steps'][$iStepId];
|
106
|
+
$oStep = new $aStep['class']($this->aGlobals);
|
107
|
+
try {
|
108
|
+
call_user_func_array(array($oStep, $aStep['method']),$aArgs);
|
109
|
+
} catch (PHPUnit_Framework_IncompleteTestError $e) {
|
110
|
+
return array('pending',$e->getMessage());
|
111
|
+
} catch (PHPUnit_Framework_SkippedTestError $e) {
|
112
|
+
return array('pending',$e->getMessage());
|
113
|
+
} catch (PHPUnit_Framework_ExpectationFailedException $e) {
|
114
|
+
return array('fail', array('message' => $e->getMessage()));
|
115
|
+
} catch (Exception $e) {
|
116
|
+
return array('fail', array('exception' => $e->__toString()));
|
117
|
+
}
|
118
|
+
return array('success');
|
119
|
+
}
|
120
|
+
|
121
|
+
}
|
122
|
+
?>
|