CakePHP unit tesztelés

cakephpSokáig halogattam a PHP unit tesztekkel való megismerkedést. Így utólag kiderült, hogy egy rendkívül hasznos eszköz ami biztosabbá és fenntarthatóvá teszi a kódunkat. A cakephp eleve tartalmaz unit teszteléshez szükséges alkatrészeket, és a keretrendszer frissítésénél ütköztem egy rakat problémába ami unit tesztekkel könnyebben kezelhető lett volna.

Update: A végén azért összejött annyi érdekesség, hogy írtam az egészről egy e-bookot.

Nem fogok itt sem magukról a unit tesztekről írni, sem azokról a részletekről amik benne vannak egyértelműen a kézikönyvben. Itt csak azokra a hozzátevőkre térek ki amelyek kiderítése hosszadalmas volt.

Azt, hogy a test adatbázisban a cake_session táblát kézzel hozzá kell adni, még viszonylag gyorsan megtaláltam, de többit itt lent már nem.

Miután feltelepítettük a PHPunit-ot és létrehoztuk a test adatbázis kapcsolatot első körben létre kell hoznunk a fixture-öket. Persze ez le van írva a kézikönyvben, de ha az ember hajlamos egyből beleugrani akkor kellemetlen meglepetésekkel szembesülhet. Esetemben ez megmagyarázhatatlan átirányításokkal járt, míg végül rájöttem, hogy ha hirtelen a http://localhost címen találom magam akkor az app/tmp/logs/error.log file-t kell megnézni, mert ott lesz valami gubanc.

A másik meglepetés a controllerek tesztelésénél jött elő, ugyanis ha a $this->generate() hívásnál nem adjuk meg a components tömbben a DebugKit.Toolbar-t (már legalábbis ha egyébként használjuk), akkor szintén nehezen értelmezhető hibákba futkosunk majd bele.

A következő kihívás a Session válozók kezelése volt. Erre az a megoldás, hogy egyrészt megadjuk a $this->generate() hívás során a components tömbben a Session-t, hozzáadjuk a fixture tömbhöz a core.session-t, majd a következő kódot használjuk.

class BizonylatokControllerTest extends ControllerTestCase {
   
   public $fixtures = array('app.bizonylat', 'core.session');
   
   public function setUp() {
      parent::setUp();
      $this->Bizonylatok = $this->generate('Bizonylatok',
                                           array(
                                             'components' => array('Session', 'DebugKit.Toolbar')
                                             )
                                           );
   }

   function testBizonylatokAkarmi(){
      $this->controller->Session->expects($this->any()) #legalább egyszer
         ->method('read') #meghívjuk Session:read() metódust
         ->with($this->equalTo('Settings.cegId')) #és kiolvassuk belőle a 'Session.cegId' paramétert
         ->will($this->returnValue(2)); #akkor adjunk vissza visszatérési értékként 2-t
   }

A következő kihívás akkor jött amikor többféle session változót használt a tesztelt controller. Erre a returnCallback adott megoldást.

      $this->controller->Session->expects($this->any())
         ->method('read')
         ->with($this->logicalOr('Settings.cegId', 'Settings.ev'))
         ->will($this->returnCallback(
                           function($param){
                              if($param == 'Settings.cegId')
                                 return 2;
                              elseif($param == 'Settings.ev')
                                 return 2012;
                              else
                                 return null;
                           }
                           ));

Majd a privát metódusok tesztelése jött a sorban.

      $myClass = $this->generate('Bizonylatok');
      $class = new ReflectionClass ($myClass);
      $method = $class->getMethod ('_szamFormal');
      $method->setAccessible(true);

      $actual = $method->invoke($myClass, '5 000,25');
      $expected = 5000.25;
      $this->assertEquals($expected, $actual);

Ami még tovább fokozta az izgalmaimat az az, hogy join táblákra habtm kapcsolat esetén hiába hoztam létre a fixture-t és adtam használatra egy model teszt esetében, folyamatosan arra panaszkodott, hogy nem létezik a tábla. Jópár órányi őrület után aludtam rá egyet és bekapcsoltam a MySQL szereren, hogy loggoljon minden egyes query-t. Ebből láttam, hogy a join táblát nem jól többesszámúsítja az inflector, mivel magyar táblaneveket használok. A megoldás az lett, hogy a /app/Config/bootstrap.php file-ban hozzá kellett adnom még egy egyedi többesszámos szabályt.

Inflector::rules('plural', array(
	'irregular' => array(
		'osztaly'			=>		'osztalyok',
		'gyujto'				=>		'gyujtok',
		'gyujto_osztaly'	=>		'gyujtok_osztalyok',
		'gyujtoosztaly'	=>		'gyujtok_osztalyok'	//ez itt a test suite miatt kell
		)));

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.