When your module / patch is used by multiple people, you should make sure that it will work with every update, otherwise you'll break other peoples websites.
https://www.drupal.org/project/issues?projects=&status=8
../modules/custom
--lissabon
----lissabon.info.yml
----lissabon.module
----src
------Lissabon.php
----tests
------src
--------Unit
----------LissabonSumTest.php
<?php
namespace Drupal\lissabon;
/**
* Defines a Lissabon class.
*/
class Lissabon {
private $total = 0;
/**
* Returns the total amount.
*
* @return int
* Returns the total
*/
public function getTotal() {
return $this->total;
}
/**
* Sets the total.
*
* @param int $amount
* Amount to be set.
*/
public function setTotal($amount) {
$this->total = $amount;
}
/**
* Adds an amount to the total.
*
* @param int $amount
* Amount to be added.
*/
public function addToTotal($amount) {
$this->total = $this->getTotal() + $amount;
}
}
<?php
namespace Drupal\lissabon;
use Drupal\Tests\UnitTestCase;
/**
* Defines a Unit class.
*
* @group lissabon
*/
class LissabonSumTest extends UnitTestCase {
protected $lissabon;
/**
* Before a test method is run, setUp() is invoked.
*
* We create a new object of the class Lissabon.
*/
public function setUp() {
$this->lissabon = new Lissabon();
}
}
<?php
namespace Drupal\lissabon;
use Drupal\Tests\UnitTestCase;
/**
* Defines a Unit class.
*
* @group lissabon
*/
class LissabonSumTest extends UnitTestCase {
/**
* We unset the lissabon object.
*
* Once test method has finished running, whether it succeeded or
* failed, tearDown() will be invoked.
*/
public function tearDown() {
unset($this->lissabon);
}
}
<?php
namespace Drupal\lissabon;
use Drupal\Tests\UnitTestCase;
/**
* Defines a Unit class.
*
* @group lissabon
*/
class LissabonSumTest extends UnitTestCase {
/**
* Covers setTotal.
*/
public function testSetTotal() {
$this->assertEquals('0', $this->lissabon->getTotal());
$this->lissabon->setTotal(366);
$this->assertEquals(366, $this->lissabon->getTotal());
}
/**
* Covers getTotal.
*/
public function testGetTotal() {
$this->lissabon->setTotal(366);
$this->assertNotEquals(200, $this->lissabon->getTotal());
}
/**
* Covers addToTotal.
*/
public function testAddToTotal() {
$this->lissabon->setTotal(200);
$this->lissabon->addToTotal(166);
$this->assertEquals(366, $this->lissabon->getTotal());
}
}
# Download a drupal installation file (you can also use git clone here)
composer create-project drupal-composer/drupal-project:8.x-dev lissabon-testing
--stability dev --no-interaction --prefer-source
# Install the module you're working on (unless you're working on core,
# here you can alsou use git clone if you want)
composer require drupal/example --prefer-source
# go to the core folder in the web directory
cd lissabon-testing/web/core
# Copy the phpunit.xml.dist file to phpunit.xml
cp phpunit.xml.dist phpunit.xml
# Go to the root of your website (web folder)
cd ..
# start the test (change example for the module you're using or leave it empty to test core)
../vendor/bin/phpunit -c core modules/example
# If you want to test 1 specific test, you can add the following option
--filter testName
../vendor/bin/phpunit modules/custom/lissabon/tests/src/Unit/
../vendor/bin/phpunit -c core modules/custom/lissabon/tests/src/Unit/
#or, go into the core folder
cd core
../../vendor/bin/phpunit ../modules/custom/lissabon/tests/src/Unit/
Kernel tests are integration tests that test on components.
You can install modules
Minimal Drupal, full
Extends from KernelTestBase or EntityKernelTestBase
../modules/custom
--lissabon
----lissabon.info.yml
----lissabon.module
----config
------install
--------lissabon.settings.yml
------schema
--------lissabon.schema.yml
----src
------Form
--------LissabonConfigForm.php
------Lissabon.php
----tests
------src
--------Kernel
----------LissabonConfigTest.php
<?php
namespace Drupal\lissabon\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines a Configuration form.
*/
class LissabonConfigForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'lissabon_config_form';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'lissabon.settings',
];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('lissabon.settings');
$lissabon_name = $config->get('lissabon_name');
$form['lissabon_name'] = [
'#type' => 'textfield',
'#default_value' => isset($lissabon_name) ? $lissabon_name : '',
'#title' => $this->t('Fill in a name'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Save the form values in config.
$lissabon_name = $form_state->getValue('lissabon_name');
\Drupal::configFactory()
->getEditable('lissabon.settings')
->set('lissabon_name', $lissabon_name)
->save();
parent::submitForm($form, $form_state);
}
}
lissabon_name: 'Dev days is awesome!'
lissabon.settings:
type: config_object
label: 'Lissabon testing'
mapping:
lissabon_name:
type: string
label: 'Lissabon name'
<?php
namespace Drupal\lissabon;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests the config for Lissabon.
*
* @package Drupal\lissabon
*/
class LissabonConfigTest extends KernelTestBase {
/**
* User for testing.
*
* @var \Drupal\user\UserInterface
*/
protected $testUser;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'system',
'user',
'lissabon',
];
/**
* Sets up the test.
*/
protected function setUp() {
/** @var \Drupal\user\RoleInterface $role */
parent::setUp();
// We install the config of this module, otherwise the default value won't
// be set.
$this->installConfig(['lissabon']);
}
}
<?php
namespace Drupal\lissabon;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests the config for Lissabon.
*
* @package Drupal\lissabon
*/
class LissabonConfigTest extends KernelTestBase {
/**
* Tests the default config.
*/
public function testDefaultLissabonConfig() {
$config = $this->config('lissabon.settings');
$lissabon_name = $config->get('lissabon_name');
$this->assertEquals('Dev days is awesome!', $lissabon_name);
}
/**
* Tests changing the config.
*/
public function testChangeLissabonConfig() {
// First we check if the config is the default one.
$config = $this->config('lissabon.settings');
$lissabon_name = $config->get('lissabon_name');
$this->assertEquals('Dev days is awesome!', $lissabon_name);
// We change the config.
\Drupal::configFactory()
->getEditable('lissabon.settings')
->set('lissabon_name', 'Lissabon is awesome!')
->save();
// We check if the config has changed.
$lissabon_name = $config->get('lissabon_name');
$this->assertEquals('Lissabon is awesome!', $lissabon_name);
}
}
# Download a drupal installation file
composer create-project drupal-composer/drupal-project:8.x-dev lissabon-testing
--stability dev --no-interaction --prefer-source
# Install the module you're working on (unless you're working on core)
composer require drupal/example --prefer-source
# go to the core folder in the web directory
cd lissabon-testing/web/core
# Copy the phpunit.xml.dist file to phpunit.xml
cp phpunit.xml.dist phpunit.xml
# Create a database for your website (e.g. lissabon_testing).
# in the phpunit.xml file, update the following lines:
<env name="SIMPLETEST_DB" value=""/>
# to
<env name="SIMPLETEST_DB" value="mysql://root:root@localhost/lissabon_testing"/>
# where you change the value with your values (mysql://username:password@localhost/database_name)
# Go to the root of your website (web folder)
cd ..
# start the test (change example for the module you're using or leave it empty to test core)
../vendor/bin/phpunit -c core modules/example
# If you want to test 1 specific test, you can add the following option
--filter testName
../vendor/bin/phpunit -c core modules/custom/lissabon/tests/src/Kernel/
2 types:
../modules/custom
--lissabon
----lissabon.info.yml
----lissabon.module
----lissabon.routing.yml
----config
------install
--------lissabon.settings.yml
------schema
--------lissabon.schema.yml
----src
------Form
--------LissabonConfigForm.php
------Lissabon.php
----tests
------src
--------Functional
----------LissabonConfigFormTest.php
----------LoadTest.php
# Lissabon routing definition
entity.lissabon_routing.collection:
path: '/admin/lissabon'
defaults:
_form: '\Drupal\lissabon\Form\LissabonConfigForm'
_title: 'Lissabon configuration'
requirements:
_permission: 'administer site configuration'
options:
_admin_route: TRUE
<?php
namespace Drupal\lissabon\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines a Configuration form.
*/
class LissabonConfigForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'lissabon_config_form';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'lissabon.settings',
];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('lissabon.settings');
$lissabon_name = $config->get('lissabon_name');
$form['lissabon_name'] = [
'#type' => 'textfield',
'#default_value' => isset($lissabon_name) ? $lissabon_name : '',
'#title' => $this->t('Fill in a name'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Save the form values in config.
$lissabon_name = $form_state->getValue('lissabon_name');
\Drupal::configFactory()
->getEditable('lissabon.settings')
->set('lissabon_name', $lissabon_name)
->save();
parent::submitForm($form, $form_state);
}
}
<?php
namespace Drupal\lissabon;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the config form.
*
* @package Drupal\lissabon
*/
class LissabonConfigFormTest extends BrowserTestBase {
protected $user;
protected $editForm;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['lissabon'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);
}
}
<?php
namespace Drupal\lissabon;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the config form.
*
* @package Drupal\lissabon
*/
class LissabonConfigFormTest extends BrowserTestBase {
/**
* Tests the configuration form.
*/
public function testConfigForm() {
// We try to change the form on /admin/lissabon.
$this->editForm = 'admin/lissabon';
$form = [
'edit-lissabon-name' => 'Lissabon is awesome',
];
$this->drupalPostForm($this->editForm, $form, 'Save');
// We check if our change went through.
$this->drupalGet('admin/lissabon');
$this->assertResponse(200);
$config = $this->config('lissabon.settings');
$this->assertFieldByName('lissabon_name', $config->get('lissabon_name'));
}
}
# Download a drupal installation file
composer create-project drupal-composer/drupal-project:8.x-dev lissabon-testing
--stability dev --no-interaction --prefer-source
# Install the module you're working on (unless you're working on core)
composer require drupal/example --prefer-source
# go to the core folder in the web directory
cd lissabon-testing/web/core
# Copy the phpunit.xml.dist file to phpunit.xml
cp phpunit.xml.dist phpunit.xml
# Create a database for your website (e.g. lissabon_testing).
# in the phpunit.xml file, update the following lines:
<env name="SIMPLETEST_DB" value=""/>
# to
<env name="SIMPLETEST_DB" value="mysql://root:root@localhost/lissabon_testing"/>
# where you change the value with your values (mysql://username:password@localhost/database_name)
# Now you'll have to set up a base url as well, so change the following line
<env name="SIMPLETEST_BASE_URL" value=""/>
# to
<env name="SIMPLETEST_BASE_URL" value="http://lissabontesting.local"/>
# where you change the value with your values (http://lissabontesting.local)
# Go to the root of your website (web folder)
cd ..
# start the test (change example for the module you're using or leave it empty to test core)
../vendor/bin/phpunit -c core modules/example
# If you want to test 1 specific test, you can add the following option
--filter testName
../vendor/bin/phpunit -c core modules/custom/lissabon/tests/src/Unit/
# In the phpunit.xml file, change
<env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/>
# to
<env name="BROWSERTEST_OUTPUT_DIRECTORY" value="/Applications/MAMP/htdocs/customprojects/lissabon-testing/web/sites/default/files"/>
# where The value is a writable folder on your site
# Add this to your command.
--printer="\Drupal\Tests\Listeners\HtmlOutputPrinter"
# Execute test while printing html
../vendor/bin/phpunit -c core modules/custom/lissabon/tests/src/Functional/
--printer="\Drupal\Tests\Listeners\HtmlOutputPrinter"
By starting with the easy task, you'll get more and more familiar with the code for testing.
A lot of tests are similar, use that to your advantage and read other tests of similar modules.
Try to find a maintainer/co-maintainer of a module you would like to help on.
They will be glad to help you and guide you through it.
On your project page, create a roadmap with future steps of your module.
Add a segment tests that you'll update along the way
When creating a module with Drupal console, it asks if you want to create a test.
This is a very simple functional test to check if the front page is still working
<?php
namespace Drupal\Tests\facets_autocomplete\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Simple test to ensure that main page loads with module enabled.
*
* @group facets_autocomplete
*/
class LoadTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['facets_autocomplete'];
/**
* A user with permission to administer site configuration.
*
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);
}
/**
* Tests that the home page loads with a 200 response.
*/
public function testLoad() {
$this->drupalGet(Url::fromRoute('<front>'));
$this->assertSession()->statusCodeEquals(200);
}
}
https://joind.in/talk/21543
@brentgees