diff --git a/src/Handler.php b/src/Handler.php
index 19c53f36eb1231baedca4f82f2c96ba1cd63520c..df5e59892a2fb2eae1bd9ed76a13cc073b9c2fad 100644
--- a/src/Handler.php
+++ b/src/Handler.php
@@ -105,12 +105,11 @@ class Handler {
     // Directory where this plugin is being installed.
     $pluginRoot = $installationManager->getInstallPath($this->getPackage('lakedrops/d8-project-scaffold-developer'));
 
-    // Create contrib/custom dirs for modules, profiles, themes and drush.
+    // Create contrib/custom dirs for modules, profiles and themes.
     foreach ([
       $webRoot . '/modules',
       $webRoot . '/profiles',
       $webRoot . '/themes',
-      'drush',
     ] as $dir) {
       foreach (['contrib', 'custom'] as $subdir) {
         $path = $dir . '/' . $subdir;
@@ -129,6 +128,8 @@ class Handler {
       'settings/default',
       'files/default/files',
       'files/default/private',
+      'drush',
+      'tests',
     ] as $dir) {
       $path = $projectRoot . '/' . $dir;
       if (!$fs->exists($path)) {
@@ -181,6 +182,11 @@ class Handler {
       $fs->copy($pluginRoot . '/templates/drush/' . $template, 'drush/' . $template);
     }
 
+    // Copy Test files.
+    foreach (['phpunit.xml.dist'] as $template) {
+      $fs->copy($pluginRoot . '/templates/tests/' . $template, 'tests/' . $template);
+    }
+
     // Link Drupal site's config directory.
     if (!$fs->exists($webRoot . '/sites/default/files/config')) {
       $rel = substr($fs->makePathRelative($projectRoot . '/config/default', $projectRoot . '/files/default/files/config'), 3, -1);
diff --git a/src/TestSuite/Base.php b/src/TestSuite/Base.php
new file mode 100644
index 0000000000000000000000000000000000000000..87f41e4cf75d289594a8c420a9b6d9beb8b1d16d
--- /dev/null
+++ b/src/TestSuite/Base.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace LakeDrops\Drupal8ScaffoldDeveloper\TestSuites;
+
+use Drupal\simpletest\TestDiscovery;
+use PHPUnit\Framework\TestSuite;
+
+/**
+ * Base class for Drupal test suites.
+ */
+abstract class Base extends TestSuite {
+
+  /**
+   * Finds extensions in a Drupal installation.
+   *
+   * An extension is defined as a directory with an *.info.yml file in it.
+   *
+   * @param string $root
+   *   Path to the root of the Drupal installation.
+   *
+   * @return string[]
+   *   Associative array of extension paths, with extension name as keys.
+   */
+  protected function findExtensionDirectories($root) {
+    $paths = [
+      $root . '/modules/custom',
+      $root . '/profiles/custom',
+      $root . '/themes/custom',
+    ];
+    $extension_roots = array_filter($paths, 'file_exists');
+
+    $extension_directories = array_map('drupal_phpunit_find_extension_directories', $extension_roots);
+    return array_reduce($extension_directories, 'array_merge', []);
+  }
+
+  /**
+   * Find and add tests to the suite for core and any extensions.
+   *
+   * @param string $root
+   *   Path to the root of the Drupal installation.
+   * @param string $suite_namespace
+   *   SubNamespace used to separate test suite. Examples: Unit, Functional.
+   */
+  protected function addTestsBySuiteNamespace($root, $suite_namespace) {
+    foreach ($this->findExtensionDirectories($root) as $extension_name => $dir) {
+      $test_path = "$dir/tests/src/$suite_namespace";
+      if (is_dir($test_path)) {
+        $this->addTestFiles(TestDiscovery::scanDirectory("Drupal\\Tests\\$extension_name\\$suite_namespace\\", $test_path));
+      }
+    }
+  }
+
+}
diff --git a/src/TestSuite/Functional.php b/src/TestSuite/Functional.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e901902b16305202d9d808708bdea8222d32ad6
--- /dev/null
+++ b/src/TestSuite/Functional.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace LakeDrops\Drupal8ScaffoldDeveloper\TestSuites;
+
+require_once __DIR__ . '/Base.php';
+
+/**
+ * Discovers tests for the functional test suite.
+ */
+class Functional extends Base {
+
+  /**
+   * Factory method which loads up a suite with all functional tests.
+   *
+   * @return static
+   *   The test suite.
+   */
+  public static function suite() {
+    $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/web';
+
+    $suite = new static('functional');
+    $suite->addTestsBySuiteNamespace($root, 'Functional');
+
+    return $suite;
+  }
+
+}
diff --git a/src/TestSuite/Unit.php b/src/TestSuite/Unit.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1dd80bb867ae3e708c7f9312bcc108f27b15457
--- /dev/null
+++ b/src/TestSuite/Unit.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace LakeDrops\Drupal8ScaffoldDeveloper\TestSuites;
+
+require_once __DIR__ . '/Base.php';
+
+/**
+ * Discovers tests for the unit test suite.
+ */
+class Unit extends Base {
+
+  /**
+   * Factory method which loads up a suite with all unit tests.
+   *
+   * @return static
+   *   The test suite.
+   */
+  public static function suite() {
+    $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/web';
+
+    $suite = new static('unit');
+    $suite->addTestsBySuiteNamespace($root, 'Unit');
+
+    return $suite;
+  }
+
+}
diff --git a/templates/tests/phpunit.xml.dist b/templates/tests/phpunit.xml.dist
new file mode 100644
index 0000000000000000000000000000000000000000..4aff2ec2a5ef0a215873789ad3670958014a41dc
--- /dev/null
+++ b/templates/tests/phpunit.xml.dist
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- TODO set checkForUnintentionallyCoveredCode="true" once https://www.drupal.org/node/2626832 is resolved. -->
+<!-- PHPUnit expects functional tests to be run with either a privileged user
+ or your current system user. See core/tests/README.md and
+ https://www.drupal.org/node/2116263 for details.
+-->
+<phpunit bootstrap="../web/core/tests/bootstrap.php" colors="true"
+         beStrictAboutTestsThatDoNotTestAnything="true"
+         beStrictAboutOutputDuringTests="true"
+         beStrictAboutChangesToGlobalState="true">
+<!-- TODO set printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter" once
+ https://youtrack.jetbrains.com/issue/WI-24808 is resolved. Drupal provides a
+ result printer that links to the html output results for functional tests.
+ Unfortunately, this breaks the output of PHPStorm's PHPUnit runner. However, if
+ using the command line you can add
+ - -printer="\Drupal\Tests\Listeners\HtmlOutputPrinter" to use it (note there
+ should be no spaces between the hyphens).
+-->
+  <php>
+    <!-- Set error reporting to E_ALL. -->
+    <ini name="error_reporting" value="32767"/>
+    <!-- Do not limit the amount of memory tests take to run. -->
+    <ini name="memory_limit" value="-1"/>
+    <!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
+    <env name="SIMPLETEST_BASE_URL" value=""/>
+    <!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/databasename#table_prefix -->
+    <env name="SIMPLETEST_DB" value=""/>
+    <!-- Example BROWSERTEST_OUTPUT_DIRECTORY value: /path/to/webroot/sites/simpletest/browser_output -->
+    <env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/>
+    <!-- To disable deprecation testing completely uncomment the next line. -->
+    <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/> -->
+    <!-- Example for changing the driver class for mink tests MINK_DRIVER_CLASS value: 'Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver' -->
+    <!-- Example for changing the driver args to mink tests MINK_DRIVER_ARGS value: '["http://127.0.0.1:8510"]' -->
+    <!-- Example for changing the driver args to phantomjs tests MINK_DRIVER_ARGS_PHANTOMJS value: '["http://127.0.0.1:8510"]' -->
+    <!-- Example for changing the driver args to webdriver tests MINK_DRIVER_ARGS_WEBDRIVER value: '["firefox", null, "http://localhost:4444/wd/hub"]' -->
+  </php>
+  <testsuites>
+    <testsuite name="unit">
+      <file>../vendor/lakedrops/d8-project-scaffold-developer/src/TestSuite/Unit.php</file>
+    </testsuite>
+    <testsuite name="functional">
+      <file>../vendor/lakedrops/d8-project-scaffold-developer/src/TestSuite/Functional.php</file>
+    </testsuite>
+  </testsuites>
+  <listeners>
+    <listener class="\Drupal\Tests\Listeners\DrupalListener">
+    </listener>
+    <!-- The Symfony deprecation listener has to come after the Drupal listener -->
+    <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
+    </listener>
+  </listeners>
+  <!-- Filter for coverage reports. -->
+  <filter>
+    <whitelist>
+      <directory>../web/modules/custom</directory>
+      <directory>../web/profiles/custom</directory>
+      <directory>../web/themes/custom</directory>
+      <!-- By definition test classes have no tests. -->
+      <exclude>
+        <directory suffix="Test.php">./</directory>
+        <directory suffix="TestBase.php">./</directory>
+      </exclude>
+     </whitelist>
+  </filter>
+</phpunit>