diff --git a/tests/src/Functional/IntegrationTest.php b/tests/src/Functional/IntegrationTest.php
index 58fd0bf..8ad7a6b 100644
--- a/tests/src/Functional/IntegrationTest.php
+++ b/tests/src/Functional/IntegrationTest.php
@@ -8,6 +8,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\node\Entity\Node;
+use Drupal\search_api\Entity\Index;
 use Drupal\search_api\Entity\Server;
 use Drupal\search_api\Plugin\search_api\tracker\Basic;
 use Drupal\search_api\SearchApiException;
@@ -32,6 +33,13 @@ class IntegrationTest extends SearchApiBrowserTestBase {
   protected $adminUser2;
 
   /**
+   * The backend of the search server used for this test.
+   *
+   * @var string
+   */
+  protected $serverBackend = 'search_api_test';
+
+  /**
    * The ID of the search server used for this test.
    *
    * @var string
@@ -125,7 +133,7 @@ class IntegrationTest extends SearchApiBrowserTestBase {
       'id' => 456,
       'name' => 789,
       'description' => 'WebTest server' . ' description',
-      'backend' => 'search_api_test',
+      'backend' => $this->serverBackend,
       'backend_config' => [],
     ])->save();
 
@@ -193,10 +201,8 @@ class IntegrationTest extends SearchApiBrowserTestBase {
       'name' => '',
       'status' => 1,
       'description' => 'A server used for testing.',
-      'backend' => 'search_api_test',
+      'backend' => $this->serverBackend,
     ];
-
-    $this->drupalGet($settings_path);
     $this->submitForm($edit, $this->t('Save'));
     $this->assertSession()->pageTextContains($this->t('@name field is required.', ['@name' => $this->t('Server name')]));
 
@@ -204,21 +210,16 @@ class IntegrationTest extends SearchApiBrowserTestBase {
       'name' => $server_name,
       'status' => 1,
       'description' => $server_description,
-      'backend' => 'search_api_test',
+      'backend' => $this->serverBackend,
     ];
-    $this->drupalGet($settings_path);
     $this->submitForm($edit, $this->t('Save'));
     $this->assertSession()->pageTextContains($this->t('@name field is required.', ['@name' => $this->t('Machine-readable name')]));
 
-    $edit = [
-      'name' => $server_name,
+    $edit += [
       'id' => $this->serverId,
-      'status' => 1,
-      'description' => $server_description,
-      'backend' => 'search_api_test',
     ];
 
-    $this->submitForm($edit, $this->t('Save'));
+    $this->configureBackendAndSave($edit);
 
     $this->assertSession()->pageTextContains($this->t('The server was successfully saved.'));
     $this->assertSession()->addressEquals('admin/config/search/search-api/server/' . $this->serverId);
@@ -231,6 +232,17 @@ class IntegrationTest extends SearchApiBrowserTestBase {
   }
 
   /**
+   * Let derived backend integration tests fill their server create form.
+   *
+   * @param array $edit
+   *   The common server form values so far.
+   */
+  protected function configureBackendAndSave($edit) {
+    // Nothing to condigure here for the test backend.
+    $this->submitForm($edit, $this->t('Save'));
+  }
+
+  /**
    * Tests creating a search server with an existing machine name.
    */
   protected function createServerDuplicate() {
@@ -240,7 +252,7 @@ class IntegrationTest extends SearchApiBrowserTestBase {
     $edit = [
       'name' => $this->serverId,
       'id' => $this->serverId,
-      'backend' => 'search_api_test',
+      'backend' => $this->serverBackend,
     ];
 
     // Try to submit an server with a duplicate machine name.
@@ -399,7 +411,7 @@ class IntegrationTest extends SearchApiBrowserTestBase {
     $this->assertEquals(1, count($elements), 'Machine name cannot be changed.');
 
     // Test the AJAX functionality for configuring the tracker.
-    $edit = ['tracker' => 'search_api_test'];
+    $edit = ['tracker' => $this->serverBackend];
     $this->submitForm($edit, 'tracker_configure');
     $edit['tracker_config[foo]'] = 'foobar';
     $this->submitForm($edit, $this->t('Save'));
@@ -788,7 +800,7 @@ class IntegrationTest extends SearchApiBrowserTestBase {
       'fields[title][id]' => 'new_id',
       'fields[title][type]' => 'text',
       'fields[title][boost]' => '21.0',
-      'fields[revision_log][type]' => 'search_api_test',
+      'fields[revision_log][type]' => $this->serverBackend,
     ];
     $this->drupalGet($this->getIndexPath('fields'));
     $this->submitForm($edit, $this->t('Save changes'));
@@ -1207,7 +1219,7 @@ class IntegrationTest extends SearchApiBrowserTestBase {
     $this->assertSession()->pageTextNotContains($this->t('Index now'));
 
     // Also try indexing via the API to make sure it is really not possible.
-    $indexed = $index->indexItems();
+    $indexed = $this->indexItems();
     $this->assertEquals(0, $indexed, 'No items were indexed after setting the index to "read only".');
     $remaining_after = $this->countRemainingItems();
     $this->assertEquals($remaining_before, $remaining_after, 'No items were indexed after setting the index to "read only".');
@@ -1323,13 +1335,11 @@ class IntegrationTest extends SearchApiBrowserTestBase {
    * "unindexed" in the tracker.
    */
   protected function changeIndexServer() {
-    $index = $this->getIndex(TRUE);
-
     $node_count = \Drupal::entityQuery('node')->count()->execute();
     $this->assertEquals($node_count, $this->countTrackedItems(), 'All nodes are correctly tracked by the index.');
 
     // Index all remaining items on the index.
-    $index->indexItems();
+    $this->indexItems();
 
     $remaining_items = $this->countRemainingItems();
     $this->assertEquals(0, $remaining_items, 'All items have been successfully indexed.');
@@ -1395,6 +1405,18 @@ class IntegrationTest extends SearchApiBrowserTestBase {
   }
 
   /**
+   * Indexes all (unindexed) items on the specified index.
+   *
+   * @return int
+   *   The number of successfully indexed items.
+   */
+  protected function indexItems() {
+    /** @var \Drupal\search_api\IndexInterface $index */
+    $index = Index::load($this->indexId);
+    return $index->indexItems();
+  }
+
+  /**
    * Ensures that all occurrences of the string are properly escaped.
    *
    * This makes sure that the string is only mentioned in an escaped version and
