---
title: "An Overview of Testing in Drupal 8"
url: "/articles/an-overview-of-testing-in-drupal-8"
type: article
date: 2017-04-27
updated: 2018-01-11
---

# An Overview of Testing in Drupal 8

#  An Overview of Testing in Drupal 8 

 There are a few ways to do automated testing in Drupal 8. In this article, we look at each and offer advice on how to decide which one to use depending on your needs.

 By

 [  Juampy NR   ](/about/juampy-nr) 

 April 27, 2017

  

I have been working with [Turner](http://www.turner.com) for the past twelve months as part of the Draco team (**Dr**upal **A**pplication **Co**re), who maintains Drupal 8 modules used by TV channels such as [NBA](https://www.givemesport.com/tag/nba/?gr=www), [PGA](https://www.pga.com/), or [TBS](https://www.tbs.com/). Once brands started to use our modules, it was mandatory for us to improve testing coverage and monitoring. By that time, we had unit tests, but there was still a long way to go to get to a point where we could feel safe to merge a given pull request by looking at the code and the test results in Jenkins. This article explains our journey, including both the frustrations and successes implementing testing coverage in Drupal 8.

## General structure of a test

A test *tests something*. Yes, it may sound trivial, but I want to use this triviality to explain why there are different types of tests in Drupal 8 and how they achieve this goal. Every test has a first step where you prepare the context and then a second step where you run assertions against that context. Here are some examples:

ContextTestsI am an editor who has created a page node.When I open the full display view, I should see the title, the body, and an imageI am visiting the homepage.There should be a menu with links to navigate to the different sections of the site, plus a few blocks promoting the main sections.I am an authenticated user who has opened the contact form.Some of the fields such as the name and email should be automatically set. Form submission should pass validation. A confirmation message is shown on success.The assertions in the **Tests** column verify that the code that you have written works as expected under a given **Context**. To me, the end goals of tests are:

- They save me from having to test things manually when I am [peer reviewing code](https://www.lullabot.com/articles/the-peer-review-howto-guide).
- They prove that a new feature or bug fix works as expected.
- They check that the new code does not cause regressions in other areas.

Having said that, letâ&#128;&#153;s dive into how we can accomplish the above in Drupal 8.

## Types of tests available

Depending on what you want to test, there are a few options available in Drupal 8:

- If you want to test **class methods**, then you can write [Unit tests](https://phpunit.de/).
- If you want to test **module APIs**, then your best option is to write [Kernel tests](https://api.drupal.org/api/drupal/core%21modules%21simpletest%21src%21KernelTestBase.php/class/KernelTestBase/8.2.x).
- If you want to test **web interfaces** (I call these **UI tests**), then you have a few options: 
    - If they **do not involve JavaScript**, then you can write [Browser tests](https://www.drupal.org/docs/8/phpunit/phpunit-browser-test-tutorial).
    - If they **do involve JavaScript**, then write a [JavaScript test](https://www.drupal.org/docs/8/phpunit/phpunit-javascript-testing-tutorial) or a [Behat test](https://www.drupal.org/project/drupalextension).

In the following sections we will see how to write and run each of the above, plus a few things to take into account in order to avoid frustration.

## Unit tests

Unit tests in Drupal 8 are awesome. They use the well known [PHPUnit](https://phpunit.de) testing framework and they run blazingly fast. Here is a clip where we show one of our unit tests and then we run the moduleâ&#128;&#153;s unit test suite:

The downside of Unit tests is that if the class has many dependencies, then there is a lot that you need to [mock](https://phpunit.de/manual/current/en/test-doubles.html) in order to prepare the context for your test to work, which complicates understanding and maintaining the test logic. Here is what I do to overcome that: whenever I see that I am spending too much time writing the code to set up the context of a Unit test, I end up converting the test to a Kernel test, which we explore in the next section.

## Kernel tests

Kernel tests are Unit tests on steroids. They are great when you want to test your moduleâ&#128;&#153;s APIs. In a Kernel test, Drupal is installed with a limited set of features so you specify what you need in order to prepare the context of your test. These tests are written in PHPUnit, so you also have all the goodness of this framework such as mocking and [data providers](https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers).

Here is a Kernel test in action. Notice that it is very similar to the clip above about Unit tests:

Kernel tests fetch the database information from core/phpunit.xml where you need to set the database connection details. You may have noticed that these tests are slightly slower than Unit testsâ&#128;&#148;they need to install Drupalâ&#128;&#148;yet they are extremely powerful. There are many good examples of [Kernel tests in Drupal core](http://cgit.drupalcode.org/drupal/tree/core/modules/node/tests/src/Kernel) and contributed modules like [Token](http://cgit.drupalcode.org/token/tree/tests/src/Kernel).

## UI tests

I am grouping together Browser tests, JavaScript tests, and Behat tests as *UI tests* because they all test the user interface through different methods. I want to save you the hassle of going through each of them by suggesting that if you need to test the user interface, then install and use [Drupal Behat Extension](https://www.drupal.org/project/drupalextension). Here is why:

**Browser tests** donâ&#128;&#153;t support JavaScript. Unless you are testing an administration form, chances are that you will need JavaScript to run on a page. They are solid, but I donâ&#128;&#153;t see a reason to write a Browser test when I could write a Behat one.

**JavaScript tests** only support [PhantomJS](https://phantomjs.org/) as the browser. PhantomJS is headless, meaning that there is no visual interface. It is tedious and at times frustrating to write tests using PhantomJS because you need to type and execute commands on a debugger in order to figure out what the test â&#128;&#156;seesâ&#128;&#157; at a given point, while with Behat you can use full-featured Chrome or Firefox (I laugh at myself every time I call this a "bodymore" browser) so debugging becomes way more fun. Moreover, these kind of tests [get randomly stuck](https://github.com/ariya/phantomjs/issues/14286#issuecomment-264863179) both in my local development environment and in Jenkins.

## Discovering Behat tests

[Andrew Berry](https://www.lullabot.com/about/andrew-berry) and myself spent a lot of time trying to get JavaScript tests working locally and in Jenkins without luck, which is why we decided to give Behat tests a go. It felt like salvation because:

- The [setup](https://github.com/jhedstrom/drupalextension#quick-start) process of the [Drupal Behat Extension](https://www.drupal.org/project/drupalextension) module is straightforward.
- We found no bugs in the module while writing tests.
- We can use Chrome or Firefox locally, while Jenkins uses PhantomJS and does not get stuck like it did with JavaScript tests.

Here is a sample test run:

On top of the above, I discovered the usefulness of [feature files](http://docs.behat.org/en/v2.5/guides/1.gherkin.html). A feature file contains human readable steps to test something. As a developer, I thought that I did not need this, but then I discovered how easy it was for the whole team to read the feature file of a module to understand what is tested, and then dive into the step implementations of that feature file to extend them.

Here is a sample feature file:

   

   

 ![Behat feature file](/sites/default/files/styles/wide_xs/public/assets/2017-04/feature_file.png.webp?itok=zk44R65N "feature_file.png")

Each of the above steps matches with a class method that implements its logic. For example, here is the step implementation of the step â&#128;&#156;When I create a Runsheetâ&#128;&#157;:

   

   

 ![Feature step implementation](/sites/default/files/styles/wide_xs/public/assets/2017-04/feature_implementation.png.webp?itok=EKci5tif "feature_implementation.png")

Behat tests [can access Drupalâ&#128;&#153;s APIs](https://behat-drupal-extension.readthedocs.io/en/3.1/drupalapi.html) so, if needed, you can prepare the context of a test programmatically. All that Behat needs in its "behat.yml" file is the URL of your site and the Drupalâ&#128;&#153;s root path:

   

   

 ![Behat configuration file](/sites/default/files/styles/wide_xs/public/assets/2017-04/behat_yml.png.webp?itok=3VMuhgDi "behat_yml.png")

## Now look at your project

Does your project or module have any tests? Does it need them? If so, which type of tests? I hope that now you have the answers to some of these questions thanks to this article. Go ahead and make your project more robust by writing tests.

If you are willing to improve how testing works in Drupal 8 core, here are a few interesting open issues:

- [\[PP-2\] JavascriptTests with webDriver](https://www.drupal.org/node/2775653) aims to replace gastonjs by WebDriver, which would mean that you could use Chrome or Firefox locally instead of just PhantomJS.
- [The PHPUnit initiative](https://www.drupal.org/node/2807237), whose goal is to get rid of Simpletest in Drupal 9.
- [Experiment: Get nightwatch working to functional test Drupal JS via JS](https://www.drupal.org/node/2869825) would allow to write functional tests in JavaScript.

In the next article, I will share with you how do we run Unit, Kernel, and Behat tests automatically when a developer creates a pull request and report their results.

## Acknowledgements

I want to thank the following folks for their help while writing this article:

- [Matt Oliveira](https://www.lullabot.com/about/matt-oliveira), for proofreading.
- [Marcos Cano](https://www.lullabot.com/about/marcos-cano), for his tips and his time spent doing research on this topic.
- [Seth Brown](https://www.lullabot.com/about/seth-brown), for helping me to become a better writer.
- The Draco team at [Turner](http://www.turner.com), for giving me the chance to experiment and implement testing as part of our development workflow.

 Published in:

- [  Drupal Development   ](/topics/drupal-development)

 

   You must have JavaScript enabled to use this form.

## Get in touch with us

### Tell us about your project. We'd love to hear from you!

 First Name  

 Last Name  

 Your email address  

 Your organization  

 How you heard about us  

 Tell us more 

     Leave this field blank