2009-10-31 6 views
10

Ho appena iniziato a utilizzare PHPUnit, ma ho incontrato un po 'di difficoltà.Gestione dei problemi relativi ai percorsi con PHPUnit

Il mio codice utilizza $ _SERVER ['DOCUMENT_ROOT'] per calcolare i percorsi per include, che funziona quando il mio server Apache è quello che esegue PHP, ma DOCUMENT_ROOT non è impostato quando eseguo phpunit dalla riga di comando con "phpunit Test" , quindi questi include non funzionano.

Mi manca qualcosa nella configurazione di PHPUnit? Dovrebbe in qualche modo essere integrato con Apache?

risposta

14

risposta tardiva, mi spiace.

No, non ti manca nulla. PHP CLI (PHP per la riga di comando) è una bestia diversa da PHP come un modulo Apache/CGI.

cosa si potrebbe fare, anche se è cambiare la setUp() dei file per impostare $_SERVER['DOCUMENT_ROOT'] a quello che vi serve (dal $_SERVER è ancora disponibile come superglobale anche nel contesto CLI), ad esempio, :

public function setUp() { 
    $_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__) . "/../application"; 
} 

Basta essere attenti, probabilmente vogliono mettere questo nella vostra tearDown():

public function tearDown() { 
    unset($_SERVER['DOCUMENT_ROOT']); 
} 

PHPUnit backs up your global state se si utilizzano dati globali (anche superglobale) a tutti, che può rallentare i test verso il basso in modo drammatico, quindi perché è meglio evitare di averne dopo che un test è stato eseguito.

0

Il modo migliore sarebbe quello di disaccoppiare il codice dall'uso dello $_SERVER o di qualsiasi altro array globale. Per esempio fare

class MyClass 
{ 
    protected $_docroot; 

    public function __construct($docroot) 
    { 
     $this->_docroot = $docroot; 
    } 

    public function getDocRoot() 
    { 
     return $this->_docroot; 
    } 
} 

invece di

class MyClass 
{ 
    public function getDocRoot() 
    { 
     return $_SERVER['DOCUMENT_ROOT']; 
    } 
} 

Questo ti permette di fare

// in your actual code 
$instance = new MyClass($_SERVER['DOCUMENT_ROOT']); 
$docroot = $instance->getDocRoot(); 

// in your test 
$instance = new MyClass($variable_holding_the_correct_path); 
$docroot = $instance->getDocRoot(); 

Si prega di essere consapevoli che questo è solo un semplice esempio di disaccoppiamento. Potrebbe essere molto più complicato nel tuo caso, ma in generale vale la pena, specialmente se stai eseguendo dei test unitari.

+0

Il problema diventa, come posso includere il file che contiene questa classe? –

+0

Ah OK - Vedo il problema ... Ho leggermente frainteso il reale background della tua domanda. Non dovresti fare affidamento sull'inclusione di file usando qualsiasi variabile d'ambiente (incluso '$ _SERVER ['DOCUMENT_ROOT']'). Potrebbe essere possibile includere i file utilizzando percorsi relativi, ad es. 'require_once dirname (__ FILE__). '/ MyClass.php''? D'altra parte è possibile impostare una sorta di autoloading ... –

1

$_SERVER['DOCUMENT_ROOT'] può anche essere impostata nel file Bootstrap e lo stesso Bootstrap_test.php è allegato al file di configurazione PHPUnit phpunit.xml con l'attributo name bootstrap=Bootstrap_test.php

sono stato in grado di raggiungere il requisito per impostare $ _SERVER [ 'DOCUMENT_ROOT'] per la configurazione del lavoro di Jenkins. Il "Bootstrap_test.php" si presenta come

<phpunit 

    backupGlobals="false" 

    backupStaticAttributes="false" 

    strict="true" 

    verbose="true" 

    bootstrap="Bootstrap_test.php"> 

    <testsuites> 

    <testsuite name="PHPUnit Test Suite"> 

    <file>PHPUnitTest.php</file> 

    </testsuite> 

    </testsuites> 

    <logging> 

    <log type="coverage-clover" target="logs/clover.xml"/> 

    </logging> 

</phpunit> 

e il contenuto in Bootstrap.php si dichiara usando define() funzione:

define('BASE_PATH', realpath(dirname(__FILE__)));  
$_SERVER['DOCUMENT_ROOT'] = BASE_PATH; 

La variabile BASE_PATH deterrà di norma il percorso completo della directory di lavoro Jenkins. Dì, il nome del lavoro Jenkins è Test_Job. La directory in cui Jenkins inserirà il codice sorgente del progetto è /var/lib/jenkins/jobs/Test_Job/workspace (assumendo la directory di lavoro di jenkins come /var/lib/jenkins).

Se Bootstrap_test.php viene inserito nella directory di base, BASE_PATH si terrà /var/lib/jenkins/jobs/Test_Job/workspace e infine impostato su $_SERVER['DOCUMENT_ROOT'].

0

Desidero semplicemente documentare chiamando un altro file php (come config.php) dai test PHPUnit interni.
Ho una classe di prova:

class xyzTest extends TestCase { 

    public static function setUpBeforeClass() { 
     require_once __DIR__ . '/../../app/config/Config.php'; 
    } 

... 

In config.php ho creato alcune costanti, come i percorsi dei file. Questi percorsi sono relativi a $_SERVER['DOCUMENT_ROOT'].
Voglio testare la mia classe xyz utilizzando queste costanti di percorso.
Tuttavia, il superglobale $_SERVER è vuoto quando si chiama PHPUnit dalla riga di comando. Ho provato a seguire il buon consiglio da un answer above e impostare il $_SERVER['DOCUMENT_ROOT'] in PHPUnits setUp metodi. Questo non ha risolto il mio problema.

ho riparato con l'aggiunta di un if dichiarazione nel mio Config.php, in questo modo:

if ($_SERVER['DOCUMENT_ROOT']) { 
    $DocumentRoot = realpath($_SERVER['DOCUMENT_ROOT']); 
} else { 
    $DocumentRoot = realpath(dirname(__FILE__) . '/../..'); //for PHPUnit 
} 

Spero che questo consente di risparmiare qualcuno mal di testa.