2012-03-12 13 views
8

estoy aprendiendo y explorando las aplicaciones de PHPUnit con PHP 5.2.9 y se han encontrado con el problema de globales. Me he puesto $ backupGlobals a FALSO, incluido el doc '@backupGlobals discapacitados' y esto no parece afectar el comportamiento de PHPUnit de copia de seguridad de las variables globales. ¿Se me escapa algo? ¿Debo modificar el archivo xml de PHPUnit? Crear un bootstrap?PHPUnit y Globals

config.php:

$testString = 'Hello world!'; 

basicApp.php:

require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\config.php'); 

class BasicApp { 

public $test; 

public function __construct() { 
    global $testString; 
    $this->test = $testString; 
} 

public function getTest() { 
    return $this->test; 
} 

public function setTest($test){ 
    $this->test = $test; 
} 

BasicAppTest.php:

require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\BasicApp.php'); 

class BasicAppTest extends PHPUnit_Framework_TestCase{ 
    protected $testClass; 
    protected $backupGlobals = FALSE; 
    protected $backupGlobalsBlacklist = array('testString'); 

    public function SetUp(){ 
     $this->testClass = new BasicApp; 
     $this->testClass->bootstrap(); 
    } 

    public function testGlobal(){ 
     echo $this->testClass->getTest(); 
     $this->assertNotNull($this->backupGlobals); 
     $this->assertFalse($this->backupGlobals); 
     $this->assertNotEmpty($this->testClass->test); 
    } 

    public function testMethods(){ 
     $this->testClass->setTest('Goodbye World!'); 
     echo $this->testClass->getTest(); 
     $this->assertNotNull($this->backupGlobals); 
     $this->assertNotNull($this->testClass->test); 
     if (empty($this->testClass->test)) echo 'Method set failed!'; 
    } 
} 

testGlobal() falla en $ this-> assertNotEmpty ($ this -> testClass-> test), lo que indica que $ this-> backupGlobals está establecido en FALSE y que los globales todavía están siendo respaldados por PHPUnit.

EDIT: Tengo este trabajo al hacer la siguiente cambios-

BasicAppTest.php:

protected $backupGlobals = FALSE; <- REMOVED 
    protected $backupGlobalsBlacklist = array('testString'); <- REMOVED 

config.php:

global $testString; <- ADDED 
$testString = 'Hello world!'; 

estoy anonadado de que esto no tiene ha sido cubierto antes en alguna parte!

+1

es la línea '$ testString mundial;' necesita? Tengo entendido que la palabra clave 'global' en el ámbito global no tiene ningún efecto porque ya se encuentra en el ámbito global. –

+1

@DavidHarkness que no hay manera de saber cuando se escribe el código si se encuentra en el ámbito global o no. El hecho de que esté en el alcance principal del archivo y no dentro de una función no significa que estará en alcance global en el tiempo de ejecución.Si ese archivo está 'include'd dentro de una función, en realidad estará en el alcance de esa función, incluso en el alcance principal del archivo. Por este motivo, generalmente se considera la mejor práctica declarar siempre una variable que desea que sea global como tal con la palabra clave 'global'. De esa forma sabrá que será global sin importar qué. –

Respuesta

10

En su caso de prueba está definiendo una nueva propiedad $backupGlobals que PHPUnit no verá. Dado que la propiedad está protegido, puede configurarlo para que false en el constructor, pero PHPUnit utiliza sus constructores para pasar información sobre cómo ejecutar el método de ensayo. En su lugar, crear un phpunit.xml configuration file para establecer la propiedad backupGlobals a false.

<phpunit backupGlobals="false"> 
    <testsuites> 
     <testsuite name="Test"> 
      <directory>.</directory> 
     </testsuite> 
    </testsuites> 
</phpunit> 
+0

Muchas gracias. Me he golpeado la cabeza contra esto durante la mayor parte de la semana pasada en busca de la pieza faltante. ¡Supuse que las subcategorías podrían sobrescribir las propiedades protegidas! Muy bien, seguimiento rápido: ¿a dónde va el archivo .xml? – Malovich

+0

Lo puse en la raíz de mi carpeta 'tests', pero puede ir a cualquier parte. Puedes apuntarle a 'phpunit' con el parámetro' --configuration' (creo que '-c' se agregó como un acceso directo recientemente). Si está en el directorio actual y se llama 'phpunit.xml', PHPUnit lo recogerá automáticamente. –

+2

... de alguna manera, esto se deslizó en la red. Si va a usar variables globales con PHPUnit, necesita declarar la variable global en el espacio global (y asignarle el valor) y declarar su inclusión donde sea necesaria localmente. El comportamiento predeterminado con PHP es que las variables inicializadas en el espacio global se vuelven globales. ¡PHPUnit cambia este valor predeterminado! – Malovich

2

En sus ediciones y comentarios que he señalado una solución para el problema (que declara explícitamente variables globales dentro de la aplicación probada). En onlab's comment to a PHPUnit issue explica el comportamiento: cuando se incluye un archivo en una función, PHP coloca globales de los archivos incluidos en el alcance de la función. PHPUnit carga archivos en una función, y aunque intenta extraer globales, falla en los casos que he intentado.

Por desgracia, no he sido capaz de reproducir los problemas de mi sistema de legado en los casos de prueba mínimos (y que tenía problemas para entender el suyo), y por lo tanto no puedo confirmar la explicación. Pero su solución sugerida me ayudó: proporcionar un archivo bootstrap con la opción --bootstrap; en él, declare cada global utilizado por las partes probadas de su aplicación. Esto evita la necesidad de modificar la aplicación para probarla. Aquí está el ejemplo de OnLab de GitHub:

phpunit --bootstrap bootstrap.php test-path 

con bootstrap.php:

global $my, $system, $globals, $here; 
require_once("/path/to/my/system/bootstrap.php"); 
+1

Tanto en el enlace como en su copia y pega hay un pequeño error tipográfico. Debería leer: 'global $ my, $ system, $ globals, $ here; ', es decir, sin los' seguidos '. – Ognyan