Score:0

Running tests for a module without requiring a full site installation

in flag

I'm building a custom module (for use on multiple projects) with code that relies on stuff from Drupal core and third party modules (e.g. extending classes, implementing interfaces, annotating as plugins, etc.). I would like to start writing tests for them, with unit tests to begin with. But so far, all of the resources point to putting the module in a Drupal installation and test in that setup, as if I'm running a full Drupal site - even for a unit test.

I was more imagining that my module would have the runner, the dependencies, and Drupal core be dependencies (or dev dependencies) - just like how JavaScript tests are usually written, whether it's unit tests or headless browser tests. That is, JavaScript testing doesn't require you to pop your code in some other code before you can start testing.

Can this be achieved? Or is putting the my modules code in a Drupal install really the only way to test Drupal modules?

Jaypan avatar
de flag
Unit tests do not bootstrap the whole system, and run very fast. Kernel tests, functional tests, and JavaScript tests require bootstrapping the system, and take longer.
in flag
@Jaypan Yup, I'm aware of the kinds of tests and how they run. The question is more like "can Drupal core and third-party modules be 'dev dependencies' so I can satisfy my modules dependencies during testing and run my unit tests without setting up Drupal in a site-like fashion?"
Jaypan avatar
de flag
Not exactly, as you would then be testing the external code, rather than your own unit of code. In this case you instead create mocks/stubs, which imitate the service you are trying to call: https://www.drupal.org/docs/automated-testing/phpunit-in-drupal/mocking-entities-and-services-with-phpunit-and-mocks
Jaypan avatar
de flag
I put those last two comments together into a more comprehensive reply to the original question.
Score:2
de flag

Unit tests do not bootstrap the whole system, and run very fast. Kernel tests, functional tests, and JavaScript tests require bootstrapping the system, and take longer.

With unit testing, you don't declare dependencies upon foreign code. This is because tests unit test a piece of code, not the foreign code. If an error was introduced into the foreign code, and the code being tested depended upon that code, the tests would fail, even though the code being tested was still correct. This would be a false fail, and a developer would probably spend time trying to figure out why their code had failed, even though it had not.

The solution is to use mocks to stub the data. A mock is a fake service, created within the test, that simulates the actual dependent service. So when the code being tested makes a call to foreign code, the mock returns a response (aka a stub) as if the foreign code had responded, taking away any risk of false positives from the foreign code failing, since your test will always respond, and will always respond exactly as you set it to.

in flag
I get that I can mock dependencies (e.g. services, arguments, etc.). I was more wondering what happens to classes declared in `use`, or the class I'm extending, or the interface I'm implementing, or the traits I'm applying. For example, I build a plugin _extending_ core's `PluginBase`. Do I need to do anything special for my test with regards to `PluginBase`? Does the test go looking for `PluginBase`? Do I need the real `PluginBase`? Or do I have to use a fake `PluginBase`? I'm just testing some basic logic in that plugin, not the whole plugin mechanism.
Jaypan avatar
de flag
I would suggest looking at some examples in core, or opening new tickets for your questions, as I feel the original question has been answered, that being that you use mocks to deal with dependencies in unit tests. And as core modules are doing this, yes, `use` declarations will work fine.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.