更新日: 2017-09-19 (火) 12:03:24 (90d)

:PHP
CakePHP 3.2.3

CakePHP3 PHPUnit テーブルが消える

CakePHPでのユニットテストに取り組んでおります。
まだまだやり始めたばっかりなので、いろいろと間違っているところもあると思いますが、詳しい人はぜひ教えてください。

さて、いきなり全体のテストではなく、まずは試しにモデルのテストを作ってみます。

//テストする対象のモデル
//Model/Table/OffersTable.php
class OffersTable extends Table
{
 //前略
 public function findApproved(Query $query, array $options){

   	$query->where([
           'Offers.status' => 'approved'
       ]);
       $query->select(['id', 'status']);
       return $query;
   }
 //後略
}
//上記のメソッドのテストを作ります
//tests/TestCase/Model/Table/OffersTableTest.php
<?php
namespace App\Test\TestCase\Model\Table;

use App\Model\Table\OffersTable;
use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;

/**
* App\Model\Table\OffersTable Test Case
*/
class OffersTableTest extends TestCase
{
	
   public $Offers;
   public $fixtures = [
       'app.offers'
   ];

   public function setUp()
   {
       parent::setUp();
       $config = TableRegistry::exists('Offers') ? [] : ['className' => 'App\Model\Table\OffersTable'];
       $this->Offers = TableRegistry::get('Offers', $config);
   }

   public function tearDown()
   {
       unset($this->Offers);

       parent::tearDown();
   }

   public function testInitialize()
   {
       $this->markTestIncomplete('Not implemented yet.');
   }

   public function testValidationDefault()
   {
       $this->markTestIncomplete('Not implemented yet.');
   }

   public function testBuildRules()
   {
       $this->markTestIncomplete('Not implemented yet.');
   }
   

  public function testFindApproved()
   {
       $query = $this->Offers->find('approved');
       $this->assertInstanceOf('Cake\ORM\Query', $query);
       $result = $query->hydrate(false)->toArray();
       $expected = [
           ['id' => 2, 'status' => 'approved'],
       ];
       debug($result);
       $this->assertEquals($expected, $result);
   }

}

設定ファイルに、テスト用のDBの設定を書いておきます。

   'Datasources' => [

       /**
        * The test connection is used during the test suite.
        */
       'test' => [
           'className' => 'Cake\Database\Connection',
           'driver' => 'Cake\Database\Driver\Mysql',
           'persistent' => false,
           'host' => 'localhost',
           'username' => 'my_app',
           'password' => 'secret',
           'database' => 'test_myapp',
           'encoding' => 'utf8',
           'timezone' => 'UTC',
           'cacheMetadata' => true,
           'quoteIdentifiers' => false,
           'log' => false,
       ],
   ],

サーバーで、次のようにphpunitを実行します。

phpunit --filter testFindApproved tests/TestCase/Model/Table/OffersTableTest

次のように、Failureが返ってきます。

PHP Warning:  Module 'intl' already loaded in Unknown on line 0
PHPUnit 5.2.9 by Sebastian Bergmann and contributors.

F 1 / 1 (100%)/tests/TestCase/Model/Table/OffersTableTest.php (line 88)
########## DEBUG ##########
[]
###########################


Time: 149 ms, Memory: 12.00Mb

There was 1 failure:

1) App\Test\TestCase\Model\Table\OffersTableTest::testFindApproved
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
Array (
    0 => Array (
-        'id' => 2
+        'id' => 24
        'status' => 'approved'
    )
)

/var/www/html/gildotcom/tests/TestCase/Model/Table/OffersTableTest.php:89

FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

ま、これは予想されたことなのでよいのですが、問題は、test_myappデータベースから、offers というテーブルが消えてしまったことです。

は??(・A・) Oh My God!!となりますね。私の場合は、別に開発中のサーバーだったので、無問題なのですが…。

犯人は、こ・い・つ!

   public $fixtures = [
       'app.offers'
   ];

Fixtureというやつですね。
これを指定しているので、

tests/Fixture/OffersFixture.php

にある、次のフィクスチャーにあるデータが実行されていたようです。

<?php
namespace App\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

/**
* OffersFixture
*
*/
class OffersFixture extends TestFixture
{
   // @codingStandardsIgnoreStart
   public $fields = [
       'id' => ['type' => 'string', 'length' => 64, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null],
       'status' => ['type' => 'string', 'length' => 16, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null],
       'winner_id' => ['type' => 'string', 'length' => 64, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null],
       'work_type_id' => ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false],
  //以下略        
   ];
   // @codingStandardsIgnoreEnd

   public $records = [
       [
           'id' => '24a1f938-c898-4376-8a05-b8d6a614dda7',
           'status' => 'approved',
           'winner_id' => 'Lorem ipsum dolor sit amet',
           'work_type_id' => 1,
           'created' => '2016-02-02 11:22:24',
           'modified' => '2016-02-02 11:22:24'
       ],
   ];
}

そんで、そのあとDBのテーブルがDropされていた。と。

フィクスチャーはテストの際に、実際のデータに影響を与えないように、仮のテスト用データを作れるという機能です。
上記では、class OffersFixtureでデータのフィールドと、実際のデータを作っているわけですね。

下記の公式ページに
http://book.cakephp.org/3.0/en/development/testing.html#creating-a-test-method

CakePHP performs the following during the course of a fixture based test case:
・Creates tables for each of the fixtures needed.
・Populates tables with data, if data is provided in fixture.
・Runs test methods.
・Empties the fixture tables.
・Removes fixture tables from database.

要は
「そのテーブル 消えるよ」
と言ってくれていたのですが、仮のデータが消されるのかと思ってましたよ…(つД`)
本当に、テスト用のデータベースのテーブルを消すんですね!!Cake先輩!!

ちなみに、bake で自動でテストコード作ると、このように自動でFixtureを作ってくれて、Fixtureを使うようになっています。

bakeしたみなさん、ご注意を!!
app.phpのテストDBの設定を、
「本物のデータでテストしてみよー」
とか気軽に考えて、気軽に実行すると、データが全部消えることになりますから。

ということで、public $fixtures をOffersTabteTest.phpから消去し、再び

phpunit --filter testFindApproved tests/TestCase/Model/Table/OffersTableTest

すると、test_myAppDBからoffersテーブルを読み込み、次のように結果がOKとなります。

PHP Warning:  Module 'intl' already loaded in Unknown on line 0
PHPUnit 5.2.9 by Sebastian Bergmann and contributors.
 1 / 1 (100%)/tests/TestCase/Model/Table/OffersTableTest.php (line 87)
########## DEBUG ##########
[
       (int) 0 => [
               'id' => (int) 2,
               'status' => 'approved'
       ]
]
###########################

Time: 189 ms, Memory: 12.00Mb

OK (1 test, 2 assertions)

テーブルもきえませんでした! ⊂(^-^)⊃


選択肢 投票
役に立った 3  
役に立たなかった 0  
どちらでもない 0  
このページが参照された数
Total: 1377, 今日: 5, 昨日: 2

でじうぃきは神奈川県横浜市の位置情報システム・スマホアプリ開発の株式会社オンラインコンサルタントが運営しています。
投稿
トップ   このページを編集する 再編集不可にする 差分 バックアップ 添付 複製 名前変更 リロード   新しいページを作る 一覧 検索する 最新の更新   ヘルプ   最終更新のRSS
Last-modified: 2017-09-19 (火) 12:03:24 (90d)