Skip to content

Commit 7683b5f

Browse files
committed
Merge pull request #28 from symfony-cmf/db_testing
[WIP] Improve Database testing
2 parents 1b132c7 + de636d0 commit 7683b5f

File tree

5 files changed

+365
-0
lines changed

5 files changed

+365
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
composer.lock
2+
/vendor/

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Changelog
2+
=========
3+
4+
* **2013-11-17**: Added DatabaseTestListener to support database testing

src/Symfony/Cmf/Component/Testing/HttpKernel/TestKernel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public function init()
3838
'\Doctrine\Bundle\PHPCRBundle\DoctrinePHPCRBundle',
3939
));
4040

41+
$this->registerBundleSet('doctrine_orm', array(
42+
'\Doctrine\Bundle\DoctrineBundle\DoctrineBundle',
43+
));
44+
4145
$this->registerBundleSet('sonata_admin', array(
4246
'\Sonata\BlockBundle\SonataBlockBundle',
4347
'\Sonata\AdminBundle\SonataAdminBundle',
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
<?php
2+
3+
namespace Symfony\Cmf\Component\Testing\Phpunit;
4+
5+
use Symfony\Component\Process\ProcessBuilder;
6+
use Symfony\Component\Process\Process;
7+
use Symfony\Component\HttpKernel\Kernel;
8+
use Doctrine\Common\DataFixtures\Purger;
9+
10+
class DatabaseTestListener implements \PHPUnit_Framework_TestListener
11+
{
12+
protected static $currentSuite;
13+
private $processBuilder;
14+
15+
public function __construct($processBuilder = null)
16+
{
17+
if (null === $processBuilder) {
18+
$this->processBuilder = new PrefixedProcessBuilder();
19+
$this->processBuilder->setPrefix(array('php', __DIR__.'/../../../../../../bin/console'));
20+
} else {
21+
$this->processBuilder = $processBuilder;
22+
}
23+
}
24+
25+
public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
26+
{
27+
}
28+
29+
public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
30+
{
31+
}
32+
33+
public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
34+
{
35+
}
36+
37+
public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
38+
{
39+
}
40+
41+
public function startTest(\PHPUnit_Framework_Test $test)
42+
{
43+
switch (static::$currentSuite->getName()) {
44+
case 'orm':
45+
$db = $test->getDbManager('ORM');
46+
$purger = new Purger\ORMPurger($db->getOm());
47+
break;
48+
49+
case 'phpcr':
50+
$db = $test->getDbManager('PHPCR');
51+
$purger = new Purger\PHPCRPurger($db->getOm());
52+
break;
53+
54+
default;
55+
return;
56+
}
57+
58+
$purger->purge();
59+
}
60+
61+
public function endTest(\PHPUnit_Framework_Test $test, $time)
62+
{
63+
}
64+
65+
public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
66+
{
67+
static::$currentSuite = $suite;
68+
69+
switch ($suite->getName()) {
70+
case 'orm':
71+
$this->setUpOrmDatabase($suite);
72+
break;
73+
74+
case 'phpcr':
75+
$this->setUpPhpcrDatabase($suite);
76+
break;
77+
78+
default:
79+
if (!class_exists($suite->getName())) {
80+
echo PHP_EOL.PHP_EOL.'['.$suite->getName().']'.PHP_EOL;
81+
}
82+
}
83+
}
84+
85+
private function setUpPhpcrDatabase($suite)
86+
{
87+
echo PHP_EOL.PHP_EOL;
88+
89+
$process = $this->processBuilder
90+
->setArguments(array('doctrine:phpcr:init:dbal', '--drop'))
91+
->getProcess();
92+
$process->run();
93+
94+
while (true) {
95+
if ($process->isTerminated()) {
96+
if (!$process->isSuccessful()) {
97+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
98+
$suite->markTestSuiteSkipped('[PHPCR] Error when initializing dbal: '.$output);
99+
} else {
100+
$process = $this->processBuilder
101+
->setArguments(array('doctrine:phpcr:repository:init'))
102+
->getProcess();
103+
$process->run();
104+
105+
while (true) {
106+
if ($process->isTerminated()) {
107+
if (!$process->isSuccessful()) {
108+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
109+
$suite->markTestSuiteSkipped('[PHPCR] Error when initializing repositories: '.$output);
110+
} else {
111+
echo '[PHPCR]'.PHP_EOL;
112+
}
113+
}
114+
115+
break;
116+
}
117+
}
118+
119+
break;
120+
}
121+
}
122+
}
123+
124+
private function setUpOrmDatabase($suite)
125+
{
126+
echo PHP_EOL.PHP_EOL;
127+
128+
$process = $this->processBuilder
129+
->setArguments(array('doctrine:schema:drop', '--env=orm', '--force'))
130+
->getProcess();
131+
$process->run();
132+
133+
while (true) {
134+
if ($process->isTerminated()) {
135+
if (!$process->isSuccessful()) {
136+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
137+
$suite->markTestSuiteSkipped('[ORM] Error when dropping database: '.$output);
138+
return;
139+
}
140+
break;
141+
}
142+
}
143+
144+
$process = $this->processBuilder
145+
->setArguments(array('doctrine:database:create', '--env=orm'))
146+
->getProcess();
147+
$process->run();
148+
149+
while (true) {
150+
if ($process->isTerminated()) {
151+
if (!$process->isSuccessful()) {
152+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
153+
$suite->markTestSuiteSkipped('[ORM] Error when creating database: '.$output);
154+
} else {
155+
$process = $this->processBuilder
156+
->setArguments(array('doctrine:schema:create', '--env=orm'))
157+
->getProcess();
158+
$process->run();
159+
160+
while (true) {
161+
if ($process->isTerminated()) {
162+
if (!$process->isSuccessful()) {
163+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
164+
$suite->markTestSuiteSkipped('[ORM] Error when creating schema: '.$output);
165+
} else {
166+
echo '[ORM]'.PHP_EOL;
167+
}
168+
}
169+
170+
break;
171+
}
172+
}
173+
174+
break;
175+
}
176+
}
177+
}
178+
179+
public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
180+
{
181+
if (!in_array($suite->getName(), array('phpcr', 'orm'))) {
182+
return;
183+
}
184+
185+
$process = $this->processBuilder
186+
->setArguments(array('doctrine:database:drop', '--force'))
187+
->getProcess();
188+
$process->run();
189+
190+
while (true) {
191+
if ($process->isTerminated()) {
192+
if (!$process->isSuccessful()) {
193+
$output = null !== $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput();
194+
$suite->markTestSuiteSkipped('Error when dropping database: '.$output);
195+
}
196+
}
197+
break;
198+
}
199+
}
200+
}
201+
202+
class PrefixedProcessBuilder extends ProcessBuilder
203+
{
204+
private $prefixes = array();
205+
private $activated = true;
206+
207+
public function __construct(array $arguments = array())
208+
{
209+
parent::__construct($arguments);
210+
211+
if (class_exists('Symfony\Component\HttpKernel\Kernel')) {
212+
$this->activated = Kernel::VERSION_ID <= 20400;
213+
} else {
214+
$ref = new \ReflectionMethod(get_parent_class($this), 'setPrefix');
215+
$doc = $ref->getDocComment();
216+
217+
$this->activated = false === strpos('array', $doc);
218+
}
219+
}
220+
221+
public function setPrefix($prefix)
222+
{
223+
$prefixes = is_array($prefix) ? $prefix : array($prefix);
224+
225+
if (!$this->activated) {
226+
return parent::setPrefix($prefix);
227+
}
228+
229+
foreach ($prefixes as $prefix) {
230+
$this->prefixes[] = $prefix;
231+
}
232+
233+
return $this;
234+
}
235+
236+
public function getProcess()
237+
{
238+
if (!$this->activated || 0 === count($this->prefixes)) {
239+
return parent::getProcess();
240+
}
241+
242+
$process = parent::getProcess();
243+
$command = implode(' ', array_map('escapeshellarg', $this->prefixes)).' '.$process->getCommandLine();
244+
245+
$process->setCommandLine($command);
246+
247+
return $process;
248+
}
249+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
namespace Tests\Phpunit;
4+
5+
use Symfony\Cmf\Component\Testing\Phpunit\DatabaseTestListener;
6+
7+
class DatabaseTestListenerTest extends \PHPUnit_Framework_TestCase
8+
{
9+
protected $listener;
10+
private $processBuilder;
11+
private static $i;
12+
13+
public function setUp()
14+
{
15+
$this->listener = new DatabaseTestListener($this->getProcessBuilder());
16+
self::$i = 0;
17+
}
18+
19+
public function testPhpcrTestSuite()
20+
{
21+
$suite = $this->getMock('PHPUnit_Framework_TestSuite');
22+
$suite->expects($this->any())
23+
->method('getName')
24+
->will($this->returnValue('phpcr'));
25+
26+
$this->assertProcessExecuted(array('doctrine:phpcr:init:dbal', '--drop'));
27+
$this->assertProcessExecuted(array('doctrine:phpcr:repository:init'));
28+
29+
ob_start();
30+
$this->listener->startTestSuite($suite);
31+
32+
$this->assertEquals(PHP_EOL.PHP_EOL.'[PHPCR]'.PHP_EOL, ob_get_clean());
33+
}
34+
35+
public function testOrmTestSuite()
36+
{
37+
$suite = $this->getMock('PHPUnit_Framework_TestSuite');
38+
$suite->expects($this->any())
39+
->method('getName')
40+
->will($this->returnValue('orm'));
41+
42+
$this->assertProcessExecuted(array('doctrine:schema:drop', '--env=orm', '--force'));
43+
$this->assertProcessExecuted(array('doctrine:database:create', '--env=orm'));
44+
$this->assertProcessExecuted(array('doctrine:schema:create', '--env=orm'));
45+
46+
ob_start();
47+
$this->listener->startTestSuite($suite);
48+
49+
$this->assertEquals(PHP_EOL.PHP_EOL.'[ORM]'.PHP_EOL, ob_get_clean());
50+
}
51+
52+
public function testUnknownTestSuite()
53+
{
54+
$suite = $this->getMock('PHPUnit_Framework_TestSuite');
55+
$suite->expects($this->any())
56+
->method('getName')
57+
->will($this->returnValue('not orm or phpcr tests'));
58+
59+
$this->getProcessBuilder()
60+
->expects($this->never())
61+
->method('setArguments');
62+
63+
ob_start();
64+
$this->listener->startTestSuite($suite);
65+
66+
$this->assertEquals(PHP_EOL.PHP_EOL.'[not orm or phpcr tests]'.PHP_EOL, ob_get_clean());
67+
}
68+
69+
protected function assertProcessExecuted(array $arguments, $successfull = true)
70+
{
71+
$process = $this->getMockBuilder('Symfony\Component\Process\Process')
72+
->disableOriginalConstructor()
73+
->getMock();
74+
75+
$process->expects($this->once())
76+
->method('run');
77+
78+
$process->expects($this->once())
79+
->method('isTerminated')
80+
->will($this->returnValue(true));
81+
82+
$process->expects($this->once())
83+
->method('isSuccessful')
84+
->will($this->returnValue($successfull));
85+
86+
$processPlaceholder = $this->getMock('ProcessPlaceholder', array('getProcess'));
87+
$processPlaceholder->expects($this->once())
88+
->method('getProcess')
89+
->will($this->returnValue($process));
90+
91+
$this->getProcessBuilder()
92+
->expects($this->at(self::$i++))
93+
->method('setArguments')
94+
->with($this->equalTo($arguments))
95+
->will($this->returnValue($processPlaceholder));
96+
}
97+
98+
protected function getProcessBuilder()
99+
{
100+
if (null === $this->processBuilder) {
101+
$this->processBuilder = $this->getMock('Symfony\Component\Process\ProcessBuilder');
102+
}
103+
104+
return $this->processBuilder;
105+
}
106+
}

0 commit comments

Comments
 (0)