cuke4php 0.9.6.c → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|