You are here

public function SelectTest::testRandomOrder in Drupal 10

Same name and namespace in other branches
  1. 8 core/tests/Drupal/KernelTests/Core/Database/SelectTest.php \Drupal\KernelTests\Core\Database\SelectTest::testRandomOrder()
  2. 9 core/tests/Drupal/KernelTests/Core/Database/SelectTest.php \Drupal\KernelTests\Core\Database\SelectTest::testRandomOrder()

Tests that random ordering of queries works.

We take the approach of testing the Drupal layer only, rather than trying to test that the database's random number generator actually produces random queries (which is very difficult to do without an unacceptable risk of the test failing by accident).

Therefore, in this test we simply run the same query twice and assert that the two results are reordered versions of each other (as well as of the same query without the random ordering). It is reasonable to assume that if we run the same select query twice and the results are in a different order each time, the only way this could happen is if we have successfully triggered the database's random ordering functionality.

File

core/tests/Drupal/KernelTests/Core/Database/SelectTest.php, line 444

Class

SelectTest
Tests the Select query builder.

Namespace

Drupal\KernelTests\Core\Database

Code

public function testRandomOrder() {

  // Use 52 items, so the chance that this test fails by accident will be the
  // same as the chance that a deck of cards will come out in the same order
  // after shuffling it (in other words, nearly impossible).
  $number_of_items = 52;
  while ($this->connection
    ->query("SELECT MAX([id]) FROM {test}")
    ->fetchField() < $number_of_items) {
    $this->connection
      ->insert('test')
      ->fields([
      'name' => $this
        ->randomMachineName(),
    ])
      ->execute();
  }

  // First select the items in order and make sure we get an ordered list.
  $expected_ids = range(1, $number_of_items);
  $ordered_ids = $this->connection
    ->select('test', 't')
    ->fields('t', [
    'id',
  ])
    ->range(0, $number_of_items)
    ->orderBy('id')
    ->execute()
    ->fetchCol();
  $this
    ->assertEquals($expected_ids, $ordered_ids, 'A query without random ordering returns IDs in the correct order.');

  // Now perform the same query, but instead choose a random ordering. We
  // expect this to contain a differently ordered version of the original
  // result.
  $randomized_ids = $this->connection
    ->select('test', 't')
    ->fields('t', [
    'id',
  ])
    ->range(0, $number_of_items)
    ->orderRandom()
    ->execute()
    ->fetchCol();
  $this
    ->assertNotEquals($ordered_ids, $randomized_ids, 'A query with random ordering returns an unordered set of IDs.');
  $sorted_ids = $randomized_ids;
  sort($sorted_ids);
  $this
    ->assertEquals($ordered_ids, $sorted_ids, 'After sorting the random list, the result matches the original query.');

  // Now perform the exact same query again, and make sure the order is
  // different.
  $randomized_ids_second_set = $this->connection
    ->select('test', 't')
    ->fields('t', [
    'id',
  ])
    ->range(0, $number_of_items)
    ->orderRandom()
    ->execute()
    ->fetchCol();
  $this
    ->assertNotEquals($randomized_ids, $randomized_ids_second_set, 'Performing the query with random ordering a second time returns IDs in a different order.');
  $sorted_ids_second_set = $randomized_ids_second_set;
  sort($sorted_ids_second_set);
  $this
    ->assertEquals($sorted_ids, $sorted_ids_second_set, 'After sorting the second random list, the result matches the sorted version of the first random list.');
}