Closed soullivaneuh closed 3 years ago
I think there can be two sorts of abstract tests :
I think both should be separated, because the first should not be autoloadable
Also, I think tests of type 2 should be integration tests (meaning some things are not mocked), because I can't imagine an abstract unit test that would be useful for users, and because I also think we should try to avoid inheritance as much as we can (main reason I prefer data mapper to active record).
because I can't imagine an abstract unit test that would be useful for users
Why?
It could be useful to simplify testing. For example, instead of let the user do all the mock logic, we can make an abstract method like getExpectedResult
that the user extending the test case will simply have to implement to have tests running.
I think both should be separated, because the first should not be autoloadable
What do you mean?
What do you mean?
If some tests are not meant to be run by the user, or used, they should not be autoloadable (they should be only in dev, thanks to autoload-dev
)
It could be useful to simplify testing. For example, instead of let the user do all the mock logic, we can make an abstract method like getExpectedResult that the user extending the test case will simply have to implement to have tests running.
Do you have a concrete example ?
If some tests are not meant to be run by the user, or used, they should not be autoloadable (they should be only in dev, thanks to autoload-dev)
This is not currently the case: https://github.com/sonata-project/SonataAdminBundle/blob/daa65de93c11737481ab99475bb5b551234082ce/composer.json#L63-L65
This is weird because Symfony does this: https://github.com/symfony/symfony/blob/2.8/composer.json#L107-L109
And I'm pretty sur I'm using one of their test class for my project...
Do you have a concrete example ?
Use getValidValues
data provider. So I defined an abstract method of this here: https://github.com/Soullivaneuh/IsoCodesValidator/blob/6ef053d7131ce701aba2f1e1f5fdb84aa5bec2c2/tests/Constraints/AbstractConstraintValidatorTest.php#L81
With that, you only have to supply the valid values on test classes, like this: https://github.com/Soullivaneuh/IsoCodesValidator/blob/6ef053d7131ce701aba2f1e1f5fdb84aa5bec2c2/tests/Constraints/BbanValidatorTest.php#L13-L19
At the end, nearly no test logic have to be written on child classes, except for special cases.
And this does not stop only at data providers: https://github.com/Soullivaneuh/IsoCodesValidator/blob/6ef053d7131ce701aba2f1e1f5fdb84aa5bec2c2/tests/Constraints/AbstractConstraintValidatorTest.php#L60
This is not currently the case: https://github.com/sonata-project/SonataAdminBundle/blob/daa65de93c11737481ab99475bb5b551234082ce/composer.json#L63-L65
This is a bundle. What about libraries? And what about the future, what if someday Symfony recommends to blacklist tests from the autoload in bundles ?
I must go, but I'll have a look at your examples.
Thanks for the example, it is valid indeed!
So to sum up my point of view :
In a library, tests useful for end-users would go insrc
, so that they can be autoloadable, abstract tests not useful for end-users would go in test
?
In a bundle… well I think it would be Tests
vs Test
, like symfony does : https://github.com/symfony/symfony/tree/master/src/Symfony/Bundle/FrameworkBundle
In a library, tests useful for end-users would go in
src
, so that they can be autoloadable
So you mean src/Test/AbstractDummyTestCase.php
for example?
In a bundle… well I think it would be
Tests
vsTest
, like symfony does
Sound good to me. :+1:
So you mean
src/Test/AbstractDummyTestCase.php
for example?
Yes
@sonata-project/contributors is everyone ok with that?
Yes for me. :+1:
It would be great to add a note about this on the contributing guide.
23 days have passed... Only 3 reactions :(
@core23 Testing is not the priority of lot of people... :wink: :trollface:
Let's write this on the contributing guide soon.
3 positive reactions though. I think we can merge https://github.com/sonata-project/SonataCoreBundle/pull/275 , ok?
It would be great to have proper guideline about this before merging anything IMHO.
FYI, usually a TestCase is an abstract, so placing Abstract before it seems a bit redundant.
FYI, usually a TestCase is an abstract, so placing Abstract before it seems a bit redundant.
Plus, Symfony does it this way ™.
Symfony did it historically.
But each abstract class name must be prefixed by Abstract according to Symfony conventions.
But each abstract class name must be prefixed by Abstract according to Symfony conventions.
You mean they are not following their own conventions?
You mean they are not following their own conventions?
Historically.
Prefix abstract classes with
Abstract
. Please note some early Symfony classes do not follow this convention and have not been renamed for backward compatibility reasons. However all new abstract classes must follow this naming convention;
http://symfony.com/doc/current/contributing/code/standards.html#naming-conventions
If the need comes and someone wants to implement it , it will be welcomed
Lot of Sonata classes are abstract classes and the goal is to be extended on your projects.
I'm thinking about
AbstractAdmin
orBlockService
.The test case
The goal of a test case is to provide facilities to the user to test project classes extending Sonata classes.
A test case can:
setUp
andsetUpBeforeClass
assert
methodstest*
method that will be launched on each children test class.The name
I suggest to name those kind of class
Abstract<TargetClass>TestCase
.Abstract
prefix because, well, it's an abstract class. :-)TestCase
to differentiate internal abstract test class that should not be used by ending user and abstract class dedicated for thisBC compliance
By definition, test classes should not be affected by the BC rule.
*TestCase
classes must do, because they will be used.Tag all other test classes with the
@internal
label can do the trick, but will be painful to apply.So I'm thinking about the
@api
tag.This is exactly the goal here.
With that, we can quickly see which test class can be broke and which should not.
A documentation about that should be added somewhere for ending users.
Sources
Class example from Symfony: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php
A class from one of my projects: https://github.com/Soullivaneuh/IsoCodesValidator/blob/3.x/tests/Constraints/AbstractConstraintValidatorTest.php
This is not a test case class, but you can see the principle of "default test" like
testNullIsValid
. This avoid test code duplication.What is your opinion about this?