diff --git a/core/modules/system/src/Tests/Batch/PageTest.php b/core/modules/system/tests/src/Functional/Batch/PageTest.php
similarity index 73%
rename from core/modules/system/src/Tests/Batch/PageTest.php
rename to core/modules/system/tests/src/Functional/Batch/PageTest.php
index dbdf18c..b108a11 100644
--- a/core/modules/system/src/Tests/Batch/PageTest.php
+++ b/core/modules/system/tests/src/Functional/Batch/PageTest.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\system\Tests\Batch;
+namespace Drupal\Tests\system\Functional\Batch;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the content of the progress page.
  *
  * @group Batch
  */
-class PageTest extends WebTestBase {
+class PageTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -38,6 +38,7 @@ public function testBatchProgressPageTheme() {
     // function saved as a variable) matches the theme used on the
     // administrative page.
     $this->drupalGet('admin/batch-test/test-theme');
+    $this->waitBatchProccessToEnd();
     // The stack should contain the name of the theme used on the progress
     // page.
     $this->assertEqual(batch_test_stack(), ['seven'], 'A progressive batch correctly uses the theme of the page that started the batch.');
@@ -51,9 +52,10 @@ public function testBatchProgressPageTitle() {
     // title shown during batch execution (which the batch callback function
     // saved as a variable) matches the theme used on the administrative page.
     $this->drupalGet('batch-test/test-title');
+    $this->waitBatchProccessToEnd();
     // The stack should contain the title shown on the progress page.
     $this->assertEqual(batch_test_stack(), ['Batch Test'], 'The batch title is shown on the batch page.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $this->assertSession()->pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
   }
 
   /**
@@ -63,12 +65,16 @@ public function testBatchProgressMessages() {
     // Go to the initial step only.
     $this->maximumMetaRefreshCount = 0;
     $this->drupalGet('batch-test/test-title');
-    $this->assertRaw('<div class="progress__description">Initializing.<br />&nbsp;</div>', 'Initial progress message appears correctly.');
-    $this->assertNoRaw('&amp;nbsp;', 'Initial progress message is not double escaped.');
+    $this->waitBatchProccessToEnd();
+    $assertSession = $this->assertSession();
+    $assertSession->responseContains('<div class="progress__description">Initializing.<br />&nbsp;</div>', 'Initial progress message appears correctly.');
+    $assertSession->responseNotContains('&amp;nbsp;', 'Initial progress message is not double escaped.');
+
     // Now also go to the next step.
     $this->maximumMetaRefreshCount = 1;
     $this->drupalGet('batch-test/test-title');
-    $this->assertRaw('<div class="progress__description">Completed 1 of 1.</div>', 'Progress message for second step appears correctly.');
+    $this->waitBatchProccessToEnd();
+    $assertSession->responseContains('<div class="progress__description">Completed 1 of 1.</div>', 'Progress message for second step appears correctly.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/Batch/ProcessingTest.php b/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
similarity index 80%
rename from core/modules/system/src/Tests/Batch/ProcessingTest.php
rename to core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
index 6b90cc8..6404973 100644
--- a/core/modules/system/src/Tests/Batch/ProcessingTest.php
+++ b/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\system\Tests\Batch;
+namespace Drupal\Tests\system\Functional\Batch;
 
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests batch processing in form and non-form workflow.
  *
  * @group Batch
  */
-class ProcessingTest extends WebTestBase {
+class ProcessingTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -25,9 +25,11 @@ class ProcessingTest extends WebTestBase {
   public function testBatchNoForm() {
     // Displaying the page triggers batch 1.
     $this->drupalGet('batch-test/no-form');
+    $this->waitBatchProccessToEnd();
     $this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch for step 2 performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $this->assertSession()
+      ->pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
   }
 
   /**
@@ -36,9 +38,11 @@ public function testBatchNoForm() {
   public function testBatchRedirectFinishedCallback() {
     // Displaying the page triggers batch 1.
     $this->drupalGet('batch-test/finish-redirect');
+    $this->waitBatchProccessToEnd();
     $this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch for step 2 performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
-    $this->assertText('Test page text.', 'Custom redirection after batch execution displays the correct page.');
+    $this->assertSession()
+      ->pageTextContains('Test page text.', 'Custom redirection after batch execution displays the correct page.');
     $this->assertUrl(Url::fromRoute('test_page_test.test_page'));
   }
 
@@ -46,73 +50,86 @@ public function testBatchRedirectFinishedCallback() {
    * Tests batches defined in a form submit handler.
    */
   public function testBatchForm() {
+    $assertSession = $this->assertSession();
     // Batch 0: no operation.
     $edit = ['batch' => 'batch_0'];
     $this->drupalPostForm('batch-test', $edit, 'Submit');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
     $this->assertBatchMessages($this->_resultMessages('batch_0'), 'Batch with no operation performed successfully.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession
+      ->pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
 
     // Batch 1: several simple operations.
     $edit = ['batch' => 'batch_1'];
     $this->drupalPostForm('batch-test', $edit, 'Submit');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
     $this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch with simple operations performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession
+      ->pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
 
     // Batch 2: one multistep operation.
     $edit = ['batch' => 'batch_2'];
     $this->drupalPostForm('batch-test', $edit, 'Submit');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
     $this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch with multistep operation performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession
+      ->pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
 
     // Batch 3: simple + multistep combined.
     $edit = ['batch' => 'batch_3'];
     $this->drupalPostForm('batch-test', $edit, 'Submit');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
     $this->assertBatchMessages($this->_resultMessages('batch_3'), 'Batch with simple and multistep operations performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_3'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession->
+      pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
 
     // Batch 4: nested batch.
     $edit = ['batch' => 'batch_4'];
     $this->drupalPostForm('batch-test', $edit, 'Submit');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
     $this->assertBatchMessages($this->_resultMessages('batch_4'), 'Nested batch performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_4'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession->
+      pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
   }
 
   /**
    * Tests batches defined in a multistep form.
    */
   public function testBatchFormMultistep() {
+    $assertSession = $this->assertSession();
     $this->drupalGet('batch-test/multistep');
+    $this->waitBatchProccessToEnd();
     $this->assertNoEscaped('<', 'No escaped markup is present.');
-    $this->assertText('step 1', 'Form is displayed in step 1.');
+    $assertSession->
+      pageTextContains('step 1', 'Form is displayed in step 1.');
 
     // First step triggers batch 1.
     $this->drupalPostForm(NULL, [], 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch for step 1 performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
-    $this->assertText('step 2', 'Form is displayed in step 2.');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->
+      pageTextContains('step 2', 'Form is displayed in step 2.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
 
     // Second step triggers batch 2.
     $this->drupalPostForm(NULL, [], 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch for step 2 performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
-    $this->assertNoEscaped('<', 'No escaped markup is present.');
+    $assertSession->
+      pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
+    $assertSession->assertNoEscaped('<', 'No escaped markup is present.');
 
     // Extra query arguments will trigger logic that will add them to the
     // redirect URL. Make sure they are persisted.
     $this->drupalGet('batch-test/multistep', ['query' => ['big_tree' => 'small_axe']]);
+    $this->waitBatchProccessToEnd();
     $this->drupalPostForm(NULL, [], 'Submit');
-    $this->assertText('step 2', 'Form is displayed in step 2.');
+    $assertSession->
+      pageTextContains('step 2', 'Form is displayed in step 2.');
     $this->assertTrue(strpos($this->getUrl(), 'batch-test/multistep?big_tree=small_axe'), 'Query argument was persisted and another extra argument was added.');
   }
 
@@ -130,7 +147,8 @@ public function testBatchFormMultipleBatches() {
     // The stack contains execution order of batch callbacks and submit
     // handlers and logging of corresponding $form_state->getValues().
     $this->assertEqual(batch_test_stack(), $this->_resultStack('chained', $value), 'Execution order was correct, and $form_state is correctly persisted.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $this->assertSession()->
+      pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
   }
 
   /**
@@ -148,7 +166,8 @@ public function testBatchFormProgrammatic() {
     // The stack contains execution order of batch callbacks and submit
     // handlers and logging of corresponding $form_state->getValues().
     $this->assertEqual(batch_test_stack(), $this->_resultStack('chained', $value), 'Execution order was correct, and $form_state is correctly persisted.');
-    $this->assertText('Got out of a programmatic batched form.', 'Page execution continues normally.');
+    $this->assertSession()->
+      pageTextContains('Got out of a programmatic batched form.', 'Page execution continues normally.');
   }
 
   /**
@@ -159,6 +178,7 @@ public function testDrupalFormSubmitInBatch() {
     // form.
     $value = rand(0, 255);
     $this->drupalGet('batch-test/nested-programmatic/' . $value);
+    $this->waitBatchProccessToEnd();
     $this->assertEqual(batch_test_stack(), ['mock form submitted with value = ' . $value], '\Drupal::formBuilder()->submitForm() ran successfully within a batch operation.');
   }
 
@@ -170,9 +190,11 @@ public function testDrupalFormSubmitInBatch() {
   public function testBatchLargePercentage() {
     // Displaying the page triggers batch 5.
     $this->drupalGet('batch-test/large-percentage');
+    $this->waitBatchProccessToEnd();
     $this->assertBatchMessages($this->_resultMessages('batch_5'), 'Batch for step 2 performed successfully.');
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_5'), 'Execution order was correct.');
-    $this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
+    $this->assertSession()->
+      pageTextContains('Redirection successful.', 'Redirection after batch execution is correct.');
   }
 
 
diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php
index 5751368..3f46cfc 100644
--- a/core/tests/Drupal/Tests/BrowserTestBase.php
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -23,15 +23,16 @@
 use Drupal\Core\Utility\Error;
 use Drupal\FunctionalTests\AssertLegacyTrait;
 use Drupal\simpletest\AssertHelperTrait;
-use Drupal\simpletest\ContentTypeCreationTrait;
 use Drupal\simpletest\BlockCreationTrait;
+use Drupal\simpletest\ContentTypeCreationTrait;
 use Drupal\simpletest\NodeCreationTrait;
 use Drupal\simpletest\UserCreationTrait;
+use Drupal\Tests\Traits\Core\MetaRefreshTrait;
 use PHPUnit\Framework\TestCase;
-use Symfony\Component\CssSelector\CssSelectorConverter;
-use Symfony\Component\HttpFoundation\Request;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
+use Symfony\Component\CssSelector\CssSelectorConverter;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Provides a test case for functional Drupal tests.
@@ -66,6 +67,7 @@
     createUser as drupalCreateUser;
   }
   use XdebugRequestTrait;
+  use MetaRefreshTrait;
 
   /**
    * The database prefix of this test run.
@@ -911,6 +913,7 @@ protected function drupalPostForm($path, $edit, $submit, array $options = []) {
     }
 
     $this->submitForm($edit, $submit);
+    $this->waitBatchProccessToEnd();
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Traits/Core/MetaRefreshTrait.php b/core/tests/Drupal/Tests/Traits/Core/MetaRefreshTrait.php
new file mode 100644
index 0000000..1d9dbb8
--- /dev/null
+++ b/core/tests/Drupal/Tests/Traits/Core/MetaRefreshTrait.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\Tests\Traits\Core;
+
+use Drupal\Component\Utility\Html;
+
+/**
+ * Allows tests redirect on meta refresh tag found in page.
+ */
+trait MetaRefreshTrait {
+
+  /**
+   * The number of meta refresh redirects to follow, or NULL if unlimited.
+   *
+   * @var null|int
+   */
+  protected $maximumMetaRefreshCount = NULL;
+
+  /**
+   * The number of meta refresh redirects followed during ::drupalGet().
+   *
+   * @var int
+   */
+  protected $metaRefreshCount = 0;
+
+  /**
+   * Checks for meta refresh tag and if found call drupalGet() recursively.
+   *
+   * This function looks for the http-equiv attribute to be set to "Refresh" and
+   * is case-sensitive.
+   *
+   * @return string|false
+   *   Either the new page content or FALSE.
+   */
+  protected function checkForMetaRefresh() {
+    $refresh = $this->cssSelect('meta[http-equiv="Refresh"]');
+    if (!empty($refresh) && (!isset($this->maximumMetaRefreshCount) || $this->metaRefreshCount < $this->maximumMetaRefreshCount)) {
+      // Parse the content attribute of the meta tag for the format:
+      // "[delay]: URL=[page_to_redirect_to]".
+      if (preg_match('/\d+;\s*URL=(?<url>.*)/i', $refresh[0]->getAttribute('content'), $match)) {
+        $this->metaRefreshCount++;
+        return $this->drupalGet($this->getAbsoluteUrl(Html::decodeEntities($match['url'])));
+      }
+    }
+    return FALSE;
+  }
+
+  /**
+   * Wait until batch process finish.
+   */
+  protected function waitBatchProccessToEnd() {
+    while ($this->checkForMetaRefresh()) {
+      // Do nothing. checkForMetaRefresh will return FALSE once batch process
+      // have finshed.
+    }
+  }
+
+}
