diff --git a/phpunit_example/lib/Drupal/phpunit_example/Controller/PHPUnitExampleController.php b/phpunit_example/lib/Drupal/phpunit_example/Controller/PHPUnitExampleController.php
new file mode 100644
index 0000000..1317b4f
--- /dev/null
+++ b/phpunit_example/lib/Drupal/phpunit_example/Controller/PHPUnitExampleController.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\phpunit_example\Controller\PHPUnitExampleController.
+ */
+
+namespace Drupal\phpunit_example\Controller;
+
+/**
+ * Controller routines for filter routes.
+ */
+class PHPUnitExampleController {
+
+  /**
+   * Displays a page with a descriptive page.
+   *
+   * Our router maps this method to the path 'examples/phpunit_example'.
+   */
+  function description() {
+    $build = array(
+      '#markup' => t('<h2>PHPUnit for Drupal: A very basic how-to.</h2>
+
+<h3>How to use this example module</h3>
+
+<p>You really should be reading the various docblocks in the test files.</p>
+
+<h3>Drupalisms</h3>
+
+<ul>
+<li><p>Tests belong in their own <code>Drupal\[your_module]\Tests</code> namespace. Under Drupal&#39;s PSR-0 system, this means your PHPUnit-based tests should go in <code>[your_module]/tests/Drupal/[your_module]/Tests/</code>. Modules which are only used for testing purposes should be in <code>[your_module]/tests/modules/[testing_module]/</code></p></li>
+<li><p>Your test case should subclass <code>Drupal\Tests\UnitTestCase</code>.</p></li>
+<li><p>You can run PHPUnit-based tests from within Drupal 8, by enabling the SimpleTest module and then selecting the PHPUnit group from the testing page. As of this writing, this method doesn&#39;t provide any useful output.</p></li>
+</ul>
+
+<h3>Standard PHPUnit Practices</h3>
+
+<p>You can (and really, should) run PHPUnit from the command line. On unix-based systems this means you need to <code>cd core</code> and then <code>./vendor/bin/phpunit</code>.</p>
+
+<p>Also, you should mark your tests as belonging to a group, so they can be run independently. You do this by annotating your test classes with <code>@group GroupName</code>. Currently, no conventions exist for how these groups should be named. You use groups like this: <code>./vendor/bin/phpunit --group GroupName</code>.</p>'),
+    );
+
+    return $build;
+  }
+
+}
diff --git a/phpunit_example/lib/Drupal/phpunit_example/SystemUnderTest/SystemUnderTest.php b/phpunit_example/lib/Drupal/phpunit_example/SystemUnderTest/SystemUnderTest.php
new file mode 100644
index 0000000..3fe23c9
--- /dev/null
+++ b/phpunit_example/lib/Drupal/phpunit_example/SystemUnderTest/SystemUnderTest.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\phpunit_example\SystemUnderTest
+ */
+
+namespace Drupal\phpunit_example;
+
+/**
+ * A class with features to show how to do unit testing.
+ */
+class SystemUnderTest {
+  
+  /**
+   * A simple addition method with validity checking.
+   *
+   * @param $a
+   *   A number to add.
+   * @param $b
+   *   Another number to add.
+   *
+   * @return
+   *   The sum of $a and $b.
+   *
+   * @throws \InvalidArgumentException
+   */
+  public function add($a, $b) {
+    // Check whether the arguments are numeric.
+    foreach(array($a, $b) as $argument) {
+      if (!is_numeric($argument)) {
+        throw new \InvalidArgumentException('Arguments must be numeric.');
+      }
+    }
+    return $a + $b;
+  }
+
+}
diff --git a/phpunit_example/phpunit_example.info.yml b/phpunit_example/phpunit_example.info.yml
new file mode 100644
index 0000000..c6d179c
--- /dev/null
+++ b/phpunit_example/phpunit_example.info.yml
@@ -0,0 +1,5 @@
+name: PHPUnit example
+type: module
+description: 'How to use PHPUnit-based tests with Drupal 8.'
+package: Example modules
+core: 8.x
diff --git a/phpunit_example/phpunit_example.module b/phpunit_example/phpunit_example.module
new file mode 100644
index 0000000..816d820
--- /dev/null
+++ b/phpunit_example/phpunit_example.module
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @file
+ * Module file for phpunit_example_module.
+ */
+
+/**
+ * @defgroup phpunit_example Example: PHPUnit
+ * @ingroup examples
+ * @{
+ * This example demonstrates how a module can display a page at a given URL.
+ *
+ * It's important to understand how the menu system works in order to
+ * implement your own pages. See the Menu Example module for some insight.
+ *
+ * @see menu_example
+ */
+
+/**
+ * Implements hook_help().
+ *
+ * Through hook_help(), a module can make documentation available to the user
+ * for the module as a whole or for specific paths. Where the help appears
+ * depends on the $path specified.
+ *
+ * In the first example below, the help text will appear on the simple page
+ * defined in hook_menu below in the region designated for help text.
+ *
+ * In the second example, the text will be available through the module page as
+ * a link beside the module or on the admin help page (admin/help) in the list
+ * of help topics using the name of the module. To specify help in the admin
+ * section use the module name in the path as in the second case below.
+ *
+ * @see hook_help()
+ */
+function phpunit_example_help($path, $arg) {
+  switch ($path) {
+    case 'examples/page_example/simple':
+      // Help text for the simple page registered for this path.
+      return t('This is help text for the simple page.');
+
+    case 'admin/help#page_example':
+      // Help text for the admin section, using the module name in the path.
+      return t("This is help text created in the page example's second case.");
+  }
+}
+
+/**
+ * Implements hook_permission().
+ *
+ * Since the access to our new custom pages will be granted based on
+ * special permissions, we need to define what those permissions are here.
+ * This ensures that they are available to enable on the user role
+ * administration pages.
+ */
+function page_example_permission() {
+  return array(
+    'access simple page' => array(
+      'title' => t('Access simple page'),
+      'description' => t('Allow users to access simple page'),
+    ),
+    'access arguments page' => array(
+      'title' => t('Access page with arguments'),
+      'description' => t('Allow users to access page with arguments'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_menu().
+ *
+ * We will define some menu items, and their paths will be interpreted as follows:
+ *
+ * @see hook_menu()
+ * @see menu_example
+ */
+function phpunit_example_menu() {
+  $items['examples/phpunit_example'] = array(
+    'title' => 'PHPUnit Example',
+    'route_name' => 'phpunit_example_description',
+    'expanded' => TRUE,
+  );
+  return $items;
+}
+
+/**
+ * @} End of "defgroup phpunit_example".
+ */
diff --git a/phpunit_example/phpunit_example.routing.yml b/phpunit_example/phpunit_example.routing.yml
new file mode 100644
index 0000000..fdcca2a
--- /dev/null
+++ b/phpunit_example/phpunit_example.routing.yml
@@ -0,0 +1,7 @@
+# In order to create pages is necessary to define routes for them.
+phpunit_example_description:
+  pattern: 'examples/page_example'
+  defaults:
+    _content: '\Drupal\phpunit_example\Controller\PHPUnitExampleController::description'
+  requirements:
+    _access: 'TRUE'
diff --git a/phpunit_example/tests/Drupal/phpunit_example/Tests/SystemUnderTestTest.php b/phpunit_example/tests/Drupal/phpunit_example/Tests/SystemUnderTestTest.php
new file mode 100644
index 0000000..3f5a61e
--- /dev/null
+++ b/phpunit_example/tests/Drupal/phpunit_example/Tests/SystemUnderTestTest.php
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\phpunit_example\Tests\SystemUnderTestTest.
+ */
+
+namespace Drupal\phpunit_example\Tests;
+
+use Drupal\Tests\UnitTestCase;
+
+use Drupal\phpunit_example\SystemUnderTest;
+
+/**
+ * A Drupal PHPUnit test case against an example class.
+ *
+ * PHPUnit looks for classes with names ending in 'Test'. Then it
+ * looks to see whether that class is a subclass of
+ * \PHPUnit_Framework_TestCase. Drupal supplies us with
+ * Drupal\Tests\UnitTestCase, which is a subclass of
+ * \PHPUnit_Framework_TestCase. So yay, PHPUnit will find this class.
+ *
+ * In unit testing, there should be as few dependencies as possible.
+ * We want the smallest number of moving parts to be interacting in
+ * our test, or we won't be sure where the errors are, or if our tests
+ * passed by accident.
+ *
+ * So with that in mind, UnitTestCase provides us with very few methods.
+ * It's up to us to build out whatever dependencies we need.
+ *
+ * Annotation for api.drupal.org:
+ * @ingroup phpunit_example
+ *
+ * Annotation for PHPUnit:
+ * @group phpunit_example
+ */
+class SystemUnderTestTest extends UnitTestCase {
+
+  /**
+   * Test SystemUnderTest::add().
+   *
+   * This is a very simple unit test of a single method. It has
+   * a single assertion, and that assertion is probably going to
+   * pass. It ignores most of the problems that could arise in the
+   * method under test, so therefore: It is not a very good test.
+   */
+  public function testAdd() {
+    $sut = new SystemUnderTest();
+    $this->assertEquals($sut->add(2, 3), 5);
+  }
+
+  /**
+   * Data provider for testAddWithDataProvider().
+   *
+   * Data provider methods take no arguments and return an array of data
+   * to use for tests. Each element of the array is another array, which
+   * corresponds to the arguments in the test method's signature.
+   *
+   * Note also that PHPUnit tries to run tests using methods that begin
+   * with 'test'. This means that data provider method names should not
+   * begin with 'test'. Also, by convention, they should end with
+   * 'DataProvider'.
+   *
+   * @see SystemUnderTestTest::testAddWithDataProvider()
+   */
+  public function addDataProvider() {
+    return array(
+      // array($a, $b, $expected)
+      array(2, 3, 5),
+      array(20, 30, 50),
+    );
+  }
+
+  /**
+   * Test SystemUnderTest::add() with a data provider method.
+   *
+   * This method is very similar to testAdd(), but uses a data provider method
+   * to test with a wider range of data.
+   *
+   * You can tell PHPUnit which method is the data provider using the
+   * '@dataProvider' annotation.
+   *
+   * This test has a better methodology than testAdd(), because it can easily
+   * be adapted by other developers, and because it tries more than one data
+   * set. This test is much better than testAdd(), although it still only
+   * tests 'good' data. When combined with testAddWithBadDataProvider(),
+   * we get a better picture of the behavior of the method under test.
+   *
+   * @dataProvider addDataProvider
+   *
+   * @see SystemUnderTestTest::addDataProvider()
+   */
+  public function testAddWithDataProvider($a, $b, $expected) {
+    $sut = new SystemUnderTest();
+    $this->assertEquals($sut->add($a, $b), $expected);
+  }
+
+  /**
+   * Data provider for testAddWithBadDataProvider().
+   *
+   * Since SystemUnderTest::add() can throw exceptions, it's time
+   * to give it some data that will cause these exceptions.
+   *
+   * add() should throw exceptions if either of it's arguments are
+   * not numeric, and we will generate some test data to prove that
+   * this is what it actually does.
+   *
+   * @see SystemUnderTestTest::testAddWithBadDataProvider()
+   */
+  public function addBadDataProvider() {
+    $badData = array();
+    // Set up an array with data that should cause add()
+    // to throw an exception.
+    $badDataTypes = array('string', FALSE, array('foo'), new \stdClass());
+    // Create some data where both $a and $b are bad types.
+    foreach ($badDataTypes as $badDatumA) {
+      foreach ($badDataTypes as $badDatumB) {
+        $badData[] = array($badDatumA, $badDatumB);
+      }
+    }
+    // Create some data where $a is good and $b is bad.
+    foreach($badDataTypes as $badDatumB) {
+      $badData[] = array(1, $badDatumB);
+    }
+    // Create some data where $b is good and $a is bad.
+    foreach($badDataTypes as $badDatumA) {
+      $badData[] = array($badDatumA, 1);
+    }
+    return $badData;
+  }
+
+  /**
+   * Test SystemUnderTest::add() with data that should throw an exception.
+   *
+   * This method is similar to testAddWithDataProvider(), but the data
+   * provider gives us data that should throw an exception.
+   *
+   * This test uses the '@expectedException' annotation to tell PHPUnit that
+   * a thrown exception should pass the test. You specify a
+   * fully-qualified exception class name. If you specify \Exception, PHPUnit
+   * will pass any exception, whereas a more specific subclass of \Exception
+   * will require that exception type to be thrown.
+   *
+   * Alternately, you can use try and catch blocks with assertions in order
+   * to test exceptions.
+   *
+   * @dataProvider addBadDataProvider
+   * @expectedException \InvalidArgumentException
+   *
+   * @see SystemUnderTestTest::addBadDataProvider()
+   */
+  public function testAddWithBadDataProvider($a, $b) {
+    $sut = new SystemUnderTest();
+    $sut->add($a, $b);
+  }
+
+}
