Build Testing

Last updated on
11 March 2021

This page has not yet been reviewed by PHPUnit in Drupal maintainer(s) and added to the menu.

This documentation needs work. See "Help improve this page" in the sidebar.

Why Build Testing?

The bash functionality of drupalci.yml is intended to do minor setup work. It is *not* intended to be a bash testing framework or anything resembling that. It is not desirable to place bash scripts into drupalci.yml and then rely on the exit codes of those scripts as evidence of build success or failure.

It is preferable to have these bash scripts execute within the context of phpunit, which frames them as a standard test, and give the results in a standard way, and is runnable in environments *other than* drupalci.

Additionally, we want any developer to be able to write and execute these tests locally, and running phpunit is typical. Setting up a local drupalci, is not very typical.

Build Testing

This allows tests like the following:

use Drupal\BuildTests\Framework\BuildTestBase;

/**
 * Test whether we can install a Drupal site using the quickstart CLI.
 *
 * @group Build
 * @group Command
 * @group QuickStart
 */
class InstallTest extends BuildTestBase {

  public function providerProfile() {
    return [
      'standard' => ['standard'],
      'minimal' => ['minimal'],
      'demo_umami' => ['demo_umami'],
    ];
  }

  /**
   * @dataProvider providerProfile
   * @requires externalCommand composer
   */
  public function testInstall($profile) {
    $adminUsername = '';
    $adminPassword = '';

    // Copy the codebase to our workspace.
    $this->copyCodebase();

    // Execute composer install.
    $this->executeCommand('composer install --no-dev --no-interaction');
    // Command assertions operate on the last command executed.
    $this->assertCommandSuccessful();
    // Composer tells you stuff in error output.
    $this->assertErrorOutputContains('Generating autoload files');

    $finder = new PhpExecutableFinder();
    // You can keep the process object for later assertions or manipulations.
    $process = $this->executeCommand(
      $finder->find() . ' ./core/scripts/drupal install ' . $profile
    );
    $this->assertCommandSuccessful();
    $this->assertCommandOutputContains('Username:');
    preg_match('/Username: (.+)\vPassword: (.+)/', $process->getOutput(), $matches);
    $this->assertNotEmpty($adminUsername = $matches[1]);
    $this->assertNotEmpty($adminPassword = $matches[2]);

    // The visit() method returns a Mink object, and we can perform assertions
    // against that.
    $assert = $this->visit()->assertSession();
    $assert->elementExists('css', 'html');
    // We also have a built-in assertion to check if the generator meta on the
    // last request says this is a Drupal site.
    $this->assertDrupalVisit();

    // Do we get 404 for a path that does not exist?
    $this->visit('/does-not-exist')->assertSession()->statusCodeEquals(404);

    // Can we log in and be an administrator?
    $this->visit('/admin');
    $assert->statusCodeEquals(403);

    // Use the form to log in.
    $mink = $this->visit('/user/login');
    $assert = $mink->assertSession();
    $assert->statusCodeEquals(200);
    $assert->fieldExists('edit-name')->setValue($adminUsername);
    $assert->fieldExists('edit-pass')->setValue($adminPassword);
    $mink->getSession()->getPage()->findButton('Log in')->submit();

    // Visit the admin page as an administrator.
    $this->visit('/admin');
    $assert->statusCodeEquals(200);

    // Can we try to be an admin even though we logged out?
    $this->visit('/user/logout')->assertSession()->statusCodeEquals(200);
    $this->visit('/admin');
    $assert->statusCodeEquals(403);
  }

}

Help improve this page

Page status: Needs work

You can: