cuke4php 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,79 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Base class that all cucumber steps should derive from
|
8
|
+
*
|
9
|
+
* Each step gets a reference to the global variables array provided by the scenario.
|
10
|
+
* This allows steps to save and maintain state over the course of a scenario run.
|
11
|
+
*
|
12
|
+
* This class also inherits PHPUnit assertions, so those can all be used within the context of a
|
13
|
+
* step. Data providers probably don't work, and really should not be used in any case.
|
14
|
+
* @package Cuke4Php
|
15
|
+
*/
|
16
|
+
class CucumberSteps extends PHPUnit_Framework_Assert {
|
17
|
+
static private $aMocks = array();
|
18
|
+
protected $aGlobals;
|
19
|
+
|
20
|
+
public function __construct(&$_aGlobals) {
|
21
|
+
$this->aGlobals =& $_aGlobals;
|
22
|
+
}
|
23
|
+
|
24
|
+
public static function markPending($sMessage = "Not Implemented") {
|
25
|
+
self::markTestIncomplete($sMessage);
|
26
|
+
}
|
27
|
+
|
28
|
+
public static function getSubclasses() {
|
29
|
+
$aClasses = array();
|
30
|
+
foreach (get_declared_classes() as $sClassName) {
|
31
|
+
if (is_subclass_of($sClassName, 'CucumberSteps') && (stripos($sClassName,"Mock") === false))
|
32
|
+
$aClasses[] = $sClassName;
|
33
|
+
}
|
34
|
+
return $aClasses;
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @param $sMethod
|
39
|
+
* @return mixed
|
40
|
+
*/
|
41
|
+
function invoke($sMethod) {
|
42
|
+
return $this->$sMethod();
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* @static
|
47
|
+
* @param $sClass
|
48
|
+
* @param $oMock
|
49
|
+
* @return void
|
50
|
+
*
|
51
|
+
* Allows tests to set mock hooks to be used
|
52
|
+
*/
|
53
|
+
static function setMock($sClass, $oMock) {
|
54
|
+
self::$aMocks[$sClass] = $oMock;
|
55
|
+
}
|
56
|
+
|
57
|
+
static function clearMocks() {
|
58
|
+
self::$aMocks = array();
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* @static
|
63
|
+
* @param $sClass
|
64
|
+
* @param $aGlobals
|
65
|
+
* @return
|
66
|
+
*
|
67
|
+
* Get an instance of a hook which is either a pre-set mock,
|
68
|
+
* or an instance of the appropriate step class with the globals initialized
|
69
|
+
*/
|
70
|
+
static function getInstance($sClass, $aGlobals) {
|
71
|
+
if (array_key_exists($sClass, self::$aMocks) && self::$aMocks[$sClass]) {
|
72
|
+
return self::$aMocks[$sClass];
|
73
|
+
} else {
|
74
|
+
return new $sClass($aGlobals);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
?>
|
data/lib/Cuke4Php.php
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
set_time_limit(0);
|
7
|
+
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Cuke4Php implements the Cucumber wire protocol for PHP
|
11
|
+
*
|
12
|
+
* http://wiki.github.com/aslakhellesoy/cucumber/wire-protocol
|
13
|
+
* @package Cuke4Php
|
14
|
+
*/
|
15
|
+
class Cuke4Php {
|
16
|
+
public $iPort;
|
17
|
+
private $bRun;
|
18
|
+
private $oSocket;
|
19
|
+
private $oScenario;
|
20
|
+
private $aStepClasses;
|
21
|
+
public $aWorld = array(
|
22
|
+
'steps' => array(),
|
23
|
+
'before' => array(),
|
24
|
+
'after' => array()
|
25
|
+
);
|
26
|
+
|
27
|
+
function __construct($_sFeaturePath, $_iPort = 16816) {
|
28
|
+
if ($_iPort > 0) {
|
29
|
+
$this->iPort = $_iPort;
|
30
|
+
} else {
|
31
|
+
$this->iPort = 16816;
|
32
|
+
}
|
33
|
+
|
34
|
+
foreach (self::rglob("*.php", 0, $_sFeaturePath . "/support") as $sFilename) {
|
35
|
+
require_once $sFilename;
|
36
|
+
}
|
37
|
+
require_once "Cucumber.php";
|
38
|
+
foreach (self::rglob("*.php", 0, $_sFeaturePath . "/step_definitions") as $sFilename) {
|
39
|
+
require_once $sFilename;
|
40
|
+
}
|
41
|
+
$this->aStepClasses = CucumberSteps::getSubclasses();
|
42
|
+
foreach ($this->aStepClasses as $sClass) {
|
43
|
+
$oReflection = new ReflectionClass($sClass);
|
44
|
+
$aMethods = $oReflection->getMethods();
|
45
|
+
foreach ($aMethods as $oMethod) {
|
46
|
+
$sComment = $oMethod->getDocComment();
|
47
|
+
$aMatches = array();
|
48
|
+
$aMethod = array();
|
49
|
+
$aMethod['method'] = $oMethod->name;
|
50
|
+
$aMethod['class'] = $oMethod->class;
|
51
|
+
$aMethod['filename'] = $oMethod->getFileName();
|
52
|
+
$aMethod['startline'] = $oMethod->getStartLine();
|
53
|
+
if (substr($oMethod->name, 0, 4) === "step") {
|
54
|
+
preg_match("/(?:Given|When|Then) (.+)$/im", $sComment, $aMatches);
|
55
|
+
$aMethod['regexp'] = $aMatches[1];
|
56
|
+
$this->aWorld['steps'][] = $aMethod;
|
57
|
+
continue;
|
58
|
+
}
|
59
|
+
preg_match("/(@.+)/im", $sComment, $aMatches);
|
60
|
+
if (array_key_exists(1, $aMatches)) {
|
61
|
+
$aMethod['tags'] = explode(" ", str_replace("@", "", $aMatches[1]));
|
62
|
+
}
|
63
|
+
if (substr($oMethod->name, 0, 6) === "before") {
|
64
|
+
$this->aWorld['before'][] = $aMethod;
|
65
|
+
continue;
|
66
|
+
}
|
67
|
+
if (substr($oMethod->name, 0, 5) === "after") {
|
68
|
+
$this->aWorld['after'][] = $aMethod;
|
69
|
+
continue;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @param string $pattern
|
77
|
+
* @param int $flags
|
78
|
+
* @param string $path
|
79
|
+
* @return array
|
80
|
+
* recursive glob utility function
|
81
|
+
*/
|
82
|
+
static function rglob($sPattern='*', $iFlags = 0, $sPath='') {
|
83
|
+
$aPaths=glob($sPath.'*', GLOB_MARK|GLOB_ONLYDIR|GLOB_NOSORT);
|
84
|
+
$aFiles=glob($sPath.$sPattern, $iFlags);
|
85
|
+
foreach ($aPaths as $sPath) { $aFiles=array_merge($aFiles,self::rglob($sPattern, $iFlags, $sPath)); }
|
86
|
+
return $aFiles;
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
/**
|
91
|
+
* @param $oScenario
|
92
|
+
* @return void
|
93
|
+
*/
|
94
|
+
function setScenario($oScenario) {
|
95
|
+
$this->oScenario = $oScenario;
|
96
|
+
}
|
97
|
+
|
98
|
+
function __destruct() {
|
99
|
+
if (isset($this->oSocket) && $this->oSocket) {
|
100
|
+
socket_close($this->oSocket);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
function run() {
|
105
|
+
print "Cuke4Php listening on port $this->iPort\n";
|
106
|
+
$this->oSocket = socket_create_listen($this->iPort);
|
107
|
+
$this->bRun = true;
|
108
|
+
while ($this->bRun && ($connection = socket_accept($this->oSocket))) {
|
109
|
+
socket_getpeername($connection, $raddr, $rport);
|
110
|
+
while ($this->bRun && ($input = socket_read($connection, 1024 * 4))) {
|
111
|
+
$data = trim($input);
|
112
|
+
if ($data !== "") {
|
113
|
+
$output = json_encode($this->process($data)) . "\n";
|
114
|
+
if ($this->bRun) {
|
115
|
+
socket_write($connection, $output);
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
socket_close($connection);
|
120
|
+
sleep(1);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
function process($sInput) {
|
125
|
+
switch ($sInput) {
|
126
|
+
case "quit":
|
127
|
+
case "bye":
|
128
|
+
$this->bRun = false;
|
129
|
+
return "Complete";
|
130
|
+
break;
|
131
|
+
default:
|
132
|
+
$aCommand = json_decode($sInput);
|
133
|
+
$sAction = $aCommand[0];
|
134
|
+
$sData = NULL;
|
135
|
+
if (array_key_exists(1, $aCommand)) {
|
136
|
+
$sData = $aCommand[1];
|
137
|
+
}
|
138
|
+
switch ($sAction) {
|
139
|
+
case 'begin_scenario':
|
140
|
+
return $this->beginScenario($sData->tags);
|
141
|
+
break;
|
142
|
+
case 'step_matches':
|
143
|
+
return $this->stepMatches($sData->name_to_match);
|
144
|
+
break;
|
145
|
+
case 'invoke':
|
146
|
+
return $this->oScenario->invoke($sData->id, $sData->args);
|
147
|
+
break;
|
148
|
+
case 'end_scenario':
|
149
|
+
return $this->endScenario($sData->tags);
|
150
|
+
break;
|
151
|
+
case 'snippet_text':
|
152
|
+
return $this->snippetText($sData);
|
153
|
+
default:
|
154
|
+
print "Unknown Command: $sInput\n";
|
155
|
+
break;
|
156
|
+
}
|
157
|
+
return array('success');
|
158
|
+
break;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* @param $aTags
|
164
|
+
* @return array
|
165
|
+
* run any before hooks for a scenario
|
166
|
+
*/
|
167
|
+
function beginScenario($aTags) {
|
168
|
+
$this->setScenario(CucumberScenario::getInstance($this->aWorld));
|
169
|
+
return $this->oScenario->invokeBeforeHooks($aTags);
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* @param $sStep
|
174
|
+
* @return array
|
175
|
+
* when given a string, this method will return information about any step that matches it
|
176
|
+
*/
|
177
|
+
function stepMatches($sStep) {
|
178
|
+
$aSteps = array();
|
179
|
+
for ($i = 0; $i < count($this->aWorld['steps']); $i++) {
|
180
|
+
$aMatches = array();
|
181
|
+
$aStep = $this->aWorld['steps'][$i];
|
182
|
+
if (preg_match_all($aStep['regexp'], $sStep, $aMatches, PREG_OFFSET_CAPTURE)) {
|
183
|
+
$aArgs = array();
|
184
|
+
array_shift($aMatches);
|
185
|
+
foreach ($aMatches as $aMatch) {
|
186
|
+
$aArgs[] = array('val' => $aMatch[0][0], 'pos' => $aMatch[0][1]);
|
187
|
+
}
|
188
|
+
$aSteps[] = array('id' => $i, 'args' => $aArgs, 'source' => $aStep['filename'] . ":" . $aStep['startline']);
|
189
|
+
};
|
190
|
+
}
|
191
|
+
return array('success', $aSteps);
|
192
|
+
}
|
193
|
+
|
194
|
+
/**
|
195
|
+
* @param $aTags
|
196
|
+
* @return array
|
197
|
+
* run any after hooks for a scenario
|
198
|
+
*/
|
199
|
+
function endScenario($aTags) {
|
200
|
+
$oResult = $this->oScenario->invokeAfterHooks($aTags);
|
201
|
+
$this->oScenario = null;
|
202
|
+
return $oResult;
|
203
|
+
}
|
204
|
+
|
205
|
+
/**
|
206
|
+
* @param $aSnippet
|
207
|
+
* @return array
|
208
|
+
* return a template for an undefined step
|
209
|
+
*/
|
210
|
+
function snippetText($aSnippet) {
|
211
|
+
$sMethodName = "step" . str_replace(" ", "", ucwords(preg_replace("/\W+/", " ", preg_replace("/\"[^\"]*\"/", "Parameter", $aSnippet->step_name))));
|
212
|
+
$count = 0;
|
213
|
+
$aParams = array();
|
214
|
+
$sStepName = preg_replace("/\"[^\"]*\"/", "\"([^\"]*)\"", preg_quote($aSnippet->step_name), -1, &$count);
|
215
|
+
for ($param = 1; $param <= $count; $param++) {
|
216
|
+
$aParams[] = "\$arg$param";
|
217
|
+
}
|
218
|
+
switch ($aSnippet->multiline_arg_class) {
|
219
|
+
case "Cucumber::Ast::Table":
|
220
|
+
$aParams[] = "\$aTable";
|
221
|
+
break;
|
222
|
+
case "Cucumber::Ast::PyString":
|
223
|
+
$aParams[] = "\$sString";
|
224
|
+
break;
|
225
|
+
default:
|
226
|
+
}
|
227
|
+
|
228
|
+
$sParams = implode(",", $aParams);
|
229
|
+
$sMethodBody = <<<EOT
|
230
|
+
|
231
|
+
/**
|
232
|
+
* {$aSnippet->step_keyword} /^$sStepName$/
|
233
|
+
**/
|
234
|
+
public function $sMethodName($sParams) {
|
235
|
+
self::markPending();
|
236
|
+
}
|
237
|
+
EOT;
|
238
|
+
return array('success', $sMethodBody);
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
?>
|
@@ -0,0 +1,20 @@
|
|
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 Cuke4Php server
|
10
|
+
*/
|
11
|
+
require_once dirname(__FILE__) . "/../lib/Cuke4Php.php";
|
12
|
+
$aOptions = getopt("p:");
|
13
|
+
if (array_key_exists('p',$aOptions)) {
|
14
|
+
$iPort = $aOptions['p'];
|
15
|
+
} else {
|
16
|
+
$iPort = null;
|
17
|
+
}
|
18
|
+
$oServer = new Cuke4Php(realpath($argv[$argc-1]), $iPort);
|
19
|
+
$oServer->run();
|
20
|
+
?>
|
@@ -0,0 +1,161 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* load Cucumber php framework
|
8
|
+
*/
|
9
|
+
require_once dirname(__FILE__) . "/../../lib/Cucumber.php";
|
10
|
+
|
11
|
+
/**
|
12
|
+
* class TestException
|
13
|
+
* this class is used during the tests to mock exceptions.
|
14
|
+
* @package Cuke4Php
|
15
|
+
*/
|
16
|
+
class TestException extends Exception {
|
17
|
+
public function __toString() {
|
18
|
+
return "TestException";
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
require_once(dirname(__FILE__) . "/../../features/step_definitions/TestSteps.php");
|
23
|
+
|
24
|
+
/**
|
25
|
+
* class CucumberScenarioTest
|
26
|
+
* @package Cuke4Php
|
27
|
+
*/
|
28
|
+
class CucumberScenarioTest extends PHPUnit_Framework_TestCase {
|
29
|
+
|
30
|
+
public $oScenario;
|
31
|
+
public $aWorld;
|
32
|
+
public $aTags;
|
33
|
+
public $oMockHook;
|
34
|
+
|
35
|
+
public function setup() {
|
36
|
+
CucumberSteps::clearMocks();
|
37
|
+
$this->aWorld = array(
|
38
|
+
'before' => array(
|
39
|
+
array(
|
40
|
+
'tags' => array('one'),
|
41
|
+
'class' => 'TestSteps',
|
42
|
+
'method' => 'beforeWithOneTag'
|
43
|
+
),
|
44
|
+
array(
|
45
|
+
'tags' => array(),
|
46
|
+
'class' => 'TestSteps',
|
47
|
+
'method' => 'beforeWithNoTags'
|
48
|
+
)
|
49
|
+
),
|
50
|
+
'after' => array(
|
51
|
+
array(
|
52
|
+
'tags' => array('one'),
|
53
|
+
'class' => 'TestSteps',
|
54
|
+
'method' => 'afterWithOneTag'
|
55
|
+
),
|
56
|
+
array(
|
57
|
+
'tags' => array(),
|
58
|
+
'class' => 'TestSteps',
|
59
|
+
'method' => 'afterWithNoTags'
|
60
|
+
)
|
61
|
+
),
|
62
|
+
'steps' => array(
|
63
|
+
0 => array(
|
64
|
+
'class' => 'TestSteps',
|
65
|
+
'method' => 'stepSuccessful'
|
66
|
+
),
|
67
|
+
1 => array(
|
68
|
+
'class' => 'TestSteps',
|
69
|
+
'method' => 'stepIncomplete'
|
70
|
+
),
|
71
|
+
2 => array(
|
72
|
+
'class' => 'TestSteps',
|
73
|
+
'method' => 'stepSkipped'
|
74
|
+
),
|
75
|
+
3 => array(
|
76
|
+
'class' => 'TestSteps',
|
77
|
+
'method' => 'stepPending'
|
78
|
+
),
|
79
|
+
4 => array(
|
80
|
+
'class' => 'TestSteps',
|
81
|
+
'method' => 'stepFailed'
|
82
|
+
),
|
83
|
+
5 => array(
|
84
|
+
'class' => 'TestSteps',
|
85
|
+
'method' => 'stepException'
|
86
|
+
),
|
87
|
+
6 => array(
|
88
|
+
'class' => 'TestSteps',
|
89
|
+
'method' => 'stepNotEqual'
|
90
|
+
)
|
91
|
+
|
92
|
+
)
|
93
|
+
|
94
|
+
);
|
95
|
+
$this->aTags = array('one','two');
|
96
|
+
$this->oScenario = new CucumberScenario($this->aWorld);
|
97
|
+
$this->oMockHook = $this->getMock('TestSteps', array(
|
98
|
+
'beforeWithOneTag',
|
99
|
+
'beforeWithNoTags',
|
100
|
+
'afterWithOneTag',
|
101
|
+
'afterWithNoTags'), array(array()));
|
102
|
+
}
|
103
|
+
|
104
|
+
public function testShouldRunBeforeHooksWithAMatchingTag() {
|
105
|
+
$this->oMockHook->expects(self::once())->method('beforeWithOneTag');
|
106
|
+
$this->oMockHook->expects(self::once())->method('beforeWithNoTags');
|
107
|
+
CucumberSteps::setMock('TestSteps', $this->oMockHook);
|
108
|
+
self::assertEquals(array('success'),$this->oScenario->invokeBeforeHooks($this->aTags));
|
109
|
+
}
|
110
|
+
|
111
|
+
public function testShouldRunBeforeHooksWithNoTags() {
|
112
|
+
$this->oMockHook->expects(self::once())->method('beforeWithNoTags');
|
113
|
+
CucumberSteps::setMock('TestSteps', $this->oMockHook);
|
114
|
+
self::assertEquals(array('success'),$this->oScenario->invokeBeforeHooks(array()));
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
public function testShouldRunAfterHooksWithAMatchingTag() {
|
119
|
+
$this->oMockHook->expects(self::once())->method('afterWithOneTag');
|
120
|
+
$this->oMockHook->expects(self::once())->method('afterWithNoTags');
|
121
|
+
CucumberSteps::setMock('TestSteps', $this->oMockHook);
|
122
|
+
self::assertEquals(array('success'),$this->oScenario->invokeAfterHooks($this->aTags));
|
123
|
+
}
|
124
|
+
|
125
|
+
public function testShouldRunAfterHooksWithNoTags() {
|
126
|
+
$this->oMockHook->expects(self::once())->method('afterWithNoTags');
|
127
|
+
CucumberSteps::setMock('TestSteps', $this->oMockHook);
|
128
|
+
self::assertEquals(array('success'),$this->oScenario->invokeAfterHooks(array()));
|
129
|
+
}
|
130
|
+
|
131
|
+
public function testInvokeShouldReturnSuccess() {
|
132
|
+
self::assertEquals(array('success'),$this->oScenario->invoke(0,array()));
|
133
|
+
}
|
134
|
+
|
135
|
+
public function testInvokeShouldReturnPendingWhenIncomplete() {
|
136
|
+
self::assertEquals(array('pending','incomplete'),$this->oScenario->invoke(1,array()));
|
137
|
+
}
|
138
|
+
|
139
|
+
public function testInvokeShouldReturnPendingWhenSkipped() {
|
140
|
+
self::assertEquals(array('pending','skipped'),$this->oScenario->invoke(2,array()));
|
141
|
+
}
|
142
|
+
|
143
|
+
public function testInvokeShouldReturnPendingWhenPending() {
|
144
|
+
self::assertEquals(array('pending','pending'),$this->oScenario->invoke(3,array()));
|
145
|
+
}
|
146
|
+
|
147
|
+
public function testInvokeShouldFailWhenAssertionNotMet() {
|
148
|
+
self::assertEquals(array('fail',array('message' => 'Failed asserting that <boolean:false> is equal to <boolean:true>.')), $this->oScenario->invoke(4,array()));
|
149
|
+
}
|
150
|
+
|
151
|
+
public function testInvokeShouldFailWhenExceptionThrown() {
|
152
|
+
self::assertEquals(array('fail',array('exception' => 'TestException')), $this->oScenario->invoke(5,array()));
|
153
|
+
}
|
154
|
+
|
155
|
+
public function testInvokeShouldSucceedWithParameters() {
|
156
|
+
self::assertEquals(array('success'), $this->oScenario->invoke(6,array('one','two')));
|
157
|
+
}
|
158
|
+
|
159
|
+
}
|
160
|
+
|
161
|
+
?>
|
@@ -0,0 +1,117 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* @package Cuke4Php
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* load Cucumber framework
|
8
|
+
*/
|
9
|
+
require_once dirname(__FILE__) . "/../../lib/Cucumber.php";
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @package Cuke4Php
|
13
|
+
*/
|
14
|
+
class Cuke4PhpTest extends PHPUnit_Framework_TestCase {
|
15
|
+
|
16
|
+
public $oCuke4Php;
|
17
|
+
|
18
|
+
function setup() {
|
19
|
+
$this->oCuke4Php = new Cuke4Php(dirname(__FILE__) . "/../../features");
|
20
|
+
}
|
21
|
+
|
22
|
+
function testSnippetTextReturnsSnippet() {
|
23
|
+
$oSnippet = new StdClass;
|
24
|
+
$oSnippet->step_name = "this is a step name";
|
25
|
+
$oSnippet->multiline_arg_class = "";
|
26
|
+
$oSnippet->step_keyword = "Given";
|
27
|
+
$sActual = $this->oCuke4Php->snippetText($oSnippet);
|
28
|
+
$sExpected = array('success',"
|
29
|
+
/**
|
30
|
+
* Given /^this is a step name$/
|
31
|
+
**/
|
32
|
+
public function stepThisIsAStepName() {
|
33
|
+
self::markPending();
|
34
|
+
}");
|
35
|
+
self::assertEquals($sExpected, $sActual);
|
36
|
+
}
|
37
|
+
|
38
|
+
function testSnippetTextReturnsSnippetWithParameters() {
|
39
|
+
$oSnippet = new StdClass;
|
40
|
+
$oSnippet->step_name = 'this is a step with parameter "param1"';
|
41
|
+
$oSnippet->multiline_arg_class = "";
|
42
|
+
$oSnippet->step_keyword = "Given";
|
43
|
+
$sActual = $this->oCuke4Php->snippetText($oSnippet);
|
44
|
+
$sExpected = array('success','
|
45
|
+
/**
|
46
|
+
* Given /^this is a step with parameter "([^"]*)"$/
|
47
|
+
**/
|
48
|
+
public function stepThisIsAStepWithParameterParameter($arg1) {
|
49
|
+
self::markPending();
|
50
|
+
}');
|
51
|
+
self::assertEquals($sExpected, $sActual);
|
52
|
+
}
|
53
|
+
|
54
|
+
function testSnippetTextReturnsSnippetWithATable() {
|
55
|
+
$oSnippet = new StdClass;
|
56
|
+
$oSnippet->step_name = 'this is a step with a table:';
|
57
|
+
$oSnippet->multiline_arg_class = "Cucumber::Ast::Table";
|
58
|
+
$oSnippet->step_keyword = "Given";
|
59
|
+
$sActual = $this->oCuke4Php->snippetText($oSnippet);
|
60
|
+
$sExpected = array('success','
|
61
|
+
/**
|
62
|
+
* Given /^this is a step with a table\:$/
|
63
|
+
**/
|
64
|
+
public function stepThisIsAStepWithATable($aTable) {
|
65
|
+
self::markPending();
|
66
|
+
}');
|
67
|
+
self::assertEquals($sExpected, $sActual);
|
68
|
+
}
|
69
|
+
|
70
|
+
function testSnippetTextReturnsSnippetWithAMultilineString() {
|
71
|
+
$oSnippet = new StdClass;
|
72
|
+
$oSnippet->step_name = 'this is a step with a pystring:';
|
73
|
+
$oSnippet->multiline_arg_class = "Cucumber::Ast::PyString";
|
74
|
+
$oSnippet->step_keyword = "Given";
|
75
|
+
$sActual = $this->oCuke4Php->snippetText($oSnippet);
|
76
|
+
$sExpected = array('success','
|
77
|
+
/**
|
78
|
+
* Given /^this is a step with a pystring\:$/
|
79
|
+
**/
|
80
|
+
public function stepThisIsAStepWithAPystring($sString) {
|
81
|
+
self::markPending();
|
82
|
+
}');
|
83
|
+
self::assertEquals($sExpected, $sActual);
|
84
|
+
}
|
85
|
+
|
86
|
+
function testBeginScenarioShouldInvokeBeforeHooks() {
|
87
|
+
$oMockScenario = $this->getMock('CucumberScenario', array('invokeBeforeHooks'));
|
88
|
+
$oMockScenario->expects(self::once())->method('invokeBeforeHooks');
|
89
|
+
CucumberScenario::setInstance($oMockScenario);
|
90
|
+
$this->oCuke4Php->beginScenario(array());
|
91
|
+
}
|
92
|
+
|
93
|
+
function testEndScenarioShouldInvokeAfterHooks() {
|
94
|
+
$oMockScenario = $this->getMock('CucumberScenario', array('invokeAfterHooks'));
|
95
|
+
$oMockScenario->expects(self::once())->method('invokeAfterHooks');
|
96
|
+
$this->oCuke4Php->setScenario($oMockScenario);
|
97
|
+
$this->oCuke4Php->endScenario(array());
|
98
|
+
}
|
99
|
+
|
100
|
+
function testStepMatchesShouldReturnEmptySetWhenNoMatches() {
|
101
|
+
self::assertEquals(array('success',array()), $this->oCuke4Php->stepMatches("random step"));
|
102
|
+
}
|
103
|
+
|
104
|
+
function testStepMatchesShouldReturnMatches() {
|
105
|
+
self::assertEquals(array('success',array(
|
106
|
+
array('id' => 0, 'args' => array(), 'source' => realpath(dirname(__FILE__) . '/../../features/step_definitions/TestSteps.php') . ":14")
|
107
|
+
)), $this->oCuke4Php->stepMatches("successful"));
|
108
|
+
}
|
109
|
+
|
110
|
+
function testStepMatchesShouldReturnMatchesWithParameters() {
|
111
|
+
self::assertEquals(array('success',array(
|
112
|
+
array('id' => 6, 'args' => array(), 'source' => realpath(dirname(__FILE__) . '/../../features/step_definitions/TestSteps.php') . ":54")
|
113
|
+
)), $this->oCuke4Php->stepMatches('"arg1" not equal to "arg2"'));
|
114
|
+
}
|
115
|
+
|
116
|
+
}
|
117
|
+
?>
|