cuke4php 0.9.6.c → 0.9.8
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/HISTORY +3 -0
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/bin/cuke4php_forking_server +2 -0
- data/cuke4php.gemspec +15 -11
- data/features/Cuke4Php.feature +4 -1
- data/features/step_definitions/Cuke4Php.wire +0 -2
- data/features/step_definitions/WireSteps.php +7 -0
- data/lib/CucumberScenario.php +7 -0
- data/lib/Cuke4Php.php +29 -7
- data/lib/Cuke4PhpForkingServer.php +34 -0
- data/php_bin/cuke4php_forking_server.php +24 -0
- metadata +26 -24
data/HISTORY
CHANGED
data/Rakefile
CHANGED
@@ -27,6 +27,9 @@ begin
|
|
27
27
|
Install PHPUnit:
|
28
28
|
pear install phpunit/PHPUnit
|
29
29
|
|
30
|
+
Optional: Use PEAR/Net_Server for a remote forking server implementation
|
31
|
+
(requires PHP with pcntl extensions)
|
32
|
+
|
30
33
|
********************************************************************************
|
31
34
|
eos
|
32
35
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.8
|
data/cuke4php.gemspec
CHANGED
@@ -5,14 +5,14 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cuke4php}
|
8
|
-
s.version = "0.9.
|
8
|
+
s.version = "0.9.8"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
11
|
-
s.authors = [
|
12
|
-
s.date = %q{2011-
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Kevin Olbrich}, %q{Alessandro Dal Grande}]
|
12
|
+
s.date = %q{2011-08-31}
|
13
13
|
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.}
|
14
|
-
s.email = [
|
15
|
-
s.executables = [
|
14
|
+
s.email = [%q{kevin.olbrich+cuke4php@gmail.com}, %q{aledalgrande@gmail.com}]
|
15
|
+
s.executables = [%q{cuke4php_forking_server}, %q{cuke4php_server}, %q{cuke4php}]
|
16
16
|
s.extra_rdoc_files = [
|
17
17
|
"LICENSE",
|
18
18
|
"README.md"
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"bin/cuke4php",
|
29
|
+
"bin/cuke4php_forking_server",
|
29
30
|
"bin/cuke4php_server",
|
30
31
|
"cucumber.yml",
|
31
32
|
"cuke4php.gemspec",
|
@@ -40,11 +41,12 @@ Gem::Specification.new do |s|
|
|
40
41
|
"lib/CucumberScenario.php",
|
41
42
|
"lib/CucumberSteps.php",
|
42
43
|
"lib/Cuke4Php.php",
|
44
|
+
"lib/Cuke4PhpForkingServer.php",
|
45
|
+
"php_bin/cuke4php_forking_server.php",
|
43
46
|
"php_bin/cuke4php_server.php",
|
44
47
|
"tests/lib/CucumberScenarioTest.php",
|
45
48
|
"tests/lib/Cuke4PhpTest.php"
|
46
49
|
]
|
47
|
-
s.has_rdoc = false
|
48
50
|
s.homepage = %q{http://github.com/olbrich/cuke4php}
|
49
51
|
s.post_install_message = %q{********************************************************************************
|
50
52
|
|
@@ -58,15 +60,17 @@ Gem::Specification.new do |s|
|
|
58
60
|
Install PHPUnit:
|
59
61
|
pear install phpunit/PHPUnit
|
60
62
|
|
63
|
+
Optional: Use PEAR/Net_Server for a remote forking server implementation
|
64
|
+
(requires PHP with pcntl extensions)
|
65
|
+
|
61
66
|
********************************************************************************
|
62
67
|
}
|
63
|
-
s.require_paths = [
|
64
|
-
s.requirements = [
|
65
|
-
s.rubygems_version = %q{1.
|
68
|
+
s.require_paths = [%q{lib}]
|
69
|
+
s.requirements = [%q{PHP 5.2+}, %q{PHPUnit 3.0+}]
|
70
|
+
s.rubygems_version = %q{1.8.5}
|
66
71
|
s.summary = %q{Implementation of the Cucumber wire protocol for PHP projects}
|
67
72
|
|
68
73
|
if s.respond_to? :specification_version then
|
69
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
70
74
|
s.specification_version = 3
|
71
75
|
|
72
76
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/features/Cuke4Php.feature
CHANGED
@@ -54,4 +54,7 @@ Scenario Outline: Error Handling
|
|
54
54
|
@exception
|
55
55
|
Scenario: Exception Handling
|
56
56
|
When an "Exception" is thrown with message "generic exception"
|
57
|
-
Then an "Exception" should be caught
|
57
|
+
Then an "Exception" should be caught
|
58
|
+
|
59
|
+
Scenario: nested capture groups work fine
|
60
|
+
Given the losing code "one" has the prize "two"
|
@@ -231,6 +231,13 @@ class WireSteps extends CucumberSteps {
|
|
231
231
|
self::assertInternalType($sTypeName, $this->$sKey);
|
232
232
|
}
|
233
233
|
|
234
|
+
/**
|
235
|
+
* Given /^the(?: losing)? code "([^"]*)"(?: has the prize "([^"]*)")?$/
|
236
|
+
**/
|
237
|
+
public function stepTheLosingCodeParameterHasThePrizeParameter($sCode, $sPrize) {
|
238
|
+
$this->$sCode = $sPrize;
|
239
|
+
}
|
240
|
+
|
234
241
|
}
|
235
242
|
|
236
243
|
?>
|
data/lib/CucumberScenario.php
CHANGED
@@ -66,6 +66,7 @@ class CucumberScenario {
|
|
66
66
|
if (array_key_exists('tags', $aBeforeHook)) {
|
67
67
|
if (count($aBeforeHook['tags']) == 0 || count(array_intersect($aTags, $aBeforeHook['tags'])) > 0) {
|
68
68
|
$oStep = CucumberSteps::getInstance($aBeforeHook['class'], $this->aGlobals);
|
69
|
+
syslog(LOG_DEBUG,"Invoking Before Hook \"{$aBeforeHook['method']}\"");
|
69
70
|
$oResult = $oStep->invoke($aBeforeHook['method']);
|
70
71
|
if ($oResult === false) {
|
71
72
|
return array('failure');
|
@@ -89,6 +90,7 @@ class CucumberScenario {
|
|
89
90
|
if (array_key_exists('tags', $aAfterHook)) {
|
90
91
|
if (count($aAfterHook['tags']) == 0 || count(array_intersect($aTags, $aAfterHook['tags'])) > 0) {
|
91
92
|
$oStep = CucumberSteps::getInstance($aAfterHook['class'], $this->aGlobals);
|
93
|
+
syslog(LOG_DEBUG,"Invoking After Hook \"{$aAfterHook['method']}\"");
|
92
94
|
$oResult = $oStep->invoke($aAfterHook['method']);
|
93
95
|
if ($oResult === false) {
|
94
96
|
return array('failure');
|
@@ -132,14 +134,19 @@ class CucumberScenario {
|
|
132
134
|
|
133
135
|
}
|
134
136
|
try {
|
137
|
+
syslog(LOG_DEBUG,"Invoking Step \"{$aStep['method']}\"");
|
135
138
|
call_user_func_array(array($oStep, $aStep['method']),$aArgs);
|
136
139
|
} catch (PHPUnit_Framework_IncompleteTestError $e) {
|
140
|
+
syslog(LOG_DEBUG,"Step Pending");
|
137
141
|
return array('pending',$e->getMessage());
|
138
142
|
} catch (PHPUnit_Framework_SkippedTestError $e) {
|
143
|
+
syslog(LOG_DEBUG,"Step Pending");
|
139
144
|
return array('pending',$e->getMessage());
|
140
145
|
} catch (PHPUnit_Framework_ExpectationFailedException $e) {
|
146
|
+
syslog(LOG_DEBUG,"Step Failed due to unmet expectation: " . $e->getMessage());
|
141
147
|
return array('fail', array('message' => $e->getMessage()));
|
142
148
|
} catch (Exception $e) {
|
149
|
+
syslog(LOG_DEBUG,"Step failed due to ". get_class($e) ." exception :" . $e->getMessage());
|
143
150
|
return array('fail', array('message' => $e->getMessage() . " " . $e->getFile() . ":" . $e->getLine(), 'exception' => get_class($e), 'backtrace' => $e->getTraceAsString()));
|
144
151
|
}
|
145
152
|
return array('success');
|
data/lib/Cuke4Php.php
CHANGED
@@ -26,6 +26,7 @@ class Cuke4Php {
|
|
26
26
|
);
|
27
27
|
|
28
28
|
function __construct($_sFeaturePath, $_iPort = 16816) {
|
29
|
+
openlog("cuke4php", LOG_PID, LOG_DAEMON);
|
29
30
|
if (is_file($_sFeaturePath)) {
|
30
31
|
$_sFeaturePath = dirname($_sFeaturePath);
|
31
32
|
}
|
@@ -119,21 +120,40 @@ class Cuke4Php {
|
|
119
120
|
}
|
120
121
|
|
121
122
|
function run() {
|
122
|
-
|
123
|
+
syslog(LOG_INFO,"Cuke4Php listening on port $this->iPort\n");
|
123
124
|
$this->oSocket = socket_create_listen($this->iPort);
|
124
125
|
$this->bRun = true;
|
125
126
|
while ($this->bRun && ($connection = socket_accept($this->oSocket))) {
|
126
127
|
socket_getpeername($connection, $raddr, $rport);
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
$
|
131
|
-
if ($
|
132
|
-
|
128
|
+
syslog(LOG_INFO,"Connection from $raddr");
|
129
|
+
try {
|
130
|
+
while ($this->bRun && ($input = socket_read($connection, 4096, PHP_NORMAL_READ))) {
|
131
|
+
$data = trim($input);
|
132
|
+
if ($data !== "") {
|
133
|
+
$output = json_encode($this->process($data)) . "\n";
|
134
|
+
if ($this->bRun) {
|
135
|
+
socket_write($connection, $output);
|
136
|
+
}
|
133
137
|
}
|
138
|
+
}
|
139
|
+
} catch (Exception $e) {
|
140
|
+
switch (socket_last_error($connection)) {
|
141
|
+
case 54:
|
142
|
+
// connection closed by peer
|
143
|
+
case 104:
|
144
|
+
// unable to read from socket
|
145
|
+
// these errors just mean we are done and the connection should be closed.
|
146
|
+
// it does not mean we should stop listening for new connections.
|
147
|
+
break;
|
148
|
+
|
149
|
+
default:
|
150
|
+
syslog(LOG_ERR,$e->getMessage());
|
151
|
+
throw $e;
|
152
|
+
break;
|
134
153
|
}
|
135
154
|
}
|
136
155
|
socket_close($connection);
|
156
|
+
syslog(LOG_INFO,"Connection closed");
|
137
157
|
sleep(1);
|
138
158
|
}
|
139
159
|
}
|
@@ -183,6 +203,7 @@ class Cuke4Php {
|
|
183
203
|
* run any before hooks for a scenario
|
184
204
|
*/
|
185
205
|
function beginScenario($aTags) {
|
206
|
+
syslog(LOG_DEBUG,"Begin Scenario: Tags: " . implode(", ", $aTags));
|
186
207
|
$this->setScenario(CucumberScenario::getInstance($this->aWorld));
|
187
208
|
return $this->oScenario->invokeBeforeHooks($aTags);
|
188
209
|
}
|
@@ -216,6 +237,7 @@ class Cuke4Php {
|
|
216
237
|
*/
|
217
238
|
function endScenario($aTags) {
|
218
239
|
$oResult = $this->oScenario->invokeAfterHooks($aTags);
|
240
|
+
syslog(LOG_DEBUG,"End Scenario");
|
219
241
|
$this->oScenario = null;
|
220
242
|
return $oResult;
|
221
243
|
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
/**
|
4
|
+
* This class allows multiple concurrent connections to the same Cuke4php port. Each connection forks a process that
|
5
|
+
* loads the same feature files and then runs the step definitions. This is useful for cases where the Cuke4php server
|
6
|
+
* is deployed to a remote machine and multiple automation scripts are simultaneously connecting to the server.
|
7
|
+
*
|
8
|
+
* Uses the PEAR Net_Server package
|
9
|
+
**/
|
10
|
+
|
11
|
+
require_once "Cuke4Php.php";
|
12
|
+
require_once "Net/Server.php";
|
13
|
+
require_once "Net/Server/Handler.php";
|
14
|
+
|
15
|
+
class Cuke4PhpForkingServer extends Net_Server_Handler
|
16
|
+
{
|
17
|
+
private $cuke4php;
|
18
|
+
|
19
|
+
function __construct($_sFeaturePath, $_iPort) {
|
20
|
+
$this->cuke4php = new Cuke4Php($_sFeaturePath, $_iPort);
|
21
|
+
}
|
22
|
+
|
23
|
+
function onReceiveData($iClientId = 0, $data = "") {
|
24
|
+
$output = json_encode($this->cuke4php->process($data)) . "\n";
|
25
|
+
$this->_server->sendData($iClientId, $output);
|
26
|
+
}
|
27
|
+
|
28
|
+
function onClose($iClientId) {
|
29
|
+
// Do nothing
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
?>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env php
|
2
|
+
<?php
|
3
|
+
/**
|
4
|
+
* main entry point for starting a Cuke4Php wire server
|
5
|
+
* @package Cuke4Php
|
6
|
+
*/
|
7
|
+
|
8
|
+
/**
|
9
|
+
* load the Cuke4PhpForkingServer server
|
10
|
+
*/
|
11
|
+
require_once dirname(__FILE__) . "/../lib/Cuke4PhpForkingServer.php";
|
12
|
+
|
13
|
+
$aOptions = getopt("p:");
|
14
|
+
if (array_key_exists('p',$aOptions)) {
|
15
|
+
$iPort = $aOptions['p'];
|
16
|
+
} else {
|
17
|
+
$iPort = 16816;
|
18
|
+
}
|
19
|
+
|
20
|
+
$oServer = &Net_Server::create('fork','0.0.0.0', $iPort);
|
21
|
+
$oServerHandler = &new Cuke4PhpForkingServer(realpath($argv[$argc-1]), $iPort);
|
22
|
+
$oServer->setCallbackObject($oServerHandler);
|
23
|
+
$oServer->start();
|
24
|
+
?>
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuke4php
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 43
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
|
11
|
-
version: 0.9.6.c
|
9
|
+
- 8
|
10
|
+
version: 0.9.8
|
12
11
|
platform: ruby
|
13
12
|
authors:
|
14
13
|
- Kevin Olbrich
|
@@ -17,11 +16,10 @@ autorequire:
|
|
17
16
|
bindir: bin
|
18
17
|
cert_chain: []
|
19
18
|
|
20
|
-
date: 2011-
|
21
|
-
default_executable:
|
19
|
+
date: 2011-08-31 00:00:00 Z
|
22
20
|
dependencies:
|
23
21
|
- !ruby/object:Gem::Dependency
|
24
|
-
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
23
|
none: false
|
26
24
|
requirements:
|
27
25
|
- - ">="
|
@@ -33,11 +31,11 @@ dependencies:
|
|
33
31
|
- 2
|
34
32
|
version: 0.10.2
|
35
33
|
type: :runtime
|
36
|
-
|
34
|
+
requirement: *id001
|
37
35
|
prerelease: false
|
38
|
-
|
36
|
+
name: cucumber
|
39
37
|
- !ruby/object:Gem::Dependency
|
40
|
-
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
40
|
requirements:
|
43
41
|
- - ~>
|
@@ -48,11 +46,11 @@ dependencies:
|
|
48
46
|
- 0
|
49
47
|
version: "1.0"
|
50
48
|
type: :development
|
51
|
-
|
49
|
+
requirement: *id002
|
52
50
|
prerelease: false
|
53
|
-
|
51
|
+
name: bundler
|
54
52
|
- !ruby/object:Gem::Dependency
|
55
|
-
|
53
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
56
54
|
none: false
|
57
55
|
requirements:
|
58
56
|
- - ">="
|
@@ -62,14 +60,15 @@ dependencies:
|
|
62
60
|
- 0
|
63
61
|
version: "0"
|
64
62
|
type: :development
|
65
|
-
|
63
|
+
requirement: *id003
|
66
64
|
prerelease: false
|
67
|
-
|
65
|
+
name: jeweler
|
68
66
|
description: 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.
|
69
67
|
email:
|
70
68
|
- kevin.olbrich+cuke4php@gmail.com
|
71
69
|
- aledalgrande@gmail.com
|
72
70
|
executables:
|
71
|
+
- cuke4php_forking_server
|
73
72
|
- cuke4php_server
|
74
73
|
- cuke4php
|
75
74
|
extensions: []
|
@@ -86,6 +85,7 @@ files:
|
|
86
85
|
- Rakefile
|
87
86
|
- VERSION
|
88
87
|
- bin/cuke4php
|
88
|
+
- bin/cuke4php_forking_server
|
89
89
|
- bin/cuke4php_server
|
90
90
|
- cucumber.yml
|
91
91
|
- cuke4php.gemspec
|
@@ -100,10 +100,11 @@ files:
|
|
100
100
|
- lib/CucumberScenario.php
|
101
101
|
- lib/CucumberSteps.php
|
102
102
|
- lib/Cuke4Php.php
|
103
|
+
- lib/Cuke4PhpForkingServer.php
|
104
|
+
- php_bin/cuke4php_forking_server.php
|
103
105
|
- php_bin/cuke4php_server.php
|
104
106
|
- tests/lib/CucumberScenarioTest.php
|
105
107
|
- tests/lib/Cuke4PhpTest.php
|
106
|
-
has_rdoc: false
|
107
108
|
homepage: http://github.com/olbrich/cuke4php
|
108
109
|
licenses: []
|
109
110
|
|
@@ -120,6 +121,9 @@ post_install_message: |
|
|
120
121
|
Install PHPUnit:
|
121
122
|
pear install phpunit/PHPUnit
|
122
123
|
|
124
|
+
Optional: Use PEAR/Net_Server for a remote forking server implementation
|
125
|
+
(requires PHP with pcntl extensions)
|
126
|
+
|
123
127
|
********************************************************************************
|
124
128
|
|
125
129
|
rdoc_options: []
|
@@ -138,19 +142,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
143
|
none: false
|
140
144
|
requirements:
|
141
|
-
- - "
|
145
|
+
- - ">="
|
142
146
|
- !ruby/object:Gem::Version
|
143
|
-
hash:
|
147
|
+
hash: 3
|
144
148
|
segments:
|
145
|
-
-
|
146
|
-
|
147
|
-
- 1
|
148
|
-
version: 1.3.1
|
149
|
+
- 0
|
150
|
+
version: "0"
|
149
151
|
requirements:
|
150
152
|
- PHP 5.2+
|
151
153
|
- PHPUnit 3.0+
|
152
154
|
rubyforge_project:
|
153
|
-
rubygems_version: 1.
|
155
|
+
rubygems_version: 1.8.5
|
154
156
|
signing_key:
|
155
157
|
specification_version: 3
|
156
158
|
summary: Implementation of the Cucumber wire protocol for PHP projects
|