Problem/Motivation

The hook_test_*() hooks are invoked inconsistently in the testing system.

They are only called from the Simpletest UI form builder, not from run-tests.sh.

Proposed resolution

Deprecate these hooks for removal before Drupal 9.

Throw trigger_error() deprecation notices during the invocation of these hooks.

Testing systems needing this information should convert to PHPUnit and implement test listeners.

Remaining tasks

Remove invocations of these hooks in a follow-up.

User interface changes

API changes

Deprecation of hook_test_group_started(), hook_test_group_finished(), hook_test_finished() and mention phpunit listeners, which do something similar explicit for testcases.

Data model changes

Original Issue Summary:

It is my understanding that tests are organized as such:

  • test classes are in a single .test file and include a setUp() function
  • test cases are functions within a test class which define a single test
  • test groups can include several test classes

If such is the case, hook_test_group_started() and hook_test_group_finished() are not well named, as they are before and after each test class.

Could we, then, rename these hooks hook_test_class_started() and hook_test_class_finished(), and introduce new hook_test_group_started() and hook_test_group_finished() functions which would be called before and after each test group?

CommentFileSizeAuthor
#55 interdiff.txt724 bytesMile23
#55 2234479_55.patch11.06 KBMile23
#53 interdiff.txt2.37 KBMile23
#53 2234479_53.patch11.02 KBMile23
#51 interdiff.txt1.02 KBMile23
#51 2234479_51.patch11.04 KBMile23
#46 interdiff-2234479.txt1.67 KBdawehner
#46 2234479-46.patch10.85 KBdawehner
#40 2234479-40.patch10.03 KBalexpott
#40 37-40-interdiff.txt2.65 KBalexpott
#37 2234479_37.patch10.53 KBMile23
#36 interdiff.txt663 bytesMile23
#36 2234479_36.patch10.58 KBMile23
#34 interdiff.txt7.35 KBMile23
#34 2234479_34.patch10.58 KBMile23
#32 interdiff.txt5.9 KBMile23
#32 2234479_32.patch5.92 KBMile23
#27 interdiff.txt4.08 KBMile23
#27 2234479_27.patch3.34 KBMile23
#22 2234479_22.patch2.17 KBMile23
#17 interdiff.txt2.51 KBMile23
#17 2234479_17.patch4.29 KBMile23
#11 2234479_11.patch1.78 KBMile23
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alberto56’s picture

These hooks are invoked differently in the GUI and in scripts/run-tests.sh, as described in #2234483: hook_test_group_started() and hook_test_group_finished() not used the same way in GUI and scripts/run-tests.sh.

alberto56’s picture

sun’s picture

I'd really like to get a better understanding for "real world" use-cases for those hooks, because I'm very very tempted to remove all of them altogether without replacement.

It sounds as if you have a use-case — could you enlighten me?

alberto56’s picture

Title: Rename hook_test_group_started() and hook_test_group_finished(), and introduce hooks called before and after groups. » Rethink the hooks which need to be invoked before/during/after testing

@sun thanks for following up. I think these hooks could be useful:

  • hook_test_run_start($tests): run just before you are starting a test run (a test run can contain several test groups, test cases and tests).
  • hook_test_run_finish($results): run just before the test environment is cleaned, at the end of a test run.
  • hook_test_clean_environment(): run just before the test environment is cleaned, in the case of an error.

All other hooks can probably be removed, you are right.

Here is how I would use the above hooks:

(1) On Simpletest Turbo, which caches the result of MyTest::setUp() when it is first run, and destroys the cache when the test run ends or when the environment is cleaned. You had suggested in #2234677: Provide hook when starting a test run and when ending it a better architecture for Simpletest Turbo, but the case remains that I need to do something when the test run starts, when the test run ends, and when the environment is cleaned.

(2) My continuous integration server is running tests, and I would like to intercept the test id at the very end of a test run in order to archive the test results including verbose messages (HTML source of pages visited) as artifacts related to the build. For the moment the concept of a test id is a bit nebulous: when several test classes are run in the GUI, as far as I can tell there is only one test ID. However if we use drush test-run or php scripts/run-tests.php, several IDs seem be generated. In this case I would like my code to be notified when the test run finishes but before the clean-up occurs, and also just before the test environment is cleaned up in case of an error, so in both cases I can move the results to another directory to be archived. See #2253999: Provide a way to keep test results and verbose messages as artifacts and #590: adding artifact ability to drush.

fgm’s picture

Possible use case : when testing with an alternate path or cache plugin (e.g. mongodb), the data created during the core path.test is not deleted by the test. Since this is a core test, the contrib plugin cannot change the base class for the core test to add a tearDown step where it could do its cleanup. And since this is not done in the DB or files, the simpletest runner does not know it has to clean this.

A hook in the support module for the plugin could perform such cleanup. Of course, for this to be of use, the hook would need to pass information about the test just ran, not only its statistics. A simple way could be to pass $test to hook_test_finished, not just $test->results.

More realistically, a way to wrap test executions (event dispatching ?) could allow such behaviors.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

These hooks are only invoked by the UI test runner. run-tests.sh does not invoke them.

I'd venture that we should deprecate these hooks.

dawehner’s picture

I'd venture that we should deprecate these hooks.

Yeah totally. They are broken as you reported, and really, a testing system should not require a working instance of the system itself.

Mile23’s picture

Title: Rethink the hooks which need to be invoked before/during/after testing » Deprecate hook_test_* hooks in simpletest
Version: 8.3.x-dev » 8.4.x-dev
Category: Feature request » Task
Issue summary: View changes
Status: Active » Needs review
Issue tags: +Needs change record, +Needs followup
Related issues: +#2460521: Deprecate hook_simpletest_alter()
FileSize
1.78 KB

Similar issue: #2460521: Deprecate hook_simpletest_alter()

Rescoping and changing to a task because we're calling these hooks inconsistently. Ordinarily I'd call that a bug, but this is an API that we want to change.

Targeting core 8.4.x because this is disruptive, though we might get it in for 8.3.x if it's deemed reasonable for a testing change.

This patch just marks all the hook_test_*() hooks as deprecated in simpletest.api.php.

The suggestion is:

 * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Convert
 *   your test to a PHPUnit-based one and implement test listeners.

This may not be correct for all use-cases, so better suggestions appreciated.

Status: Needs review » Needs work

The last submitted patch, 11: 2234479_11.patch, failed testing.

dawehner’s picture

+++ b/core/modules/simpletest/simpletest.api.php
@@ -29,6 +29,12 @@ function hook_simpletest_alter(&$groups) {
+ * This hook is only invoked by the Simpletest UI builder. It will not be
+ * invoked by run-tests.sh or the phpunit tool.
+ *
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Convert
+ *   your test to a PHPUnit-based one and implement test listeners.

@@ -37,6 +43,12 @@ function hook_test_group_started() {
+ * This hook is only invoked by the Simpletest UI builder. It will not be
+ * invoked by run-tests.sh or the phpunit tool.
+ *
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Convert
+ *   your test to a PHPUnit-based one and implement test listeners.
  */

@@ -46,11 +58,17 @@ function hook_test_group_finished() {
  *
+ * This hook is only invoked by the Simpletest UI builder. It will not be
+ * invoked by run-tests.sh or the phpunit tool.
+ *
...
+ *
+ * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Convert
+ *   your test to a PHPUnit-based one and implement test listeners.
  */

I wonder whether we can throw e_trigger_error somehow in case those hooks are implemented.

Mile23’s picture

Status: Needs work » Needs review

The CI error looks like a broken testbot. Re-testing.

We could throw an error where the hook is invoked, in the follow-up.

Status: Needs review » Needs work

The last submitted patch, 11: 2234479_11.patch, failed testing.

Mile23’s picture

Issue summary: View changes

Oops, I misspoke. The follow-up is for D9 which is too late. :-)

Mile23’s picture

Status: Needs work » Needs review
FileSize
4.29 KB
2.51 KB

This patch adds a function to system module which throws errors based on whether any modules implement the given hook.

This is known as 'scope creep.' :-)

dawehner’s picture

Nice! I'm wondering whether this could be also a static method on the ModuleHandler?

Mile23’s picture

Nice! I'm wondering whether this could be also a static method on the ModuleHandler?

This really needs to be another issue. And here it is: #2866779: Add a way to trigger_error() for deprecated hooks

joachim’s picture

Status: Needs review » Needs work

Looks good, just some nitpicks:

  1. +++ b/core/modules/system/system.module
    @@ -1489,3 +1489,31 @@ function system_query_entity_reference_alter(AlterableInterface $query) {
    +
    

    Surplus blank line here.

  2. +++ b/core/modules/system/system.module
    @@ -1489,3 +1489,31 @@ function system_query_entity_reference_alter(AlterableInterface $query) {
    + * Helper function to trigger errors for deprecated hooks.
    

    Maybe put a @todo on this, saying to should get replaced as part of work on https://www.drupal.org/node/2866779 ?

Mile23’s picture

Mile23’s picture

Status: Postponed » Needs review
FileSize
2.17 KB

This patch removes all the trigger_error() stuff, leaving only deprecation notices and @todos about signaling the hooks as deprecated during invocation after #2866779: Add a way to trigger_error() for deprecated hooks

Also #2866779: Add a way to trigger_error() for deprecated hooks is postponed until the testing infrastructure is sorted in #2488860: Bring phpunit bridge into drupal and use it for unit tests and simpletest to handle Deprecation, so unpostponing here.

Mile23’s picture

Mile23’s picture

Status: Needs review » Postponed

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

Status: Postponed » Needs work
Mile23’s picture

Status: Needs work » Needs review
Issue tags: -Needs followup
FileSize
3.34 KB
4.08 KB

#2866779: Add a way to trigger_error() for deprecated hooks was the follow-up so removing that tag.

This adds handy-dandy deprecation errors via that issue.

I ran into some failing tests locally, because of our old friend SimpleTestBrowserTest. Let's see how different the testbot environment is to mine.

Mile23’s picture

Issue tags: -Needs change record

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

Issue summary: View changes
Status: Needs review » Needs work
  1. +++ b/core/modules/simpletest/simpletest.api.php
    @@ -29,6 +29,12 @@ function hook_simpletest_alter(&$groups) {
    + * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Convert
    
    @@ -37,6 +43,12 @@ function hook_test_group_started() {
    + * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Convert
    
    @@ -46,11 +58,17 @@ function hook_test_group_finished() {
    + * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Convert
    

    Let's use 8.6.x for now.

  2. +++ b/core/modules/simpletest/simpletest.api.php
    @@ -46,11 +58,17 @@ function hook_test_group_finished() {
      *
    + * This hook is only invoked by the Simpletest UI form runner. It will not be
    + * invoked by run-tests.sh or the phpunit tool.
    + *
    
    +++ b/core/modules/simpletest/simpletest.module
    @@ -161,7 +161,7 @@ function simpletest_run_tests($test_list) {
    +  \Drupal::moduleHandler()->invokeAllDeprecated('Convert your test to a PHPUnit-based one and implement test listeners.', 'test_group_started');
    
    @@ -428,7 +428,7 @@ function _simpletest_batch_operation($test_list_init, $test_id, &$context) {
    +    \Drupal::moduleHandler()->invokeAllDeprecated('Convert your test to a PHPUnit-based one and implement test listeners.', 'test_finished', [$test->results]);
    
    @@ -490,7 +490,7 @@ function _simpletest_batch_finished($success, $results, $operations, $elapsed) {
    +  \Drupal::moduleHandler()->invokeAllDeprecated('Convert your test to a PHPUnit-based one and implement test listeners.', 'test_group_finished');
    

    Can we point to the change record everywhere, please?

Mile23’s picture

#2460521: Deprecate hook_simpletest_alter() adds a test which implements hook_simpletest_alter() in a test module. We could use that test module here for the test we need to add, so this is kind of soft-postponed on that.

Mile23’s picture

Status: Needs work » Needs review
FileSize
5.92 KB
5.9 KB

Fixes #30.

Still to do: Figure out how to run simpletest UI's batch runner without running any tests, so we can invoke the deprecated hooks and prove that they trigger errors. _simpletest_batch_finished() is pretty easy to fake out, and that allows us to prove hook_test_group_finished(), but the others are more tricky.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

Mocks and more mocks. Demonstrating why we should use \Drupal::database() (see: #2991337: Document the recommended ways to obtain the database connection object).

Now we have demonstrations that the deprecation errors are thrown.

Updated CR for 8.7.x.

Status: Needs review » Needs work

The last submitted patch, 34: 2234479_34.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Mile23’s picture

Status: Needs work » Needs review
FileSize
10.58 KB
663 bytes

Wrong function signature.

Mile23’s picture

Reroll.

joachim’s picture

Status: Needs review » Reviewed & tested by the community

LGTM.

The last submitted patch, 32: 2234479_32.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
2.65 KB
10.03 KB
+++ b/core/modules/simpletest/tests/modules/simpletest_deprecation_test/simpletest_deprecation_test.module
--- /dev/null
+++ b/core/modules/simpletest/tests/modules/simpletest_deprecation_test/src/Tests/InnocuousTest.php

+++ b/core/modules/simpletest/tests/modules/simpletest_deprecation_test/src/Tests/InnocuousTest.php
+++ b/core/modules/simpletest/tests/modules/simpletest_deprecation_test/src/Tests/InnocuousTest.php
@@ -0,0 +1,38 @@

@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\simpletest_deprecation_test\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * A very simple WebTestBase test that never touches the database.
+ *
+ * @group simpletest_deprecation_test
+ */
+class InnocuousTest extends WebTestBase {
+
+  /**
+   * Override to prevent any environmental side-effects.
+   */
+  protected function prepareEnvironment() {
+  }
+
+  /**
+   * Override run() since it uses TestBase.
+   */
+  public function run(array $methods = []) {
+  }
+
+  /**
+   * Override to prevent any assertions from being stored.
+   */
+  protected function storeAssertion(array $assertion) {
+  }
+
+  /**
+   * Override to prevent any assertions from being stored.
+   */
+  public static function insertAssert($test_id, $test_class, $status, $message = '', $group = 'Other', array $caller = array()) {
+  }
+
+}

Let's move this into the same file as TestDeprecatedTestHooks. There's no need to make the WebTestBase counter go up by one...
00:09:24.965 Drupal\simpletest_deprecation_test\Tests\InnocuousTest 0 passes from the console output.

Plus let's changes it's @group annotation to be

 * @group WebTestBase
 * @group legacy

To be inline with other remaining WTB - even though this is now very fake.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

This looks great overall. I like the fact that this issue triggered deprecating hooks in the first place.
Reading the test this all seems sensible, just a small comment..

+++ b/core/modules/simpletest/simpletest.module
@@ -138,6 +138,8 @@ function simpletest_run_tests($test_list) {
+  // Use the database service so that we can inject a database for testing this
+  // function.

This is an unnecessary change, also I don't understand what information this comment adds :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed dad18d8 and pushed to 8.7.x. Thanks!

Crediting @dawehner, @alberto56 and @joachim for review comments.

diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index cf35b7f98e..1d0e7b2cb7 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -138,8 +138,6 @@ function simpletest_run_tests($test_list) {
     unset($test_list['phpunit']);
   }
 
-  // Use the database service so that we can inject a database for testing this
-  // function.
   $test_id = \Drupal::database()->insert('simpletest_test_id')
     ->useDefaults(['test_id'])
     ->execute();

Removed comment on commit as per #41.

  • alexpott committed dad18d8 on 8.7.x
    Issue #2234479 by Mile23, alexpott, dawehner, alberto56, joachim:...

  • alexpott committed 242bffc on 8.7.x
    Revert "Issue #2234479 by Mile23, alexpott, dawehner, alberto56, joachim...
alexpott’s picture

Status: Fixed » Needs work
dawehner’s picture

Looking into the problem deeper I think the function signature is wrong. We never generate a SPLString, we just have it in core.services.yml as we didn't have a better way to generate a non object service.
In general Drupal core does not require the spltypes php extension so we should not use them in our code.
Nothing in Drupal core passes along a different site path which is its own problem.

Status: Needs review » Needs work

The last submitted patch, 46: 2234479-46.patch, failed testing. View results

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Mile23’s picture

I'd RTBC but I wrote the earlier patch. Starting tests up.

I doubt we're supporting PHP 5 at all in core 8.8.x, but this still solves that problem.

Mile23’s picture

Status: Needs work » Needs review
Mile23’s picture

Fixed a test so it's not risky.

Still needs updated deprecation messages per our CS.

Status: Needs review » Needs work

The last submitted patch, 51: 2234479_51.patch, failed testing. View results

Mile23’s picture

Status: Needs work » Needs review
FileSize
11.02 KB
2.37 KB

Updated @deprecation annotation. Further updated test to not be risky.

voleger’s picture

+++ b/core/modules/simpletest/simpletest.api.php
@@ -53,11 +69,19 @@ function hook_test_group_finished() {
  * @see \Drupal\simpletest\WebTestBase::results()
+ *
+ * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Convert your
+ *   test to a PHPUnit-based one and implement test listeners.
+ *
+ * @see https://www.drupal.org/node/2934242

Those additions have to be added above the @see \Drupal\simpletest\WebTestBase::results() line. That will makes @see annotations grouped.

Regarding other changes +1 for rtbc

Mile23’s picture

Thanks, @voleger.

Addresses #54.

Lendude’s picture

Status: Needs review » Reviewed & tested by the community

Issues that caused this to be reverted and additional feedback have been addressed, so this looks ready.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Second time lucky. The whole \SplString service thing is currently deprecated in Symfony 4.4 so it's likely this will change in Drupal 9 anyway and the removal of a typehint is not BC breaking (especially when the typehint is wrong).

Committed 0125272 and pushed to 8.8.x. Thanks!

  • alexpott committed 0125272 on 8.8.x
    Issue #2234479 by Mile23, dawehner, alexpott, alberto56, joachim,...

Status: Fixed » Closed (fixed)

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

jcisio’s picture

Re #57: Actually there is a warning with that fix:

Warning : Declaration of Drupal\filebrowser\FilebrowserStream\FilebrowserStream::basePath(?SplString $site_path = NULL) should be compatible with Drupal\Core\StreamWrapper\PublicStream::basePath($site_path = NULL) in require()

I don't know if it worth creating a new issue.