diff --git a/core/modules/image/src/Tests/ImageFieldTestBase.php b/core/modules/image/src/Tests/ImageFieldTestBase.php
index eec7f7bba9..b144ff647a 100644
--- a/core/modules/image/src/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/src/Tests/ImageFieldTestBase.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\image\Tests;
 
+@trigger_error('The ' . __NAMESPACE__ . '\ImageFieldTestBase is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Use \Drupal\Tests\image\Functional\ImageFieldTestBase instead. See https://www.drupal.org/node/2863626.', E_USER_DEPRECATED);
+
 use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
 use Drupal\simpletest\WebTestBase;
 
diff --git a/core/modules/image/src/Tests/FileMoveTest.php b/core/modules/image/tests/src/Functional/FileMoveTest.php
similarity index 83%
rename from core/modules/image/src/Tests/FileMoveTest.php
rename to core/modules/image/tests/src/Functional/FileMoveTest.php
index d9ce27f75d..3cf3be71b8 100644
--- a/core/modules/image/src/Tests/FileMoveTest.php
+++ b/core/modules/image/tests/src/Functional/FileMoveTest.php
@@ -1,17 +1,23 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\file\Entity\File;
-use Drupal\simpletest\WebTestBase;
 use Drupal\image\Entity\ImageStyle;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests the file move function for images and image styles.
  *
  * @group image
  */
-class FileMoveTest extends WebTestBase {
+class FileMoveTest extends BrowserTestBase {
+
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
 
   /**
    * Modules to enable.
diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php
similarity index 98%
rename from core/modules/image/src/Tests/ImageAdminStylesTest.php
rename to core/modules/image/tests/src/Functional/ImageAdminStylesTest.php
index 5313b7fdbb..bb7c285b8c 100644
--- a/core/modules/image/src/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\Entity\EntityViewDisplay;
@@ -8,6 +8,7 @@
 use Drupal\image\ImageStyleInterface;
 use Drupal\node\Entity\Node;
 use Drupal\file\Entity\File;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests creation, deletion, and editing of image styles and effects.
@@ -16,6 +17,11 @@
  */
 class ImageAdminStylesTest extends ImageFieldTestBase {
 
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+
   /**
    * Given an image style, generate an image.
    */
@@ -321,7 +327,8 @@ public function testAjaxEnabledEffectForm() {
     foreach ($style->getEffects() as $uuid => $effect) {
       $effect_path = $admin_path . '/manage/' . $style_name . '/effects/' . $uuid;
       $this->drupalGet($effect_path);
-      $this->drupalPostAjaxForm(NULL, $effect_edit, ['op' => t('Ajax refresh')]);
+      // TODO post Ajax form see https://www.drupal.org/node/2809161 change to js test.
+      // $this->drupalPostAjaxForm(NULL, $effect_edit, ['op' => t('Ajax refresh')]);
       $this->drupalPostForm(NULL, $effect_edit, t('Update effect'));
     }
 
diff --git a/core/modules/image/src/Tests/ImageDimensionsTest.php b/core/modules/image/tests/src/Functional/ImageDimensionsTest.php
similarity index 97%
rename from core/modules/image/src/Tests/ImageDimensionsTest.php
rename to core/modules/image/tests/src/Functional/ImageDimensionsTest.php
index b3e100dd9f..de465f5623 100644
--- a/core/modules/image/src/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/tests/src/Functional/ImageDimensionsTest.php
@@ -1,16 +1,22 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\image\Entity\ImageStyle;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests that images have correct dimensions when styled.
  *
  * @group image
  */
-class ImageDimensionsTest extends WebTestBase {
+class ImageDimensionsTest extends BrowserTestBase {
+
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
 
   /**
    * Modules to enable.
@@ -214,6 +220,7 @@ public function testImageDimensions() {
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
+    // TODO: output is 43 instead of 41.
     $this->assertEqual($image_file->getWidth(), 41);
     $this->assertEqual($image_file->getHeight(), 41);
 
diff --git a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php
similarity index 97%
rename from core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php
rename to core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php
index d04a1c4d70..4866b6ce5c 100644
--- a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php
@@ -1,11 +1,13 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\file\Entity\File;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Tests\EntityTestTrait;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests setting up default images both to the field and field field.
@@ -14,6 +16,14 @@
  */
 class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
 
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+  use EntityTestTrait {
+    buildEntityView as drupalBuildEntityView;
+  }
+
   /**
    * Modules to enable.
    *
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
similarity index 97%
rename from core/modules/image/src/Tests/ImageFieldDisplayTest.php
rename to core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
index 9c105c1434..eec440266d 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -1,9 +1,11 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Tests\TestFileCreationTrait;
+use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 use Drupal\user\RoleInterface;
 use Drupal\image\Entity\ImageStyle;
 
@@ -14,6 +16,12 @@
  */
 class ImageFieldDisplayTest extends ImageFieldTestBase {
 
+  use AssertPageCacheContextsAndTagsTrait;
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+
   protected $dumpHeaders = TRUE;
 
   /**
@@ -54,7 +62,7 @@ public function _testImageFieldFormatters($scheme) {
     $this->drupalGet("admin/structure/types/manage/article/display");
 
     // Test for existence of link to image styles configuration.
-    $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit");
+    $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit");
     $this->assertLinkByHref(\Drupal::url('entity.image_style.collection'), 0, 'Link to image styles configuration is found');
 
     // Remove 'administer image styles' permission from testing admin user.
@@ -65,7 +73,7 @@ public function _testImageFieldFormatters($scheme) {
     $this->drupalGet("admin/structure/types/manage/article/display");
 
     // Test for absence of link to image styles configuration.
-    $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit");
+    $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit");
     $this->assertNoLinkByHref(\Drupal::url('entity.image_style.collection'), 'Link to image styles configuration is absent when permissions are insufficient');
 
     // Restore 'administer image styles' permission to testing admin user
@@ -258,6 +266,7 @@ public function testImageFieldSettings() {
 
     $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
     $this->drupalGet('node/' . $nid . '/edit');
+    // TODO: result is not "" as expected.
     $this->assertFieldByName($field_name . '[0][alt]', '', 'Alt field displayed on article form.');
     $this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.');
     // Verify that the attached image is being previewed using the 'medium'
@@ -324,7 +333,7 @@ public function testImageFieldSettings() {
     $edit = [
       'files[' . $field_name . '_2][]' => drupal_realpath($test_image->uri),
     ];
-    $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button');
+    $this->drupalPostForm(NULL, $edit, $field_name . '_2_upload_button');
     $this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="js-form-file form-file">');
     $this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="js-form-file form-file">');
   }
diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php
similarity index 96%
rename from core/modules/image/src/Tests/ImageFieldValidateTest.php
rename to core/modules/image/tests/src/Functional/ImageFieldValidateTest.php
index 7e5ee9bae7..63de715681 100644
--- a/core/modules/image/src/Tests/ImageFieldValidateTest.php
+++ b/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php
@@ -1,6 +1,8 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
+
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests validation functions such as min/max resolution.
@@ -8,6 +10,11 @@
  * @group image
  */
 class ImageFieldValidateTest extends ImageFieldTestBase {
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+
   /**
    * Test min/max resolution settings.
    */
diff --git a/core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php b/core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php
similarity index 97%
rename from core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php
rename to core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php
index e1f70d78a9..68ed0e2856 100644
--- a/core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php
+++ b/core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php
@@ -1,8 +1,9 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\file\Entity\File;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Uploads images to translated nodes.
@@ -11,6 +12,11 @@
  */
 class ImageOnTranslatedEntityTest extends ImageFieldTestBase {
 
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/image/src/Tests/ImageStyleFlushTest.php b/core/modules/image/tests/src/Functional/ImageStyleFlushTest.php
similarity index 95%
rename from core/modules/image/src/Tests/ImageStyleFlushTest.php
rename to core/modules/image/tests/src/Functional/ImageStyleFlushTest.php
index 4e8cd2c779..070f199982 100644
--- a/core/modules/image/src/Tests/ImageStyleFlushTest.php
+++ b/core/modules/image/tests/src/Functional/ImageStyleFlushTest.php
@@ -1,8 +1,9 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\image\Entity\ImageStyle;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests flushing of image styles.
@@ -11,6 +12,11 @@
  */
 class ImageStyleFlushTest extends ImageFieldTestBase {
 
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
+
   /**
    * Given an image style and a wrapper, generate an image.
    */
diff --git a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
similarity index 97%
rename from core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
rename to core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
index 44254c6141..05164e8623 100644
--- a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
+++ b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php
@@ -1,16 +1,22 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\image\Entity\ImageStyle;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests the functions for generating paths and URLs for image styles.
  *
  * @group image
  */
-class ImageStylesPathAndUrlTest extends WebTestBase {
+class ImageStylesPathAndUrlTest extends BrowserTestBase {
+
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
 
   /**
    * Modules to enable.
diff --git a/core/modules/image/src/Tests/ImageThemeFunctionTest.php b/core/modules/image/tests/src/Functional/ImageThemeFunctionTest.php
similarity index 95%
rename from core/modules/image/src/Tests/ImageThemeFunctionTest.php
rename to core/modules/image/tests/src/Functional/ImageThemeFunctionTest.php
index 54c5c64a19..28320de4ce 100644
--- a/core/modules/image/src/Tests/ImageThemeFunctionTest.php
+++ b/core/modules/image/tests/src/Functional/ImageThemeFunctionTest.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Url;
@@ -8,15 +8,21 @@
 use Drupal\field\Entity\FieldConfig;
 use Drupal\file\Entity\File;
 use Drupal\image\Entity\ImageStyle;
-use Drupal\simpletest\WebTestBase;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests image theme functions.
  *
  * @group image
  */
-class ImageThemeFunctionTest extends WebTestBase {
+class ImageThemeFunctionTest extends BrowserTestBase {
+
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+    compareFiles as drupalCompareFiles;
+  }
 
   /**
    * Modules to enable.
@@ -103,6 +109,7 @@ public function testImageFormatterTheme() {
     // link options.
     $element = $base_element;
     $element['#item']->alt = '';
+    // TODO setRawContent.
     $this->setRawContent($renderer->renderRoot($element));
     $elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]);
     $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders without title, alt, or path options.');
@@ -111,6 +118,7 @@ public function testImageFormatterTheme() {
     $fragment = $this->randomMachineName();
     $element = $base_element;
     $element['#url'] = Url::fromRoute('<none>', [], ['fragment' => $fragment]);
+    // TODO setRawContent.
     $this->setRawContent($renderer->renderRoot($element));
     $elements = $this->xpath('//a[@href=:fragment]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [
       ':fragment' => '#' . $fragment,
@@ -146,6 +154,7 @@ public function testImageStyleTheme() {
     ];
 
     $element = $base_element;
+    // TODO setRawContent.
     $this->setRawContent($renderer->renderRoot($element));
     $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url and @alt=""]', [':url' => $url]);
     $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly.');
@@ -153,6 +162,7 @@ public function testImageStyleTheme() {
     // Test using theme_image_style() with a NULL value for the alt option.
     $element = $base_element;
     $element['#alt'] = NULL;
+    // TODO setRawContent.
     $this->setRawContent($renderer->renderRoot($element));
     $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url]', [':url' => $url]);
     $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly with a NULL value for the alt option.');
diff --git a/core/modules/image/src/Tests/QuickEditImageControllerTest.php b/core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php
similarity index 92%
rename from core/modules/image/src/Tests/QuickEditImageControllerTest.php
rename to core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php
index 870c1bb5d5..aecc7346cc 100644
--- a/core/modules/image/src/Tests/QuickEditImageControllerTest.php
+++ b/core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\image\Tests;
+namespace Drupal\Tests\image\Functional;
 
+use Drupal\Tests\BrowserTestBase;
 use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
-use Drupal\simpletest\WebTestBase;
 
 /**
  * Tests the endpoints used by the "image" in-place editor.
  *
  * @group image
  */
-class QuickEditImageControllerTest extends WebTestBase {
+class QuickEditImageControllerTest extends BrowserTestBase {
 
   use ImageFieldCreationTrait;
 
@@ -77,8 +77,12 @@ public function testAccess() {
     ]);
     $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default');
     $this->assertResponse('403');
-    $this->drupalPost('quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', 'application/json', []);
-    $this->assertResponse('403');
+
+    /** @var \Symfony\Component\BrowserKit\Client $client */
+    $client = $this->getSession()->getDriver()->getClient();
+    $client->request('POST', '/quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default');
+    $this->assertEquals('403', $client->getResponse()->getStatus());
+
   }
 
   /**
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 2491bc84b3..39955ed48f 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -19,6 +19,7 @@
 use Drupal\Core\Test\FunctionalTestSetupTrait;
 use Drupal\Core\Url;
 use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
+use Drupal\Tests\EntityTestTrait;
 use Drupal\Tests\Traits\Core\CronRunTrait;
 use Drupal\Tests\TestFileCreationTrait;
 use Drupal\Tests\XdebugRequestTrait;
@@ -45,6 +46,9 @@
     createContentType as drupalCreateContentType;
   }
   use CronRunTrait;
+  use EntityTestTrait {
+    buildEntityView as drupalBuildEntityView;
+  }
   use AssertMailTrait {
     getMails as drupalGetMails;
   }
@@ -210,64 +214,6 @@ public function __construct($test_id = NULL) {
   }
 
   /**
-   * Builds the renderable view of an entity.
-   *
-   * Entities postpone the composition of their renderable arrays to #pre_render
-   * functions in order to maximize cache efficacy. This means that the full
-   * renderable array for an entity is constructed in drupal_render(). Some
-   * tests require the complete renderable array for an entity outside of the
-   * drupal_render process in order to verify the presence of specific values.
-   * This method isolates the steps in the render process that produce an
-   * entity's renderable array.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity to prepare a renderable array for.
-   * @param string $view_mode
-   *   (optional) The view mode that should be used to build the entity.
-   * @param null $langcode
-   *   (optional) For which language the entity should be prepared, defaults to
-   *   the current content language.
-   * @param bool $reset
-   *   (optional) Whether to clear the cache for this entity.
-   * @return array
-   *
-   * @see drupal_render()
-   */
-  protected function drupalBuildEntityView(EntityInterface $entity, $view_mode = 'full', $langcode = NULL, $reset = FALSE) {
-    $ensure_fully_built = function(&$elements) use (&$ensure_fully_built) {
-      // If the default values for this element have not been loaded yet, populate
-      // them.
-      if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
-        $elements += \Drupal::service('element_info')->getInfo($elements['#type']);
-      }
-
-      // Make any final changes to the element before it is rendered. This means
-      // that the $element or the children can be altered or corrected before the
-      // element is rendered into the final text.
-      if (isset($elements['#pre_render'])) {
-        foreach ($elements['#pre_render'] as $callable) {
-          $elements = call_user_func($callable, $elements);
-        }
-      }
-
-      // And recurse.
-      $children = Element::children($elements, TRUE);
-      foreach ($children as $key) {
-        $ensure_fully_built($elements[$key]);
-      }
-    };
-
-    $render_controller = $this->container->get('entity.manager')->getViewBuilder($entity->getEntityTypeId());
-    if ($reset) {
-      $render_controller->resetCache([$entity->id()]);
-    }
-    $build = $render_controller->view($entity, $view_mode, $langcode);
-    $ensure_fully_built($build);
-
-    return $build;
-  }
-
-  /**
    * Checks to see whether a block appears on the page.
    *
    * @param \Drupal\block\Entity\Block $block
diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php
index 5751368f61..ca9bc5c409 100644
--- a/core/tests/Drupal/Tests/BrowserTestBase.php
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -652,6 +652,43 @@ protected function drupalGet($path, array $options = [], array $headers = []) {
   }
 
   /**
+   * Retrieves a Drupal path or an absolute path and JSON decodes the result.
+   *
+   * @param \Drupal\Core\Url|string $path
+   *   Drupal path or URL to request AJAX from.
+   * @param array $options
+   *   Array of URL options.
+   * @param array $headers
+   *   Array of headers. Eg array('Accept: application/vnd.drupal-ajax').
+   *
+   * @return array
+   *   Decoded json.
+   */
+  protected function drupalGetJSON($path, array $options = [], array $headers = []) {
+    return Json::decode($this->drupalGetWithFormat($path, 'json', $options, $headers));
+  }
+
+  /**
+   * Retrieves a Drupal path or an absolute path for a given format.
+   *
+   * @param \Drupal\Core\Url|string $path
+   *   Drupal path or URL to request given format from.
+   * @param string $format
+   *   The wanted request format.
+   * @param array $options
+   *   Array of URL options.
+   * @param array $headers
+   *   Array of headers.
+   *
+   * @return mixed
+   *   The result of the request.
+   */
+  protected function drupalGetWithFormat($path, $format, array $options = [], array $headers = []) {
+    $options += ['query' => ['_format' => $format]];
+    return $this->drupalGet($path, $options, $headers);
+  }
+
+  /**
    * Takes a path and returns an absolute path.
    *
    * @param string $path
diff --git a/core/tests/Drupal/Tests/EntityTestTrait.php b/core/tests/Drupal/Tests/EntityTestTrait.php
new file mode 100644
index 0000000000..d9fee3efde
--- /dev/null
+++ b/core/tests/Drupal/Tests/EntityTestTrait.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\Tests;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Render\Element;
+
+/**
+ * Provides methods for entities.
+ *
+ * This trait is meant to be used only by test classes.
+ */
+trait EntityTestTrait {
+
+  /**
+   * Builds the render array view of an entity.
+   *
+   * Entities postpone the composition of their render arrays to #pre_render
+   * functions in order to maximize cache efficacy. This means that the full
+   * render array for an entity is constructed in drupal_render(). Some tests
+   * require the complete render array for an entity outside of the
+   * \Renderer::render() process in order to verify the presence of specific
+   * values. This method isolates the steps in the render process that produce
+   * an entity's render array.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity to prepare a render array for.
+   * @param string $view_mode
+   *   (optional) The view mode that should be used to build the entity.
+   * @param null $langcode
+   *   (optional) For which language the entity should be prepared, defaults to
+   *   the current content language.
+   * @param bool $reset
+   *   (optional) Whether to clear the cache for this entity.
+   *
+   * @return array
+   *   The render array.
+   *
+   * @see \Drupal\Core\Render\Renderer
+   */
+  protected function buildEntityView(EntityInterface $entity, $view_mode = 'full', $langcode = NULL, $reset = FALSE) {
+    $ensure_fully_built = function(&$elements) use (&$ensure_fully_built) {
+      // If the default values for this element have not been loaded yet, populate
+      // them.
+      if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
+        $elements += $this->container->get('element_info')->getInfo($elements['#type']);
+      }
+
+      // Make any final changes to the element before it is rendered. This means
+      // that the $element or the children can be altered or corrected before the
+      // element is rendered into the final text.
+      if (isset($elements['#pre_render'])) {
+        foreach ($elements['#pre_render'] as $callable) {
+          $elements = call_user_func($callable, $elements);
+        }
+      }
+
+      // And recurse.
+      $children = Element::children($elements, TRUE);
+      foreach ($children as $key) {
+        $ensure_fully_built($elements[$key]);
+      }
+    };
+
+    $render_controller = $this->container->get('entity_type.manager')->getViewBuilder($entity->getEntityTypeId());
+    if ($reset) {
+      $render_controller->resetCache([$entity->id()]);
+    }
+    $build = $render_controller->view($entity, $view_mode, $langcode);
+    $ensure_fully_built($build);
+
+    return $build;
+  }
+
+}
