Problem/Motivation

In the past, if we wanted to test the behavior of a hook function, then we needed to implement that hook inside of a "test module." Test modules are typically located in core/modules/*/tests/modules/ directories.

#3502432: Make hook testing with kernel tests very simple provided an alternative to creating test modules for Kernel tests. Now hooks may be created as functions directly in Kernel test classes. This reduces the amount of boilerplate necessary for testing hooks, couples the hook function tightly with its related test, and gives us an opportunity to remove some test modules from Core.

The MailCancelTestHooks class (core/modules/system/tests/modules/mail_cancel_test/src/Hook/MailCancelTestHooks.php) has a hook function that appears to only be used by a Kernel test. Move the hook function into its related test.

See the following for helpful information on making this change:

Proposed resolution

  • Search for the test class or classes that use the mail_cancel_test module using any method you prefer, for example grep or an IDE's search.
  • Verify that the hook is only used by one or more Kernel tests. Comment if you believe this is not true.
  • Copy the hook function from the test module into the Kernel test class(es).
  • Delete the hook function. If the Hook class is empty, delete the entire class. If the test module has no other code, delete the entire module.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3576673

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

dcam created an issue. See original summary.

dcam’s picture

Search for the test class or classes that use the mail_html_test module using any method you prefer, for example grep or an IDE's search.

I could give the test class in the issue summary, but there are reasons that I haven't:

  • I don't know what scope other hook move issues will have. Some may impact multiple tests. It may not be feasible to customize every issue summary with this information.
  • Asking contributors to search Core by themselves will develop familiarity with the code and tests as opposed to handing them the answer.

But this is a less friendly approach for new contributors. So this is one point we need feedback about.

dcam’s picture

Issue summary: View changes

I put the wrong class, file, and module name in the issue summary. Sorry about that!

sujal kshatri made their first commit to this issue’s fork.

sujal kshatri’s picture

Assigned: Unassigned » sujal kshatri

sujal kshatri’s picture

ISSUE DOCUMENTATION by ME

first of thank you so much to @dcam for letting me work on this issue

It consists of all of my thought process as a new contributor, every little detail and places I got stuck:-

So my first impression of this issue was that this issue is about moving something, meaning we need to cut some portion of code and paste it at a necessary place. This looks like a straightforward issue.

Now the question arose: what exactly do I need to move in this codebase?
We first need to find that portion. The issue description indicates toward mail_cancel_test, so my first step was to search for the test module. Using IDE search, I found the module at `core/modules/system/tests/modules/mail_cancel_test`. The next step was to verify if it contained something other than hook logic. I didn’t find anything else, so it was a safe candidate.

Now the next step was to check if it is used only by the Kernel test (because there may be cases where it is used by other services as well — like a plugin…). It was confirmed that it was only used by the Kernel test.

Now the next step was to locate the Kernel test (`core/modules/system/tests/src/Kernel/Mail/MailTest.php`). It was fairly easy to find using the earlier result from IDE search.

Now this is where the implementation part started :-

Copied the original test module hook and pasted it into the Kernel test class. Pasting it next to the function where it is used is a better approach.
Note:- importing `(use Drupal\Core\Hook\Attribute\Hook;)` is important for the hook logic.

Now the next step was interesting :-

To remove the module from `$modules`

Before:

protected static $modules = [
  'file',
  'mail_cancel_test',
  'system',
];


After:

<code>
protected static $modules = [
  'file',
  'system',
];

This should only be done if the module is not used as any other service like a plugin. If it is used in a plugin, then I believe it should stay there because it might be used later as `$this->configureDefault…`
If that module is not enabled, plugin discovery will fail.
Therefore :-

Then the main part, i.e., to remove the module, I removed the (`core/modules/system/tests/modules/mail_cancel_test`) directory because it only contained hook logic (if it contains other logic like a plugin, then only the file containing the hook logic should be removed; others should be changed with the guidance of the mentor).

And the final step would be to run Kernel tests locally.

Note:-

After discussing with my mentor, comments in the Kernel test that reference the deleted module should be changed to reference class::function().

Example:-

Before:

/**
 * Tests that message sending may be canceled.
 *
 * @see mail_cancel_test_mail_alter()
 */

After:

/**
 * Tests that message sending may be canceled.
 *
 * @see ::mailAlter()
 */

My Inputs:-

1. Understanding the issue before solving the issue, I believe, is the most important part for a new contributor.
My understanding was:-

Before Drupal 11.3.0, if you wanted to test a hook in Drupal, you had to create a small test module with its own folder, `.info.yml` file, and hook implementation, just to trigger that hook during a Kernel test. It worked, but it added extra files and maintenance overhead. Starting with Drupal 11.3.0, you can now define hooks directly inside your Kernel test class using the `#[Hook('hook_name')]` attribute. This keeps everything in one place, makes tests easier to read and maintain, and reduces unnecessary test modules. The only limitation is that advanced hook ordering or reordering isn’t supported in this setup, but for most testing cases, it’s more than enough.

2. For new contributors, the moving part is easy and will help contributors get familiar with the core. The only tricky part is if that module is used in more places other than the Kernel test.

3. I consider myself a newbie, and I was able to solve this within 1 hour (running tests and analyzing things took time). Therefore, I would highly recommend it for first-timers (given that the issue is not very complex).

4. If a little more guidance is included in the issue description (for example — they can refer to this issue and its solution that I have worked on as a reference), then I believe new contributors will be able to understand this issue very clearly and will know what to do.

5. The example commit given in this issue can be confusing for new contributors (because it was confusing to me as well).

Finally:-

As a new contributor, I recommend it to new contributors, as I was able to solve this issue with the already given instructions. It will make them learn how valuable an issue description and historical context are.

sujal kshatri’s picture

Status: Active » Needs review
dcam’s picture

Issue summary: View changes

Removed the summary text barring other users from working on the issue.

dcam’s picture

Status: Needs review » Needs work

There are a couple of comments on the MR that need attention, so I'm setting the status to Needs Work.

Otherwise, you did a fantastic job on this, @sujal kshartri. Thank you very much for your hard work in evaluating this issue. Also for working on the MR. I know it was "easy" for you, but you still did a good job and were thoughtful with how you accomplished the task. I'm going to take your feedback and use it to determine our path forward from here. If we do end up making more of these issues, then a next step may be for you to help review them since you're now one of the people who has the most experience at doing this work.

sujal kshatri’s picture

Thanks everyone , and yeah I would love to help reviewing issues related to this

dcam’s picture

Status: Needs work » Reviewed & tested by the community

The Build test failure is almost certainly unrelated, but I can't re-run it right now. Our feedback was addressed. This one looks good to me.

  • longwave committed 6833e0e2 on 11.x
    test: #3576673 Move hooks from mail_cancel_test into the Kernel test
    
    By...

  • longwave committed 783db196 on main
    test: #3576673 Move hooks from mail_cancel_test into the Kernel test
    
    By...
longwave’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Great work @sujal kshatri and also great mentoring here by @dcam. This is the first time I had seen this hook test simplification and it's really nice!

Committed and pushed 783db196aa9 to main and 6833e0e24be to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.