You are here

TestBaseTest.php in Drupal 8

File

core/modules/simpletest/tests/src/Unit/TestBaseTest.php
View source
<?php

namespace Drupal\Tests\simpletest\Unit;

use Drupal\Tests\UnitTestCase;

/**
 * @requires extension curl
 * @coversDefaultClass \Drupal\simpletest\TestBase
 * @group simpletest
 * @group TestBase
 */
class TestBaseTest extends UnitTestCase {

  /**
   * Helper method for constructing a mock TestBase object.
   *
   * TestBase is abstract, so we have to mock it. We'll also
   * mock the storeAssertion() method so we don't need the database.
   *
   * @param string $test_id
   *   An identifying name for the mocked test.
   *
   * @return object
   *   Mock of Drupal\simpletest\TestBase.
   */
  public function getTestBaseForAssertionTests($test_id) {
    $mock_test_base = $this
      ->getMockBuilder('Drupal\\simpletest\\TestBase')
      ->setConstructorArgs([
      $test_id,
    ])
      ->setMethods([
      'storeAssertion',
    ])
      ->getMockForAbstractClass();

    // Override storeAssertion() so we don't need a database.
    $mock_test_base
      ->expects($this
      ->any())
      ->method('storeAssertion')
      ->will($this
      ->returnValue(NULL));
    return $mock_test_base;
  }

  /**
   * Invoke methods that are protected or private.
   *
   * @param object $object
   *   Object on which to invoke the method.
   * @param string $method_name
   *   Name of the method to invoke.
   * @param array $arguments
   *   Array of arguments to be passed to the method.
   *
   * @return mixed
   *   Value returned by the invoked method.
   */
  public function invokeProtectedMethod($object, $method_name, array $arguments) {
    $ref_method = new \ReflectionMethod($object, $method_name);
    $ref_method
      ->setAccessible(TRUE);
    return $ref_method
      ->invokeArgs($object, $arguments);
  }

  /**
   * Provides data for the random string validation test.
   *
   * @return array
   *   - The expected result of the validation.
   *   - The string to validate.
   */
  public function providerRandomStringValidate() {
    return [
      [
        FALSE,
        ' curry paste',
      ],
      [
        FALSE,
        'curry paste ',
      ],
      [
        FALSE,
        'curry  paste',
      ],
      [
        FALSE,
        'curry   paste',
      ],
      [
        TRUE,
        'curry paste',
      ],
      [
        TRUE,
        'thai green curry paste',
      ],
      [
        TRUE,
        '@startswithat',
      ],
      [
        TRUE,
        'contains@at',
      ],
    ];
  }

  /**
   * @covers ::randomStringValidate
   * @dataProvider providerRandomStringValidate
   */
  public function testRandomStringValidate($expected, $string) {
    $mock_test_base = $this
      ->getMockForAbstractClass('Drupal\\simpletest\\TestBase');
    $actual = $mock_test_base
      ->randomStringValidate($string);
    $this
      ->assertEquals($expected, $actual);
  }

  /**
   * Provides data for testRandomString() and others.
   *
   * @return array
   *   - The number of items (characters, object properties) we expect any of
   *     the random functions to give us.
   */
  public function providerRandomItems() {
    return [
      [
        NULL,
      ],
      [
        0,
      ],
      [
        1,
      ],
      [
        2,
      ],
      [
        3,
      ],
      [
        4,
      ],
      [
        7,
      ],
    ];
  }

  /**
   * @covers ::randomString
   * @dataProvider providerRandomItems
   */
  public function testRandomString($length) {
    $mock_test_base = $this
      ->getMockForAbstractClass('Drupal\\simpletest\\TestBase');
    $string = $mock_test_base
      ->randomString($length);
    $this
      ->assertEquals($length, strlen($string));

    // randomString() should always include an ampersand ('&')  and a
    // greater than ('>') if $length is greater than 3.
    if ($length > 4) {
      $this
        ->assertContains('&', $string);
      $this
        ->assertContains('>', $string);
    }
  }

  /**
   * @covers ::randomObject
   * @dataProvider providerRandomItems
   */
  public function testRandomObject($size) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');

    // Note: count((array)object) works for now, maybe not later.
    $this
      ->assertEquals($size, count((array) $test_base
      ->randomObject($size)));
  }

  /**
   * @covers ::checkRequirements
   */
  public function testCheckRequirements() {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertInternalType('array', $this
      ->invokeProtectedMethod($test_base, 'checkRequirements', []));
  }

  /**
   * Data provider for testAssert().
   *
   * @return array
   *   Standard dataProvider array of arrays:
   *   - Expected result from assert().
   *   - Expected status stored in TestBase->assertions.
   *   - Status, passed to assert().
   *   - Message, passed to assert().
   *   - Group, passed to assert().
   *   - Caller, passed to assert().
   */
  public function providerAssert() {
    return [
      [
        TRUE,
        'pass',
        TRUE,
        'Yay pass',
        'test',
        [],
      ],
      [
        FALSE,
        'fail',
        FALSE,
        'Boo fail',
        'test',
        [],
      ],
      [
        TRUE,
        'pass',
        'pass',
        'Yay pass',
        'test',
        [],
      ],
      [
        FALSE,
        'fail',
        'fail',
        'Boo fail',
        'test',
        [],
      ],
      [
        FALSE,
        'exception',
        'exception',
        'Boo fail',
        'test',
        [],
      ],
      [
        FALSE,
        'debug',
        'debug',
        'Boo fail',
        'test',
        [],
      ],
    ];
  }

  /**
   * @covers ::assert
   * @dataProvider providerAssert
   */
  public function testAssert($expected, $assertion_status, $status, $message, $group, $caller) {
    $test_id = 'luke_i_am_your_' . $assertion_status;
    $test_base = $this
      ->getTestBaseForAssertionTests($test_id);

    // Verify some startup values.
    $this
      ->assertAttributeEmpty('assertions', $test_base);
    if (is_string($status)) {
      $this
        ->assertEquals(0, $test_base->results['#' . $status]);
    }

    // assert() is protected so we have to make it accessible.
    $ref_assert = new \ReflectionMethod($test_base, 'assert');
    $ref_assert
      ->setAccessible(TRUE);

    // Call assert() from within our hall of mirrors.
    $this
      ->assertEquals($expected, $ref_assert
      ->invokeArgs($test_base, [
      $status,
      $message,
      $group,
      $caller,
    ]));

    // Check the side-effects of assert().
    if (is_string($status)) {
      $this
        ->assertEquals(1, $test_base->results['#' . $status]);
    }
    $this
      ->assertAttributeNotEmpty('assertions', $test_base);

    // Make a ReflectionProperty for the assertions property,
    // since it's protected.
    $ref_assertions = new \ReflectionProperty($test_base, 'assertions');
    $ref_assertions
      ->setAccessible(TRUE);
    $assertions = $ref_assertions
      ->getValue($test_base);
    $assertion = reset($assertions);
    $this
      ->assertEquals($assertion_status, $assertion['status']);
    $this
      ->assertEquals($test_id, $assertion['test_id']);
    $this
      ->assertEquals(get_class($test_base), $assertion['test_class']);
    $this
      ->assertEquals($message, $assertion['message']);
    $this
      ->assertEquals($group, $assertion['message_group']);
  }

  /**
   * Data provider for assertTrue().
   */
  public function providerAssertTrue() {
    return [
      [
        TRUE,
        TRUE,
      ],
      [
        FALSE,
        FALSE,
      ],
    ];
  }

  /**
   * @covers ::assertTrue
   * @dataProvider providerAssertTrue
   */
  public function testAssertTrue($expected, $value) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals($expected, $this
      ->invokeProtectedMethod($test_base, 'assertTrue', [
      $value,
    ]));
  }

  /**
   * @covers ::assertFalse
   * @dataProvider providerAssertTrue
   */
  public function testAssertFalse($expected, $value) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(!$expected, $this
      ->invokeProtectedMethod($test_base, 'assertFalse', [
      $value,
    ]));
  }

  /**
   * Data provider for assertNull().
   */
  public function providerAssertNull() {
    return [
      [
        TRUE,
        NULL,
      ],
      [
        FALSE,
        '',
      ],
    ];
  }

  /**
   * @covers ::assertNull
   * @dataProvider providerAssertNull
   */
  public function testAssertNull($expected, $value) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals($expected, $this
      ->invokeProtectedMethod($test_base, 'assertNull', [
      $value,
    ]));
  }

  /**
   * @covers ::assertNotNull
   * @dataProvider providerAssertNull
   */
  public function testAssertNotNull($expected, $value) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(!$expected, $this
      ->invokeProtectedMethod($test_base, 'assertNotNull', [
      $value,
    ]));
  }

  /**
   * Data provider for tests of equality assertions.
   *
   * Used by testAssertIdentical(), testAssertEqual(), testAssertNotIdentical(),
   * and testAssertNotEqual().
   *
   * @return
   *   Array of test data.
   *   - Expected assertion value for identical comparison.
   *   - Expected assertion value for equal comparison.
   *   - First value to compare.
   *   - Second value to compare.
   */
  public function providerEqualityAssertions() {
    return [
      // Integers and floats.
      [
        TRUE,
        TRUE,
        0,
        0,
      ],
      [
        FALSE,
        TRUE,
        0,
        0.0,
      ],
      [
        FALSE,
        TRUE,
        '0',
        0,
      ],
      [
        FALSE,
        TRUE,
        '0.0',
        0.0,
      ],
      [
        FALSE,
        FALSE,
        23,
        77,
      ],
      [
        TRUE,
        TRUE,
        23.0,
        23.0,
      ],
      // Strings.
      [
        FALSE,
        FALSE,
        'foof',
        'yay',
      ],
      [
        TRUE,
        TRUE,
        'yay',
        'yay',
      ],
      // Bools with type conversion.
      [
        TRUE,
        TRUE,
        TRUE,
        TRUE,
      ],
      [
        TRUE,
        TRUE,
        FALSE,
        FALSE,
      ],
      [
        FALSE,
        TRUE,
        NULL,
        FALSE,
      ],
      [
        FALSE,
        TRUE,
        'TRUE',
        TRUE,
      ],
      [
        FALSE,
        FALSE,
        'FALSE',
        FALSE,
      ],
      [
        FALSE,
        TRUE,
        0,
        FALSE,
      ],
      [
        FALSE,
        TRUE,
        1,
        TRUE,
      ],
      [
        FALSE,
        TRUE,
        -1,
        TRUE,
      ],
      [
        FALSE,
        TRUE,
        '1',
        TRUE,
      ],
      [
        FALSE,
        TRUE,
        '1.3',
        TRUE,
      ],
      // Null.
      [
        FALSE,
        FALSE,
        'NULL',
        NULL,
      ],
      [
        TRUE,
        TRUE,
        NULL,
        NULL,
      ],
    ];
  }

  /**
   * @covers ::assertIdentical
   * @dataProvider providerEqualityAssertions
   */
  public function testAssertIdentical($expected_identical, $expected_equal, $first, $second) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals($expected_identical, $this
      ->invokeProtectedMethod($test_base, 'assertIdentical', [
      $first,
      $second,
    ]));
  }

  /**
   * @covers ::assertNotIdentical
   * @dataProvider providerEqualityAssertions
   */
  public function testAssertNotIdentical($expected_identical, $expected_equal, $first, $second) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(!$expected_identical, $this
      ->invokeProtectedMethod($test_base, 'assertNotIdentical', [
      $first,
      $second,
    ]));
  }

  /**
   * @covers ::assertEqual
   * @dataProvider providerEqualityAssertions
   */
  public function testAssertEqual($expected_identical, $expected_equal, $first, $second) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals($expected_equal, $this
      ->invokeProtectedMethod($test_base, 'assertEqual', [
      $first,
      $second,
    ]));
  }

  /**
   * @covers ::assertNotEqual
   * @dataProvider providerEqualityAssertions
   */
  public function testAssertNotEqual($expected_identical, $expected_equal, $first, $second) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(!$expected_equal, $this
      ->invokeProtectedMethod($test_base, 'assertNotEqual', [
      $first,
      $second,
    ]));
  }

  /**
   * Data provider for testAssertIdenticalObject().
   */
  public function providerAssertIdenticalObject() {
    $obj1 = new \stdClass();
    $obj1->foof = 'yay';
    $obj2 = $obj1;
    $obj3 = clone $obj1;
    $obj4 = new \stdClass();
    return [
      [
        TRUE,
        $obj1,
        $obj2,
      ],
      [
        TRUE,
        $obj1,
        $obj3,
      ],
      [
        FALSE,
        $obj1,
        $obj4,
      ],
    ];
  }

  /**
   * @covers ::assertIdenticalObject
   * @dataProvider providerAssertIdenticalObject
   */
  public function testAssertIdenticalObject($expected, $first, $second) {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals($expected, $this
      ->invokeProtectedMethod($test_base, 'assertIdenticalObject', [
      $first,
      $second,
    ]));
  }

  /**
   * @covers ::pass
   */
  public function testPass() {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(TRUE, $this
      ->invokeProtectedMethod($test_base, 'pass', []));
  }

  /**
   * @covers ::fail
   */
  public function testFail() {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertEquals(FALSE, $this
      ->invokeProtectedMethod($test_base, 'fail', []));
  }

  /**
   * Data provider for testError().
   *
   * @return array
   *   - Expected status for assertion.
   *   - Group for use in assert().
   */
  public function providerError() {
    return [
      [
        'debug',
        'User notice',
      ],
      [
        'exception',
        'Not User notice',
      ],
    ];
  }

  /**
   * @covers ::error
   * @dataProvider providerError
   */
  public function testError($status, $group) {

    // Mock up a TestBase object.
    $mock_test_base = $this
      ->getMockBuilder('Drupal\\simpletest\\TestBase')
      ->setMethods([
      'assert',
    ])
      ->getMockForAbstractClass();

    // Set expectations for assert().
    $mock_test_base
      ->expects($this
      ->once())
      ->method('assert')
      ->with($status)
      ->willReturn("{$status}:{$group}");

    // Invoke error().
    $this
      ->assertEquals("{$status}:{$group}", $this
      ->invokeProtectedMethod($mock_test_base, 'error', [
      'msg',
      $group,
    ]));
  }

  /**
   * @covers ::getRandomGenerator
   */
  public function testGetRandomGenerator() {
    $test_base = $this
      ->getTestBaseForAssertionTests('test_id');
    $this
      ->assertInstanceOf('Drupal\\Component\\Utility\\Random', $this
      ->invokeProtectedMethod($test_base, 'getRandomGenerator', []));
  }

}

Classes

Namesort descending Description
TestBaseTest @requires extension curl @coversDefaultClass \Drupal\simpletest\TestBase @group simpletest @group TestBase