-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make TestHook interfaces as easy to use as TestListener #3390
Comments
A few thoughts:
|
I just tried a quick proof of concept to make the TeamCity logger an extension and as it stands this is not possible. First of all, the printResult method (which would become the executeAfterLastTest method) needs a TestResult, but doesn't get one. Adding this to the interface would be a BC break. Then the addError (which would become the executeAfterFailedTest I believe) needs access to the actual Throwable to get a stack trace, but only receives a message string. I stopped trying after that, but I'm sure there would be more issues in the same vain. |
@rpkamp Thanks for your detailed feedback! I kept notes of what I ran into when refactoring the TestDox printer for #3380 and my list of required changes for the I will write up a more detailed response and proposal. The bottomline is the same as Remon says: the current printers/listeners get a lot more detail about the test run. The equivalent of interface BeforeTestHook extends TestHook
{
public function executeBeforeTest(string $test): void;
}
interface AfterSuccessfulTestHook extends TestHook
{
public function executeAfterSuccessfulTest(string $test, float $time): void;
} Reimplementing the current builtin output loggers requires (much) more information to be available. |
Just a quick heads-up: as an example, I have taken a look at Now I noticed that previously by implementing the When switching over to the hooks that appears not to be possible anymore (at least not in an easy way), as now the name of the test is passed in rather than the What do you think? Can the name of the test be a reliable source for determining test class and method? |
There are many reasons why I want to replace the
The small Also, following the priciniple of minimal visibility, |
@sebastianbergmann if using a hook rather than a Listener, how can you get access to the Test class from the string? |
You do not. And you should not need to. |
I've discovered this thread by Googling after PHPStorm informed me that |
The |
I'm trying to understand them - mainly because I need to hook into the 'beforeFirstTest' event, as opposed to the 'startTestSuite' event (regardless of how many suites are run, I need to perform one action at the beginning, and one at the end), and the older listeners don't seem to have that functionality. From what I can find, they need to be added as a .phar extension, as opposed to loaded in via the phpunit.xml |
No you can install them as extensions in phpunit.xml:
Just make sure your class implements |
Nice, thanks! Sorry for the somewhat off-topic divergence. |
I have a listener which does some stuff if the test suite contains a particular
How can this be converted to a TestHook based extension? |
Adding a use-case... I’m adding a custom annotation, which I use a TestListener before/after tests to read via |
This is a big BC-break for I found a way to get annotations, but I can't say it feels right: use PHPUnit\Util\Test;
Test::parseTestMethodAnnotations(...explode('::', $test)) @karser, you can probably use something similar with But beware: |
@greg0ire @nicolas-grekas Let us discuss |
@greg0ire @nicolas-grekas @sebastianbergmann I'd be happy to join in, I'll bring stroopwafels During the EU FOSSA hackathon we got a lot of work done on new event handling system for the loggers. I'd be happy to help out implementing the new event system to recreate the functionality you need for the bridge, and extend where needed. |
We need to lobby https://github.com/ManoManoTech so that @greg0ire can make it to SFCon :) |
It's now official, I'm going! So whatever lobbying you did behind the scenes, it worked 👍 |
Today I spent one hour trying to find an acceptable solution for a simple scenario. I have an "integration" suite that needs to initialize the lib I'm integrating with and a "unit" suite that only tests my lib. Initializing the integration is slow (DB involved), so I need to avoid doing it when not necessary. As others have said, one big problem with hooks is there's none of them that listen to suite start/end. But that's not all. Oftentimes, especially during development, I run tests selectively with With current hooks status, that's not possible, and I think that a way to overcome this issue would be to make There would be no way hooks could modify the configuration (array are passed by value) or do the nasty things that listeners could do receiving In fact, for my use case what I've resorted to doing is to use Note that to parse options is not that easy because one needs to take into account both If the hook object would be aware of the configuration object I could have written 3 lines of code instead of 25. Maybe a |
I've opened a separate issue, but it's probably related to this one: #4131 Basically, I would like an alternative to |
@sebastianbergmann If they aren't easy enough to use, then should they not be marked |
Over the course of the last year, we learned that while the approach implemented with the I understand that it must be frustrating that we deprecated the old |
Is there any place one can take a look at the new event system or is it not drafted/published yet? Tried to search PRs but couldn't find anything. |
I think it's this one: theseer#1 |
as TestListener is marked as deprecated, i am trying to migrate to a TestHook setup at FOSHttpCache. we used to have a listener that did only something in startTestSuite. the new segregated interfaces are nice, we don't have to implement 10 empty methods anymore 👍 . but we use a group on the tests to know if we need to start a server or not
how can i convert this to the new hook system? |
@dbu Per @sebastianbergmann comment above, it looks like the hook system will be removed. The deprecation warnings can be ignored. |
Correct, PHPUnit 10 will no longer support the |
oh, ok. would it make sense to remove the deprecation on the listeners then? and deprecate the hooks again? |
Actually, as PHPUnit 10 will come with a new Event based subsystem, both of the old mechanisms are gone. |
is the event subsystem available in phpunit 9 already? if not, deprecating is not helping much as users don't have an alternative. if it is, could we upgrade the listener deprecation in phpunit 8 and 9 to point to that new event system? i started adapting the hook system because thats what is referenced in the deprecation. to avoid misunderstandings: thanks for providing this high-quality tool! i don't want to just complain, but would be happy to do a PR to change the deprecations to point to the correct upgrade path, if that helps. |
The Event Subsystem is one of the major new things of PHPUnit 10 and thus not available in PHPUnit 9 or older. I unfortunately do not see any feasible way to "backport" that to PHPUnit 9 or even older, so it will be PHPUnit 10 and up only. Luckily, deprecating something doesn't mean it will stop working. Granted, if you want to have something that works for PHPUnit 10 and later it will be different from PHPUnit 9 and before. But assuming your code already works for PHPUnit 8 and 9, I don't see how that would be a problem now if you want to build a new Version for PHPUnit 10 and up? That being said: "Fixing" deprecation warnings to point to the correct replacement though seems like generally a good idea :) |
i would be happy to do a pull request to change the deprecations to point to the new system. is there any place i can link to? on readthedocs, there seems no doc version for the upcoming version... |
I don't think we have a documentation as of yet, given the stuff is under construction and there is no "official" API to register your own things yet. The best place to refer to probably is #4676. |
The event system was a catalyst for a lot of changes: Finding the right places to emit the appropriate events has revealed countless previously hidden inconsistencies and problems. For the The event system requires all of these changes to work, but backporting these changes to PHPUnit 9, for instance, is just not feasible. |
See In our project's Now sometimes an error is thrown, or the assertion fails, and we would like to know for which route exactly, for that, said for-loop stores the context in public function addError(Test $test, \Throwable $t, float $time): void
{
$this->onThrow($test, $t);
}
public function addFailure(Test $test, AssertionFailedError $error, float $time): void
{
$this->onThrow($test, $error);
}
private function onThrow(Test $test, \Throwable $error)
{
if ($test instanceof MyTest) {
if ($test->lastRoute !== null) {
self::prefixMessage($error, 'While testing route = ' . $test->lastRoute . ":\n");
}
}
}
private static function prefixMessage($obj, $prefix)
{
try {
$reflection = new \ReflectionClass($obj);
$property = $reflection->getProperty('message');
$property->setAccessible(true);
$property->setValue($obj, $prefix . $property->getValue($obj));
} catch (\ReflectionException $e) {
}
} @sebastianbergmann How can we achive above with the new interface AfterTestErrorHook extends TestHook
{
public function executeAfterTestError(string $test, string $message, float $time): void;
}
interface AfterTestFailureHook extends TestHook
{
public function executeAfterTestFailure(string $test, string $message, float $time): void;
}
SolutionsAs you deprecated our side of handling this, # 1 You could like some other frameworks, provide
# 2 Or, you could change your existing API's |
Maybe I'm being terse, but why not use a dataprovider? It'll get you loop and output which of the loops went wrong. |
First of all, that would make the message look something like:
Instead of:
And someone later running the tests would get confused (as we don't write tests for ourselves). Secondly, storing each and every route in
Last and least, rewritting logic to create |
The first concern is addressable using array keys. Array keys in data providers are used an names of the entries, so: return [
'route /admin/users/edit' => [...],
]; would generate an error like:
|
This issue is where the discussion that was started in #3381 should continue.
Related to #3388 and #3389.
The text was updated successfully, but these errors were encountered: