Skip to content

Remove Validator\TypeTestCase and add validator logic to base TypeTestCase #21960

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

Closed
wants to merge 8 commits into from

Conversation

pierredup
Copy link
Contributor

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no/possibly
Deprecations? no
Tests pass? yes
Fixed tickets N/A
License MIT
Doc PR symfony/symfony-docs#7587

Based on a discussion in the docs, users should not really extend classes in the Tests namespace. This means that if you want to unit test forms, you need to extend the Test\TypeTestCase class which doesn't have the validation logic (Not adding the validator extension gives an error if you use the constraints option in your forms).
So I propose to remove the Validator\TypeTestCase class (or it can possibly be deprecated if it is wrongly used by someone), and add the validator extension logic to the base TypTestCase class.

The benefit is that there is only one class to extend (both for internal or userland tests), and it makes it easy to add more core extensions if necessary.

The one part that I don't like too much at the moment, is keeping the extension in the getExtensions method. This means that you extend the class and need to register custom extensions, that you would need to do return array_merge(parent::getExtensions(), ... (only in the case when you want core extensions enabled). So I don't know if we rather want to add a private method like getCoreExtensions?

@nicolas-grekas
Copy link
Member

Tests are broken

@pierredup
Copy link
Contributor Author

The FormTypeValidatorExtensionTest class depends on the validator property, which is now removed. I just need to figure out a way around this, will push an update later to fix it

@@ -34,6 +35,22 @@ protected function setUp()
$this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
}

protected function getExtensions()
Copy link
Contributor

@HeahDude HeahDude Mar 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still against this, as said in #21780 we should not add the extension overhead on all base tests, so this should live in a specific type test case like ValidationTypeTestCase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with a separate class, is that you can't add more core extensions, as each one will need a separate class then, which makes extending the classes or using multiple core extensions difficult.

In terms of the overhead, I don't think that is really an issue. The overhead is so small per test that the impact would be negligible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your concerns, let me try again to explain why I suggest another way to solve this.

The issue with a separate class, is that you can't add more core extensions, as each one will need a separate class then, which makes extending the classes or using multiple core extensions difficult.

It should not be that difficult to call the parent, is it? Or maybe an ExtendedTypeTestCase with all core extensions preloaded could be an idea?

In terms of the overhead, I don't think that is really an issue. The overhead is so small per test that the impact would be negligible.

The overhead is not only about performances even if it impacts every field of every form, which indeed could be negligible in tests, but about the context, all core type tests extend this class, that means we cannot test them with the minimum of code necessary to run them anymore, and IMO we miss then the purpose of unit testing. Testing the core extension should not imply to load the validation one, it should not be tied to it, to avoid side effects, that's what we need in unit testing.

Let's imagine we follow your idea, and now want to add the CsrfExtension because in most applications this extension is enabled too, almost all core tests would fail because the token field is not submitted unless defining the related option to false.

I agree that the validation extension has the singularity to deeply test form errors, but still moving it to another base type test makes much more sense to me, that's why I'm suggesting to do it instead.

Anyway thank you for your contributions, I'm not "against" solving your issue, I'm just worrying about how we should do it.

Copy link
Contributor Author

@pierredup pierredup Mar 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this info, it makes much more sense now.

It should not be that difficult to call the parent, is it

The problem is not calling the parent. The problem is if you have a ValidatorExtension, DoctrineExtension, CsrfExtension etc, and your form uses options provided by all the extensions, but they all live in separate classes. So you will need to extend one class, while manually registering the other extensions for your forms not to break.

Or maybe an ExtendedTypeTestCase with all core extensions preloaded could be an idea?

That could also work.

I played a bit with a different approach, to use traits instead of classes.
The trait would expose a single method (E.G getValidatorExtension), then in the base TypeTestCase class we can check if the trait is added to the current class, and if it is we can register the extension just by calling the method.

The benefit in this is that you don't have to load all the extensions in the base test case, and if someone wants the validator extension in their test, they only have to add a use ValidatorExtensionTrait to their test class which then automatically registers the extension.
This can then be done for all core extensions, where you only need to add the traits you are interested in.

What are your thoughts on this approach? I have a working POC available that I can push to this PR if you want to have a look at the implementation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a good idea, of course you can push it so every one can review :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes pushed. It's just a POC, so I just want to get feedback on the idea. If everyone is happy with the approach then I'll finish the implementation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nicolas-grekas nicolas-grekas added this to the 3.x milestone Mar 14, 2017
@pierredup
Copy link
Contributor Author

pierredup commented Mar 15, 2017

Tests back to green

{
protected $validator;

protected function getValidatorExtension()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trait is now missing the tearDown (or maybe a tearDownAfterClass?) to set the validator property to null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tearDownAfterClass added to the TypeTestCase class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't use tearDownAfterClass since it's static, so I added tearDown instead

@nicolas-grekas
Copy link
Member

@pierredup looks like this one just needs fixing one small comment. Would you be up for fixing it+rebasing/retargeting to 3.4?

@pierredup pierredup changed the base branch from master to 3.4 September 26, 2017 19:17
@fabpot
Copy link
Member

fabpot commented Sep 27, 2017

Thank you @pierredup.

fabpot added a commit that referenced this pull request Sep 27, 2017
…to base TypeTestCase (pierredup)

This PR was squashed before being merged into the 3.4 branch (closes #21960).

Discussion
----------

Remove Validator\TypeTestCase and add validator logic to base TypeTestCase

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no/possibly
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | N/A
| License       | MIT
| Doc PR        | symfony/symfony-docs#7587

Based on a discussion in the docs, users should not really extend classes in the `Tests` namespace. This means that if you want to unit test forms, you need to extend the `Test\TypeTestCase` class which doesn't have the validation logic (Not adding the validator extension gives an error if you use the `constraints` option in your forms).
So I propose to remove the `Validator\TypeTestCase` class (or it can possibly be deprecated if it is wrongly used by someone), and add the validator extension logic to the base `TypTestCase` class.

The benefit is that there is only one class to extend (both for internal or userland tests), and it makes it easy to add more core extensions if necessary.

The one part that I don't like too much at the moment, is keeping the extension in the `getExtensions` method. This means that you extend the class and need to register custom extensions, that you would need to do `return array_merge(parent::getExtensions(), ... ` (only in the case when you want core extensions enabled). So I don't know if we rather want to add a private method like `getCoreExtensions`?

Commits
-------

5ab5010 Remove Validator\TypeTestCase and add validator logic to base TypeTestCase
@fabpot fabpot closed this Sep 27, 2017
@pierredup pierredup deleted the forms-testing branch September 27, 2017 16:28
This was referenced Oct 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants