Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ddev/config.wunderio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ hooks:
# @todo We could potentially make this work from recognizing the command.
- exec: |
if ! command -v wdr-core &> /dev/null; then
ln -s ${HOME}/wunderio/core/wdr-core.sh /usr/local/bin/wdr-core
sudo ln -s ${HOME}/wunderio/core/wdr-core.sh /usr/local/bin/wdr-core
fi
# Run once start hook if needed
if [ ! -f "/mnt/wdr-hooks/ddev_web_post_start_once" ]; then
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"require-dev": {
"drupal/core-dev": "^11.4",
"wunderio/code-quality": "^3.0"
"wunderio/code-quality": "dev-GH-126-php"
},
Comment on lines 36 to 38
"conflict": {
"drupal/drupal": "*"
Expand Down
15 changes: 4 additions & 11 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,12 @@
<!-- Filter for coverage reports. -->
<source>
<include>
<directory>./web/core/includes</directory>
<directory>./web/core/lib</directory>
<directory>./web/core/modules</directory>
<directory>./web/core/modules</directory>
<directory>./web/core/sites</directory>
<directory>./web/modules/custom</directory>
<directory>./web/themes/custom</directory>
</include>
<exclude>
<directory>./web/core/modules/*/src/Tests</directory>
<directory>./web/core/modules/*/tests</directory>
<directory>./web/core/modules/*/src/Tests</directory>
<directory>./web/core/modules/*/tests</directory>
<directory>./web/core/modules/*/*/src/Tests</directory>
<directory>./web/core/modules/*/*/tests</directory>
<directory>./web/modules/custom/*/tests</directory>
<directory>./web/themes/custom/*/tests</directory>
</exclude>
</source>
</phpunit>
4 changes: 1 addition & 3 deletions web/modules/custom/phpunit_example/phpunit_example.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ name: PHPUnit Example
type: module
description: Demonstrates how to use PHPUnit-based tests.
package: Example modules
core_version_requirement: ^10 || ^11
dependencies:
- drupal:node
core_version_requirement: ^11
2 changes: 1 addition & 1 deletion web/modules/custom/phpunit_example/phpunit_example.module
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @defgroup phpunit_example Example: PHPUnit
* @ingroup examples
* @{
* This example demonstrates PHPUnit for Drupal 8 unit testing.
* This example demonstrates PHPUnit for Drupal unit testing.
*/

/**
Expand Down
12 changes: 9 additions & 3 deletions web/modules/custom/phpunit_example/src/AddClass.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Drupal\phpunit_example;

/**
Expand All @@ -12,9 +14,13 @@ class AddClass {
/**
* A simple addition method with validity checking.
*
* @param int|float $a
* The parameters are typed as `mixed` (rather than `int|float`) on
* purpose, so that non-numeric values reach the validity check below and
* trigger an \InvalidArgumentException instead of a \TypeError.
*
* @param mixed $a
* A number to add.
* @param int|float $b
* @param mixed $b
* Another number to add.
*
* @return int|float
Expand All @@ -23,7 +29,7 @@ class AddClass {
* @throws \InvalidArgumentException
* If either $a or $b is non-numeric, we can't add, so we throw.
*/
public function add($a, $b) {
public function add(mixed $a, mixed $b): int|float {
// Check whether the arguments are numeric.
foreach ([$a, $b] as $argument) {
if (!is_numeric($argument)) {
Expand Down
81 changes: 40 additions & 41 deletions web/modules/custom/phpunit_example/tests/src/Unit/AddClassTest.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
<?php

declare(strict_types=1);

namespace Drupal\Tests\phpunit_example\Unit;

use Drupal\phpunit_example\AddClass;
// phpcs:ignore SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses.IncorrectlyOrderedUses
use Drupal\Tests\UnitTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;

/**
* AddClass units tests.
* AddClass unit tests.
*
* This test case demonstrates the following PHPUnit annotations:
* - dataProvider
* - expectedException.
* This test case demonstrates the following PHPUnit 11 features:
* - Attribute-based data providers (#[DataProvider]).
* - Attribute-based grouping (#[Group]).
* - expectException() for exception assertions.
*
* 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.
* PHPUnit discovers test classes by their 'Test' suffix and requires them
* to extend \PHPUnit\Framework\TestCase. Drupal supplies
* \Drupal\Tests\UnitTestCase, a subclass of \PHPUnit\Framework\TestCase,
* which this class extends.
*
* 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 whether our
* tests passed by accident.
* 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 whether our tests passed by
* accident.
*
* So with that in mind, it's up to us to build out whatever
* dependencies we need. In the case of AddClass, our needs are meager;
* we only want an instance of AddClass so we can test its add() method.
* So with that in mind, it's up to us to build out whatever dependencies we
* need. In the case of AddClass, our needs are meager; we only want an
* instance of AddClass so we can test its add() method.
*
* @ingroup phpunit_example
*
* @group phpunit_example
* @group examples
*/
#[CoversClass(AddClass::class)]
#[Group('phpunit_example')]
#[Group('examples')]
class AddClassTest extends UnitTestCase {

/**
Expand All @@ -43,19 +48,20 @@ class AddClassTest extends UnitTestCase {
* 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() {
public function testAdd(): void {
$sut = new AddClass();
$this->assertEquals($sut->add(2, 3), 5);
$this->assertEquals(5, $sut->add(2, 3));
}

#[DataProvider('addDataProvider')]
/**
* Test AddClass::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.
* 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.
* '#[DataProvider]' attribute.
*
* The data provider method just returns a big array of arrays of arguments.
* That is, for each time you want this test method run, the data provider
Expand All @@ -80,36 +86,29 @@ public function testAdd() {
* tests 'good' data. When combined with testAddWithBadDataProvider(),
* we get a better picture of the behavior of the method under test.
*
* @dataProvider addDataProvider
*
* @see self::addDataProvider()
*/
public function testAddWithDataProvider($expected, $a, $b) {
public function testAddWithDataProvider(int|float $expected, int|float $a, int|float $b): void {
$sut = new AddClass();
$this->assertEquals($expected, $sut->add($a, $b));
}

#[DataProvider('addBadDataProvider')]
/**
* Test AddClass::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 setExpectedException() method 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. We won't demonstrate that here; it's a much better
* idea to test your exceptions with setExpectedException().
*
* @dataProvider addBadDataProvider
* This test uses the expectException() method 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.
*
* @see self::addBadDataProvider()
*/
public function testAddWithBadDataProvider($a, $b) {
public function testAddWithBadDataProvider(mixed $a, mixed $b): void {
$sut = new AddClass();
$this->expectException(\InvalidArgumentException::class);
$sut->add($a, $b);
Expand All @@ -135,7 +134,7 @@ public function testAddWithBadDataProvider($a, $b) {
*
* @see self::testAddWithDataProvider()
*/
public static function addDataProvider() {
public static function addDataProvider(): array {
return [
[5, 2, 3],
[50, 20, 30],
Expand All @@ -154,7 +153,7 @@ public static function addDataProvider() {
*
* @see self::testAddWithBadDataProvider()
*/
public static function addBadDataProvider() {
public static function addBadDataProvider(): array {
$bad_data = [];
// Set up an array with data that should cause add()
// to throw an exception.
Expand Down