web-dev-qa-db-ja.com

Joomla 2.5コンポーネントをテストする方法

私は StackOverflow でこの質問をしました、そして私はここでそれを尋ねることが提案されました。

ユニット/システム/統合テストに精通しており、Joomlaコンポーネントをテストできるようにしたいと考えています。これを行う標準的な方法はありますか?

私は このjoomla mvcコンポーネントの例 に取り組んでいます。これにはテストが含まれていません。 JoomlaのドキュメントやさまざまなWebサイトで見つけることができるのは、テストコードのフラグメントとbootstrap.phpファイルだけです。具体的に私が知りたいのは:

  • コンポーネントテストコードを配置する場所
  • 独自のbootstrap.phpを提供する必要がありますか、それとも単に「joomlaを含めて」テストを実行する方法がありますか

理想的には、誰かが私にオープンソースのJoomlaコンポーネントを教えてくれ、それらを実行する方法についてのテストと指示を持っている(最初の5つにはテストがなかった)。

私が見つけた最も近いものは this であり、これは私のダミーテストに基づいています。

これまでに行ったこと

コンポーネントのディレクトリ構造:

  • こんにちは世界/
    • admin /
      • ...
      • テスト/
        • bootstrap.php
        • phpunit.xml
        • modelHelloWorldsTest.php
    • 地点/
      • ...
    • helloworld.xml

最初の試み

テストを実行するために、コンポーネントをJoomlaインストールにインストール/コピーします。次に、〜joomla/administration/components/com_helloworld/testsから次のコマンドを実行します。

php phpunit-4.2.phar --bootstrap bootstrap.php .

私が受け取るところ

Fatal error: Class 'ContentController' not found in C:\inetpub\wwwroot\ws_cairnstest\administrator\components\com_helloworld\tests\modelsHelloWorldsTest.php on line 5

これは、私のbootstrap.phpが正しくなく、必要なJoomlaクラスがロードされていないことを意味します。私はいつかこれを調査しますが、これはいくつかのテストを実行するためだけに多くの設定のようです。

bootstrap.php:

<?php
error_reporting(E_ALL);

define('_JEXEC', 1);
define('BASEPATH',realpath(dirname(__FILE__).'/../../'));
define('JOOMLA_PATH',realpath(dirname(__FILE__).'/../../../../../'));
define('JOOMLA_ADMIN_PATH',realpath(dirname(__FILE__).'/../../../../'));
$_SERVER['HTTP_Host'] = 'localhost';
$_SERVER['REQUEST_METHOD'] = 'GET';

if (file_exists(JOOMLA_ADMIN_PATH . '/defines.php'))
{
    include_once JOOMLA_ADMIN_PATH . '/defines.php';
}

if (!defined('_JDEFINES'))
{
    define('JPATH_BASE', JOOMLA_ADMIN_PATH);
    require_once JPATH_BASE . '/includes/defines.php';
}

require_once JPATH_BASE . '/includes/framework.php';
require_once JPATH_BASE . '/includes/helper.php';
require_once JPATH_BASE . '/includes/toolbar.php';
define('JPATH_COMPONENT',JOOMLA_ADMIN_PATH.'/components/com_content');
$app = JFactory::getApplication('administrator');
include BASEPATH.'/controller.php';

modelsHelloWorldsTest.php:

<?php
class HelloWorldsTest extends \PHPUnit_Framework_TestCase {

    public function testList(){
        $c = new ContentController();
        $model = $c->getModel('helloworlds');
        $worlds = $model->getItems();
        var_dump($worlds);
        $this->assertNotEmpty($worlds);
    }
}

phpunit.xml:

<phpunit bootstrap="bootstrap.php"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnFailure="false"
    syntaxCheck="false"
    verbose="true">
</phpunit>

2回目の試み

この回答 が表示された後、私はテストをjoomlaインストールの下のtest/unitの下に置き、phpunit.dist.xmlとbootstrap.phpをjoomla-cmsリポジトリから適切な場所にコピーしましたが、

Fatal error: Class 'ContentController' not found in C:\inetpub\wwwroot\ws_cairnstest\administrator\components\com_helloworld\tests\modelsHelloWorldsTest.php on line 5

以前受けていたエラー。

12
uozuAho

コンポーネントテストコードを配置する場所

通常、ベストプラクティスは次のとおりです。

/src/
/tests/

しかし、/ srcをスキップし、コンポーネントディレクトリ内の/ tests /だけをスキップしました。フロントエンドでは、「abc」コンポーネントの場合、次のようになります。

/components/com_abc/
/components/com_abc/abc.php
/components/com_abc/controller.php
/components/com_abc/router.php
/components/com_abc/tests/
/components/com_abc/tests/controllerTest.php

自分のbootstrap.phpを提供する必要がありますか

やった。ちょっと。ルートのindex.phpファイルの便利な機能を単体テストスクリプトの先頭にコピーしました。あなたのものは私のものに近かった。次のステップは、require_once()が必要な別のファイルにカプセル化することです。

<?php

error_reporting(E_ALL);

define('_JEXEC', 1);
define('_PHPUNIT', 1);
define('JPATH_BASE', "/var/www/html/abcsite");

require_once JPATH_BASE . '/includes/defines.php';
require_once JPATH_BASE . '/includes/framework.php';

// Instantiate the application.
$app = JFactory::getApplication('site');

// Include dependancies
require_once '../controller.php';

// This is specific to this component
define('JPATH_COMPONENT', JPATH_BASE . "/components/com_abc");

class controllerTest extends PHPUnit_Framework_TestCase
{
    public function testCronjob()
    {

        // Need access to the controller
        $controller = JController::getInstance('Abc');

        // Should return
        $this->assertEquals('test', $controller->execute("cronjob"));

    }
...

理想的には、誰かが私にオープンソースのJoomlaコンポーネントを教えてくれます。テストとその実行方法の説明があります(最初の5つにはテストがありませんでした)。

自分でロールするのは簡単だと思いました。 phpunit.xmlを設定する手間もありませんでした。

3
Tone Garot

私の答えがあなたの問題に直接対処していない場合は申し訳ありませんが、Joomlaについて話しているかどうかに関係なく、ユニットテストとは何か、およびその使用方法を理解することが重要です。あなたは多くの問題に対処しましたが、それらすべてに対処することはかなり困難です。

まず第一に PHPUnit にあるドキュメントを読むことが重要です。 (Joomlaから独立して)小さなクラスを自分で構築し、そのためのテストをいくつか書いてみましょう。このようなシナリオで最初に実行するPHPUnitを入手してください。それが何をするかを理解してください。 PHPUnitが開発にどのように役立つかを理解するのではなく、PHPUnitを実行することに集中しすぎていると思います。

Joomlaを実行するには、次のものが必要です。

  • bootstrap.php-Joomlaのインスタンスを提供します。
  • phpunit.xml-PHPUnit設定の微調整。たとえば、各コンポーネントのテストフォルダーがあるプロジェクト全体に対して1回指定する場合に役立ちます。そのため、一連のテストを実行できます。

発生しているエラーはできるだけ明確です。 'ContentController'は明らかにJoomlaによって自動ロードされません。 Joomlaのオートローダーが呼び出されているかどうかと、クラスのロードに失敗した理由をデバッガーで確認してください。最悪のシナリオでは、独自のオートローダーを提供し、bootstrapファイルを使用してそれを呼び出します。簡単な修正は、require_onceで必要なファイルを手動でロードすることでもあります。

テストするものを決定し、モックアップを使用します

提供されている例では、JModelを使用してデータベースからデータをフェッチしています。これはTDDの観点からは立ち入り禁止です。データベースからデータをフェッチできることをテストすることには、IMHOの価値はありません。そこで何をテストしていますか?

データベースのデータを操作する必要がある場合は、モックを使用してデータベースからの応答をモデル化します。このようにして、テストは長期にわたって一貫した動作をします。データベースで何かを変更したからといって、テストが失敗したくはありません。

あなたが何かをテストする意味がある何かを計算するメソッドがある場合。これはユニットテストです。複雑なシステムから小さなユニットを取り出し、偽のテストデータをフィードして、その動作をテストします。

システムが全体として機能することを確認する必要がある場合は、システムテストを使用してください。

6
Valentin Despa