2012-03-12 13 views
8

Uczę się i odkrywam aplikacje PHPUnit z PHP 5.2.9 i mam problem z globalizacją. Ustawiłem $ backupGlobals na FALSE, włączając dokument "@backupGlobals wyłączony" i to nie wpływa na zachowanie tworzenia kopii globalnych przez PHPUnit. Czy jest coś, czego mi brakuje? Czy muszę zmienić plik xml PHPUnit? Utworzyć bootstrap?PHPUnit i 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() nie powiedzie się na $ this-> assertNotEmpty ($ this -> testClass-> test), wskazując, że $ this-> backupGlobals jest ustawione na FALSE i że globale nadal są tworzone przez PHPUnit.

EDIT: mam tej pracy poprzez następujące changes-

BasicAppTest.php:

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

config.php:

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

Jestem oszołomiony, że nie ma gdzieś się gdzieś podziały!

+1

Czy linia 'global $ testString;' potrzebne? Rozumiem, że słowo kluczowe "global" w zasięgu globalnym nie ma żadnego efektu, ponieważ jesteś już w zasięgu globalnym. –

+1

@DavidHarkness Nie masz możliwości dowiedzenia się, kiedy piszesz kod, niezależnie od tego, czy jesteś w zasięgu globalnym czy nie. Tylko dlatego, że znajdujesz się w głównym zakresie pliku, a nie wewnątrz funkcji, nie oznacza to, że będziesz znajdować się w zasięgu globalnym w czasie wykonywania.Jeśli ten plik jest 'include'd wewnątrz funkcji, faktycznie będziesz w zasięgu tej funkcji, nawet w głównym zakresie pliku. Z tego powodu ogólnie uważa się za najlepszą praktykę, aby zawsze zadeklarować zmienną, która ma być globalna jako taka ze słowem kluczowym "global". W ten sposób wiesz, że będzie globalna bez względu na wszystko. –

Odpowiedz

10

W twoim przypadku testowym definiujesz nową właściwość , której PHPUnit nie zobaczy. Ponieważ właściwość jest chroniona, można ją ustawić w konstruktorze na false, ale PHPUnit używa swoich konstruktorów do przekazywania informacji o sposobie uruchamiania metody testowania. Zamiast tego należy utworzyć phpunit.xml configuration file, aby ustawić właściwość backupGlobals na false.

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

Dziękuję bardzo. Uderzyłem moją głową o to przez większą część ubiegłego tygodnia, szukając brakującego elementu. Sądziłem, że chronione właściwości mogą zostać nadpisane przez podklasy! Dobra, krótka kontynuacja: dokąd zmierza plik .xml? – Malovich

+0

Umieściłem go w katalogu głównym mojego folderu 'tests', ale może on być wszędzie. Możesz wskazać na nią 'phpunit' używając parametru' --configuration' (prawdopodobnie ostatnio dodano '-c' jako skrót). Jeśli znajduje się w bieżącym katalogu i nazywa się 'phpunit.xml', PHPUnit automatycznie go pobierze. –

+2

... jakoś to spadło na sieć. Jeśli zamierzasz używać zmiennych globalnych w PHPUnit, musisz zadeklarować zmienną globalną w przestrzeni globalnej (i przypisać jej wartość) i zadeklarować jej włączenie tam, gdzie jest potrzebne lokalnie. Domyślne zachowanie w PHP polega na tym, że zmienne zainicjowane w przestrzeni globalnej są globalne. PHPUnit zmienia tę wartość domyślną! – Malovich

2

W swoich edycjach i komentarzach wskazano jedno obejście problemu (jawnie deklarowanie globów w testowanej aplikacji). W onlab's comment to a PHPUnit issue wyjaśnia zachowanie: przy włączaniu pliku do funkcji PHP umieszcza globale z dołączonych plików w zakresie funkcji. PHPUnit ładuje pliki w funkcji i mimo że próbuje wyodrębnić globale, nie powiedzie się w przypadkach, które próbowałem.

Niestety, nie byłem w stanie odtworzyć problemów z mojego starego systemu w minimalnych testach (i miałem problemy ze zrozumieniem twojego), więc nie mogę naprawdę potwierdzić wyjaśnienia. Ale jego sugerowane obejście pomogło mi: dostarczyć plik bootstrap za pomocą opcji --bootstrap; w nim zadeklaruj wszystkie globalne używane przez testowane części twojego wniosku. Dzięki temu unika się konieczności modyfikacji aplikacji w celu jej przetestowania. Oto przykład onlab jest z GitHub:

phpunit --bootstrap bootstrap.php test-path 

z bootstrap.php:

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

Zarówno w linku, jak iw kopiuj i wklej znajduje się mała literówka. Powinno to brzmieć: 'global $ my, $ system, $ globals, $ here;', tj. Bez końcowych 's'. – Ognyan