TestBaseTest.php

Namespace

Drupal\Tests\simpletest\Unit

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

Title Deprecated Summary
TestBaseTest @requires extension curl @coversDefaultClass \Drupal\simpletest\TestBase[[api-linebreak]] @group simpletest @group TestBase

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.