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?
Comment | File | Size | Author |
---|---|---|---|
#55 | interdiff.txt | 724 bytes | Mile23 |
#55 | 2234479_55.patch | 11.06 KB | Mile23 |
#53 | interdiff.txt | 2.37 KB | Mile23 |
#53 | 2234479_53.patch | 11.02 KB | Mile23 |
#51 | interdiff.txt | 1.02 KB | Mile23 |
Comments
Comment #1
alberto56 CreditAttribution: alberto56 commentedThese 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.
Comment #2
alberto56 CreditAttribution: alberto56 commentedRelated Drush issue: https://github.com/drush-ops/drush/issues/565
Comment #3
sunI'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?
Comment #4
alberto56 CreditAttribution: alberto56 commented@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
orphp 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.Comment #5
fgmPossible 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
tohook_test_finished
, not just$test->results
.More realistically, a way to wrap test executions (event dispatching ?) could allow such behaviors.
Comment #9
Mile23These 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.
Comment #10
dawehnerYeah totally. They are broken as you reported, and really, a testing system should not require a working instance of the system itself.
Comment #11
Mile23Similar 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 insimpletest.api.php
.The suggestion is:
This may not be correct for all use-cases, so better suggestions appreciated.
Comment #13
dawehnerI wonder whether we can throw
e_trigger_error
somehow in case those hooks are implemented.Comment #14
Mile23The CI error looks like a broken testbot. Re-testing.
We could throw an error where the hook is invoked,
in the follow-up.Comment #16
Mile23Oops, I misspoke. The follow-up is for D9 which is too late. :-)
Comment #17
Mile23This 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.' :-)
Comment #18
dawehnerNice! I'm wondering whether this could be also a static method on the
ModuleHandler
?Comment #19
Mile23This really needs to be another issue. And here it is: #2866779: Add a way to trigger_error() for deprecated hooks
Comment #20
joachim CreditAttribution: joachim commentedLooks good, just some nitpicks:
Surplus blank line here.
Maybe put a @todo on this, saying to should get replaced as part of work on https://www.drupal.org/node/2866779 ?
Comment #21
Mile23Let's postpone on #2866779: Add a way to trigger_error() for deprecated hooks
Comment #22
Mile23This 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.
Comment #23
Mile23Planning here: #2870058: [policy, no patch] Document how to deprecate hooks
Comment #24
Mile23Postponed on #2866779: Add a way to trigger_error() for deprecated hooks
Comment #26
Mile23#2866779: Add a way to trigger_error() for deprecated hooks is in, so we're unpostponed here.
Comment #27
Mile23#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.Comment #28
Mile23Added a change record: https://www.drupal.org/node/2934242
Comment #30
dawehnerLet's use 8.6.x for now.
Can we point to the change record everywhere, please?
Comment #31
Mile23#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.Comment #32
Mile23Fixes #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 provehook_test_group_finished()
, but the others are more tricky.Comment #34
Mile23Mocks 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.
Comment #36
Mile23Wrong function signature.
Comment #37
Mile23Reroll.
Comment #38
joachim CreditAttribution: joachim commentedLGTM.
Comment #40
alexpottLet'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
To be inline with other remaining WTB - even though this is now very fake.
Comment #41
dawehnerThis 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..
This is an unnecessary change, also I don't understand what information this comment adds :)
Comment #42
alexpottCommitted dad18d8 and pushed to 8.7.x. Thanks!
Crediting @dawehner, @alberto56 and @joachim for review comments.
Removed comment on commit as per #41.
Comment #45
alexpottSadly this broke PHP 5.5 - https://www.drupal.org/pift-ci-job/1182207
Comment #46
dawehnerLooking 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.
Comment #49
Mile23I'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.
Comment #50
Mile23Comment #51
Mile23Fixed a test so it's not risky.
Still needs updated deprecation messages per our CS.
Comment #53
Mile23Updated @deprecation annotation. Further updated test to not be risky.
Comment #54
volegerThose 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
Comment #55
Mile23Thanks, @voleger.
Addresses #54.
Comment #56
LendudeIssues that caused this to be reverted and additional feedback have been addressed, so this looks ready.
Comment #57
alexpottSecond 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!
Comment #60
jcisio CreditAttribution: jcisio as a volunteer commentedRe #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.