web-dev-qa-db-ja.com

定数がテストまたはphpunit.xmlで設定されていても、機能テストは定数が未定義であることを報告します

私のローカルサイト(Acquia Cloud規約)のsettings.secrets.phpファイルに(defineを介して)シークレットの存在を確認する単体テストとカーネルテストがあります。このファイルは、リポジトリにコミットされていないか、データベースに保存されていないか、エクスポートされていません。

機能テストを書いているときに、問題に遭遇しました( これはこれに似ています )。テストファイルにdefineを入れようとすると、エラーが発生し、定数が未定義であるというテストエラーが発生します。

私はこれを思いつき、prepareSettings()をオーバーライドして、機能テスト用に生成された設定ファイルに書き込みます。

  /**
   * {@inheritdoc}
   */
  protected function prepareSettings() {
    parent::prepareSettings();
    $directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
    copy(DRUPAL_ROOT . '/sites/example.secrets.settings.php', $directory . '/secrets.settings.php');
    $append_line = 'include_once dirname(__FILE__) . \'/secrets.settings.php\';';
    file_put_contents($directory . '/settings.php', $append_line, FILE_APPEND);
  }

コピーされるファイルには、偽の値を含むdefineステートメントのみが含まれます。

これは機能テストでこの問題を修正するための有効なアプローチですか、それとも他の何かを見逃して上記のコードを必要としませんでしたか?

更新

問題のコードは、その方法があるため、機能テストでのみ機能します。下位レベルのカーネルと単体テストはそれにアクセスできません。

代わりに、phpunit.xmlに定数を追加して、テストで定数を定義できることがわかりました。

    <php>
        <const name="MYMODULE_API_URL" value="https://api.myproject.localhost"/>
        <const name="MYMODULE_API_KEY" value="123456789"/>
        <!-- Set error reporting to E_ALL. -->
        <ini name="error_reporting" value="32767"/>

ただし、例外が1つあるようです。drupalGetへの呼び出しがあるBrowserTestは、Use of undefined constant例外をスローしてテストに失敗する可能性があります。その部分を理解することはできません。また、ページまたは動的キャッシュを有効にしないテストプロファイルを使用してみました-同じ結果。とりあえず、後でわかるまで、drupalGet呼び出しをコメント化する必要がありました。

ただし、phpunit.xmlに追加すると、prepareSettingsでそれを実行できなくなるか、「定数がすでに定義されています」になります。したがって、この値の存在を認識しているようです。

BrowserTest以外のコードが、コードまたはphpunit.xmlのいずれかに設定されている定数に準拠していないのに、他のテストには準拠しているのはなぜですか?

更新2

これがテストのコードです。 drupalGetの最初のループの行はエラーで失敗しますが、奇妙なことに、最後のブロックは問題なく通過します。

    foreach ($permitted as $account) {
      $this->drupalLogin($account);

      foreach ($this->entity_types as $entity_type) {
        $this->drupalGet('node/' . $entity_type['nid'] . '/edit');

        if ($entity_type['response'] === 200) {
          $this->assertLinkByHref('/node/' . $entity_type['nid'] . '/update');
          $this->assertLinkByHref('/node/' . $entity_type['nid'] . '/data');
        } else {
          $this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/update');
          $this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/data');
        }

        $this->drupalGet('/node/' . $entity_type['nid'] . '/update');
        $this->assertResponse($entity_type['response']);

        $this->drupalGet('/node/' . $entity_type['nid'] . '/data');
        $this->assertResponse($entity_type['response']);
      }

      $this->drupalLogout();
    }

    // As someone without the specific permission
    $this->drupalLogin($this->staff);

    foreach ($this->entity_types as $entity_type) {
      $this->drupalGet('node/' . $entity_type['nid'] . '/edit');
      $this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/update');
      $this->assertNoLinkByHref('/node/' . $entity_type['nid'] . '/data');
      $this->drupalGet('/node/' . $entity_type['nid'] . '/update');
      $this->assertResponse(403);
      $this->drupalGet('/node/' . $entity_type['nid'] . '/data');
      $this->assertResponse(403);
    }
1
Kevin

問題のコードは、その方法があるため、機能テストでのみ機能します。下位レベルのカーネルお​​よび単体テストはそれにアクセスできないため、失敗します。

代わりに、phpunit.xmlに定数を追加して、テストで定数を定義できることがわかりました。

    <php>
        <const name="MYMODULE_API_URL" value="https://api.myproject.localhost"/>
        <const name="MYMODULE_API_KEY" value="123456789"/>
        <!-- Set error reporting to E_ALL. -->
        <ini name="error_reporting" value="32767"/>

次に、機能テストからprepareSettingsメソッドを削除できます。ただし、drupalGetを使用するテストが構成ファイルで定義されていても、未定義の定数エラーで失敗することがある別のバグ(私は追跡できません)があるようです(コードでも実行できます)。まだ失敗します)。

ここで私の唯一の推測は、phpunit.xmlから定義された構成を取得しない新しいプロセスの生成に関する問題、またはファイルが順不同にロードされる(テストファイルの定数が表示されない?)ことです。

私は次の事に決めました。 phpunit.xmlで定義された定数を残したので、ユニット/カーネルテストでは、テストでそれらを散らかす必要はありませんでした。機能テストでは、いくつかの変更を加えてprepareSettingsを元に戻しました。

  protected function prepareSettings() {
    parent::prepareSettings();
    $directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
    copy(DRUPAL_ROOT . '/sites/functional.settings.php', $directory . '/functional.settings.php');
    $append = 'include dirname(__FILE__) . \'/functional.settings.php\';';
    file_put_contents($directory . '/settings.php', $append, FILE_APPEND | LOCK_EX);
  }

ファイルの内容:

/**
 * @file
 * Functional tests settings file.
 *
 * There is a weird bug where constants are not recognized in certain cases
 * in functional tests, despite them being defined in phpunit.xml.dist.
 *
 * Functional tests should include any required constants here to avoid this
 * bug.
 *
 * @see https://drupal.stackexchange.com/questions/292713/functional-tests-report-constants-are-undefined-even-if-the-constant-is-set-in
 */

if (!defined('MYMODULE_API_URL')) {
  define('MYMODULE_API_URL', 'https://api.docker.localhost');
}

if (!defined('MYMODULE_API_key')) {
  define('MYMODULE_API_key', 'foobar');
}

これで、機能テストでdrupalGetへのすべての呼び出しのコメントが解除され、すべてのテストが未定義の定数に関するエラーなしで合格しています。

0
Kevin