diff --git a/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php b/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php
index a18f45c..41634b1 100644
--- a/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php
+++ b/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php
@@ -2,11 +2,16 @@
 
 namespace Drupal\system\Tests\Menu;
 
+@trigger_error(__NAMESPACE__ . '\AssertBreadcrumbTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait', E_USER_DEPRECATED);
+
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
 
 /**
  * Provides test assertions for verifying breadcrumbs.
+ *
+ * @deprecated Scheduled for removal in Drupal 9.0.0.
+ *   Use \Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait instead.
  */
 trait AssertBreadcrumbTrait {
 
diff --git a/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php b/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php
index 05e0268..e64177a 100644
--- a/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php
+++ b/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php
@@ -2,10 +2,15 @@
 
 namespace Drupal\system\Tests\Menu;
 
+@trigger_error(__NAMESPACE__ . '\AssertMenuActiveTrailTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Menu\AssertMenuActiveTrailTrait', E_USER_DEPRECATED);
+
 use Drupal\Core\Url;
 
 /**
  * Provides test assertions for verifying the active menu trail.
+ *
+ * @deprecated Scheduled for removal in Drupal 9.0.0.
+ *   Use \Drupal\Tests\system\Functional\Menu\AssertMenuActiveTrailTrait instead.
  */
 trait AssertMenuActiveTrailTrait {
 
diff --git a/core/modules/system/src/Tests/Menu/MenuTestBase.php b/core/modules/system/src/Tests/Menu/MenuTestBase.php
index f791eec..c77f079 100644
--- a/core/modules/system/src/Tests/Menu/MenuTestBase.php
+++ b/core/modules/system/src/Tests/Menu/MenuTestBase.php
@@ -2,8 +2,16 @@
 
 namespace Drupal\system\Tests\Menu;
 
+@trigger_error(__NAMESPACE__ . '\MenuTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\BrowserTestBase', E_USER_DEPRECATED);
+
 use Drupal\simpletest\WebTestBase;
 
+/**
+ * Base class for Menu tests.
+ *
+ * @deprecated Scheduled for removal in Drupal 9.0.0.
+ *   Use \Drupal\Tests\BrowserTestBase instead.
+ */
 abstract class MenuTestBase extends WebTestBase {
 
   use AssertBreadcrumbTrait;
diff --git a/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php b/core/modules/system/tests/src/Functional/Menu/AssertBreadcrumbTrait.php
similarity index 94%
copy from core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php
copy to core/modules/system/tests/src/Functional/Menu/AssertBreadcrumbTrait.php
index a18f45c..fd0dc7c 100644
--- a/core/modules/system/src/Tests/Menu/AssertBreadcrumbTrait.php
+++ b/core/modules/system/tests/src/Functional/Menu/AssertBreadcrumbTrait.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
@@ -99,9 +99,9 @@ protected function getBreadcrumbParts() {
     if (!empty($elements)) {
       foreach ($elements as $element) {
         $parts[] = [
-          'text' => (string) $element,
-          'href' => (string) $element['href'],
-          'title' => (string) $element['title'],
+          'text' => $element->getText(),
+          'href' => $element->getAttribute('href'),
+          'title' => $element->getAttribute('title'),
         ];
       }
     }
diff --git a/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php b/core/modules/system/tests/src/Functional/Menu/AssertMenuActiveTrailTrait.php
similarity index 98%
copy from core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php
copy to core/modules/system/tests/src/Functional/Menu/AssertMenuActiveTrailTrait.php
index 05e0268..c5d60e5 100644
--- a/core/modules/system/src/Tests/Menu/AssertMenuActiveTrailTrait.php
+++ b/core/modules/system/tests/src/Functional/Menu/AssertMenuActiveTrailTrait.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Core\Url;
 
diff --git a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php b/core/modules/system/tests/src/Functional/Menu/BreadcrumbTest.php
similarity index 97%
rename from core/modules/system/src/Tests/Menu/BreadcrumbTest.php
rename to core/modules/system/tests/src/Functional/Menu/BreadcrumbTest.php
index 39303ff..e9142dc 100644
--- a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/tests/src/Functional/Menu/BreadcrumbTest.php
@@ -1,9 +1,10 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Core\Url;
 use Drupal\node\Entity\NodeType;
+use Drupal\Tests\BrowserTestBase;
 use Drupal\user\RoleInterface;
 
 /**
@@ -11,7 +12,9 @@
  *
  * @group Menu
  */
-class BreadcrumbTest extends MenuTestBase {
+class BreadcrumbTest extends BrowserTestBase {
+
+  use AssertBreadcrumbTrait;
 
   /**
    * Modules to enable.
@@ -358,17 +361,17 @@ public function testBreadCrumbs() {
     // user is not able to access "Administer".
     $trail = $home;
     $this->assertBreadcrumb('admin', $trail, t('Access denied'));
-    $this->assertResponse(403);
+    $this->assertSession()->statusCodeEquals(403);
 
     // Since the 'admin' path is not accessible, we still expect only the Home
     // link.
     $this->assertBreadcrumb('admin/reports', $trail, t('Reports'));
-    $this->assertNoResponse(403);
+    $this->assertSession()->statusCodeNotEquals(403);
 
     // Since the Reports page is accessible, that will show.
     $trail += ['admin/reports' => t('Reports')];
     $this->assertBreadcrumb('admin/reports/dblog', $trail, t('Recent log messages'));
-    $this->assertNoResponse(403);
+    $this->assertSession()->statusCodeNotEquals(403);
 
     // Ensure that the breadcrumb is safe against XSS.
     $this->drupalGet('menu-test/breadcrumb1/breadcrumb2/breadcrumb3');
diff --git a/core/modules/system/src/Tests/Menu/LocalActionTest.php b/core/modules/system/tests/src/Functional/Menu/LocalActionTest.php
similarity index 93%
rename from core/modules/system/src/Tests/Menu/LocalActionTest.php
rename to core/modules/system/tests/src/Functional/Menu/LocalActionTest.php
index 3886cb8..f7b9aaf 100644
--- a/core/modules/system/src/Tests/Menu/LocalActionTest.php
+++ b/core/modules/system/tests/src/Functional/Menu/LocalActionTest.php
@@ -1,17 +1,17 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests local actions derived from router and added/altered via hooks.
  *
  * @group Menu
  */
-class LocalActionTest extends WebTestBase {
+class LocalActionTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -80,7 +80,7 @@ protected function assertLocalAction(array $actions) {
       // This behaviour is a bug in libxml, see
       // https://bugs.php.net/bug.php?id=49437.
       $this->assertPattern('@<a [^>]*class="[^"]*button-action[^"]*"[^>]*>' . preg_quote($title, '@') . '</@');
-      $this->assertEqual($elements[$index]['href'], $url->toString());
+      $this->assertEqual($elements[$index]->getAttribute('href'), $url->toString());
       $index++;
     }
   }
diff --git a/core/modules/system/src/Tests/Menu/LocalTasksTest.php b/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php
similarity index 89%
rename from core/modules/system/src/Tests/Menu/LocalTasksTest.php
rename to core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php
index 7171d3e..12a157d 100644
--- a/core/modules/system/src/Tests/Menu/LocalTasksTest.php
+++ b/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php
@@ -1,17 +1,17 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests local tasks derived from router and added/altered via hooks.
  *
  * @group Menu
  */
-class LocalTasksTest extends WebTestBase {
+class LocalTasksTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -55,10 +55,10 @@ protected function assertLocalTasks(array $routes, $level = 0) {
     foreach ($routes as $index => $route_info) {
       list($route_name, $route_parameters) = $route_info;
       $expected = Url::fromRoute($route_name, $route_parameters)->toString();
-      $method = ($elements[$index]['href'] == $expected ? 'pass' : 'fail');
+      $method = ($elements[$index]->getAttribute('href') == $expected ? 'pass' : 'fail');
       $this->{$method}(format_string('Task @number href @value equals @expected.', [
         '@number' => $index + 1,
-        '@value' => (string) $elements[$index]['href'],
+        '@value' => $elements[$index]->getAttribute('href'),
         '@expected' => $expected,
       ]));
     }
@@ -129,7 +129,7 @@ public function testPluginLocalTask() {
     // Ensure the view tab is active.
     $result = $this->xpath('//ul[contains(@class, "tabs")]//li[contains(@class, "active")]/a');
     $this->assertEqual(1, count($result), 'There is just a single active tab.');
-    $this->assertEqual('View', (string) $result[0], 'The view tab is active.');
+    $this->assertEqual('View(active tab)', $result[0]->getText(), 'The view tab is active.');
 
     // Verify that local tasks in the second level appear.
     $sub_tasks = [
@@ -144,15 +144,15 @@ public function testPluginLocalTask() {
 
     $result = $this->xpath('//ul[contains(@class, "tabs")]//li[contains(@class, "active")]/a');
     $this->assertEqual(1, count($result), 'There is just a single active tab.');
-    $this->assertEqual('Settings', (string) $result[0], 'The settings tab is active.');
+    $this->assertEqual('Settings(active tab)', $result[0]->getText(), 'The settings tab is active.');
 
     $this->drupalGet(Url::fromRoute('menu_test.local_task_test_tasks_settings_sub1'));
     $this->assertLocalTasks($sub_tasks, 1);
 
     $result = $this->xpath('//ul[contains(@class, "tabs")]//a[contains(@class, "active")]');
     $this->assertEqual(2, count($result), 'There are tabs active on both levels.');
-    $this->assertEqual('Settings', (string) $result[0], 'The settings tab is active.');
-    $this->assertEqual('Dynamic title for TestTasksSettingsSub1', (string) $result[1], 'The sub1 tab is active.');
+    $this->assertEqual('Settings(active tab)', $result[0]->getText(), 'The settings tab is active.');
+    $this->assertEqual('Dynamic title for TestTasksSettingsSub1(active tab)', $result[1]->getText(), 'The sub1 tab is active.');
 
     $this->assertCacheTag('kittens:ragdoll');
     $this->assertCacheTag('kittens:dwarf-cat');
@@ -162,8 +162,8 @@ public function testPluginLocalTask() {
 
     $result = $this->xpath('//ul[contains(@class, "tabs")]//li[contains(@class, "active")]');
     $this->assertEqual(2, count($result), 'There are tabs active on both levels.');
-    $this->assertEqual('Settings', (string) $result[0]->a, 'The settings tab is active.');
-    $this->assertEqual('Derive 1', (string) $result[1]->a, 'The derive1 tab is active.');
+    $this->assertEqual('Settings(active tab)', $result[0]->getText(), 'The settings tab is active.');
+    $this->assertEqual('Derive 1(active tab)', $result[1]->getText(), 'The derive1 tab is active.');
 
     // Ensures that the local tasks contains the proper 'provider key'
     $definitions = $this->container->get('plugin.manager.menu.local_task')->getDefinitions();
@@ -190,7 +190,7 @@ public function testPluginLocalTask() {
 
     $result = $this->xpath('//ul[contains(@class, "tabs")]//li[contains(@class, "active")]');
     $this->assertEqual(1, count($result), 'There is one active tab.');
-    $this->assertEqual('upcasting sub1', (string) $result[0]->a, 'The "upcasting sub1" tab is active.');
+    $this->assertEqual('upcasting sub1(active tab)', $result[0]->getText(), 'The "upcasting sub1" tab is active.');
 
     $this->drupalGet(Url::fromRoute('menu_test.local_task_test_upcasting_sub2', ['entity_test' => '1']));
 
@@ -202,7 +202,7 @@ public function testPluginLocalTask() {
 
     $result = $this->xpath('//ul[contains(@class, "tabs")]//li[contains(@class, "active")]');
     $this->assertEqual(1, count($result), 'There is one active tab.');
-    $this->assertEqual('upcasting sub2', (string) $result[0]->a, 'The "upcasting sub2" tab is active.');
+    $this->assertEqual('upcasting sub2(active tab)', $result[0]->getText(), 'The "upcasting sub2" tab is active.');
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Menu/MenuRouterTest.php b/core/modules/system/tests/src/Functional/Menu/MenuRouterTest.php
similarity index 99%
rename from core/modules/system/src/Tests/Menu/MenuRouterTest.php
rename to core/modules/system/tests/src/Functional/Menu/MenuRouterTest.php
index 521a691..eec96fc 100644
--- a/core/modules/system/src/Tests/Menu/MenuRouterTest.php
+++ b/core/modules/system/tests/src/Functional/Menu/MenuRouterTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\system\Tests\Menu;
+namespace Drupal\Tests\system\Functional\Menu;
 
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests menu router and default menu link functionality.
  *
  * @group Menu
  */
-class MenuRouterTest extends WebTestBase {
+class MenuRouterTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
