CakePHPのサンプルプログラムをテストしてみる

CakePHPでサンプルプログラムを作成してみる

CentOSにxdebugとphpunitをインストールしてみる
の続き

CakePHPで作成したサンプルのプログラムをテストしてみる。

ヘルパーのテスト

app/Test/Case/View/Helper/PriceHelperTest.php
を作成する。

<?php
App::uses('Controller', 'Controller');
App::uses('View', 'View');
App::uses('PriceHelper', 'View/Helper');

/**
 * PriceHelperのテスト
 */
class PriceHelperTest extends CakeTestCase {

  /**
   * 初期設定
   */
  public function setUp() {
    parent::setUp();
    $Controller = new Controller();
    $View = new View($Controller);
    $this->Price = new PriceHelper($View);
  }

  /**
   * formatメソッドのテスト
   */
  public function testFormat() {
    $result = $this->Price->format(999);
    $this->assertNotContains(',', $result);

    $result = $this->Price->format(1000);
    $this->assertContains(',', $result);
  }
}

モデルのテスト

まず、
app/Config/database.php
を編集し、$testのユーザー名とパスワードとデータベース名を設定する。
今回は、テスト用データベースとしてtestを使用する。

MySQLインストール時に最初から用意されているtestデータベース
mysql> show databases;
                                          • +
Database
                                          • +
information_schema
mysql
sample
test ←これ
                                          • +
<?php
・・・
class DATABASE_CONFIG {
  ・・・

  public $test = array(
    'datasource' => 'Database/Mysql',
    'persistent' => false,
    'host' => 'localhost',
    'login' => 'ユーザ名',	←ユーザー名を設定する
    'password' => 'パスワード',	←パスワードを設定する
    'database' => 'test',	←testデータベースを設定する。
    'prefix' => '',
    //'encoding' => 'utf8',
  );
}

次に、テスト用のサンプルデータとして、
app/Test/Fixture/ItemFixture.php
を作成する。

<?php
/**
 * Itemのテスト用データ
 */
class ItemFixture extends CakeTestFixture {

  public $useDbConfig = 'test';
  public $fields = array(
    'id'	=> array('type' => 'integer', 'key' => 'primary'),
    'name'	=> array('type' => 'string', 'length' => 32, 'null' => true),
    'price'	=> array('type' => 'integer', 'default' => '0', 'null' => true),
  );
  public $records = array(
    array('id' => 1, 'name' => 'apple',  'price' => 100),
    array('id' => 2, 'name' => 'orange', 'price' => 200),
    array('id' => 3, 'name' => 'banana', 'price' => 300),
  );

}

app/Test/Case/Model/ItemTest.php
を作成する。

<?php
App::uses('Item', 'Model');

/**
 * ItemModelのテスト
 */
class ItemTest extends CakeTestCase {

  public $fixtures = array('app.item');

  /**
   * 初期設定
   */
  public function setUp() {
    parent::setUp();
    $this->Item = ClassRegistry::init('Item');
  }

  /**
   * getAllメソッドのテスト(正常系)
   */
  public function testAdd() {
    $result = $this->Item->getAll();
    $this->assertEquals(3, count($result));

    $this->Item->add('grape', 400);
    $result = $this->Item->getAll();
    $this->assertEquals(4, count($result));
  }

  /**
   * getAllメソッドのテスト(異常系)
   */
  public function testAddNg() {
    $result = $this->Item->add('123456789', 400);
    $this->assertFalse($result);
    $this->assertArrayHasKey('name', $this->Item->validationErrors);

    $result = $this->Item->add('grape', 'aaa');
    $this->assertFalse($result);
    $this->assertArrayHasKey('price', $this->Item->validationErrors);
  }

}

コントローラのテスト

app/Test/Case/Controller/SampleControllerTest.php
を作成する。

<?php
/**
 * SampleControllerのテスト
 */
class SampleControllerTest extends ControllerTestCase {

  public $fixtures = array('app.item');

  /**
   * indexメソッドのテスト
   */
  public function testIndex() {
    $result = $this->testAction('/sample/index', array('return' => 'vars'));

    $this->assertEquals(200, $result['avg']);
    $this->assertEquals(600, $result['sum']);
    $this->assertEquals(3, count($result['items']));
  }

  /**
   * addメソッドのテスト(正常系)
   */
  public function testAdd() {
    $result = $this->testAction(
      '/sample/add',
      array('data' => array('name' => 'grape', 'price' => 400), 'method' => 'post', 'return' => 'headers')
    );
    // returnにheadersを指定した場合、redirectすると、resultに下記のような配列が設定される。
    // Array([Location] => http://サーバーのアドレス/cakephp/sample/)
    $this->assertArrayHasKey('Location', $result);
  }

  /**
   * addメソッドのテスト(異常系)
   */
  public function testAddNg() {
    $result = $this->testAction(
      '/sample/add',
      array('data' => array('name' => 'grape', 'price' => 'no_number'), 'method' => 'post', 'return' => 'contents')
    );
    $this->assertFalse(isset($result['Location']));
  }

}

コンポーネントのテスト

app/Test/Case/Controller/Component/PriceComponentTest.php
を作成する。

<?php
App::uses('Controller', 'Controller');
App::uses('CakeRequest', 'Network');
App::uses('CakeResponse', 'Network');
App::uses('ComponentCollection', 'Controller');
App::uses('PriceComponent', 'Controller/Component');

/**
 * Componentのテスト用のダミークラス
 */
class DummyController extends Controller {
}

/**
 * PriceComponentのテスト
 */
class PriceComponentTest extends CakeTestCase {

  public $PriceComponent = null;
  public $Controller = null;

  /**
   * 初期設定
   */
  public function setUp() {
    parent::setUp();
    $Collection = new ComponentCollection();
    $this->PriceComponent = new PriceComponent($Collection);
    $this->Controller = new DummyController(new CakeRequest(), new CakeResponse());
    $this->PriceComponent->startup($this->Controller);
  }

  /**
   * getSumメソッドのテスト
   */
  public function testSum() {
    $items = array(
      array('Item' => array('price' => 100)),
      array('Item' => array('price' => 200)),
      array('Item' => array('price' => 300)),
    );
    $result = $this->PriceComponent->getSum($items);
    $this->assertEquals(600, $result);
  }

  /**
   * getAverageメソッドのテスト
   */
  public function testAverage() {
    $items = array(
      array('Item' => array('price' => 100)),
      array('Item' => array('price' => 200)),
      array('Item' => array('price' => 300)),
    );
    $result = $this->PriceComponent->getAverage($items);
    $this->assertEquals(200, $result);
  }

  /**
   * 後処理
   */
  public function tearDown() {
    parent::tearDown();
    unset($this->PriceComponent);
    unset($this->Controller);
  }

}

以上で

ブラウザで
http://(CakePHPの設置先)/test.php
にアクセスすると、今回作成したテストが表示される。

クリックするとテストが実行される。