Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
See title.
Comment | File | Size | Author |
---|---|---|---|
#46 | entity-dubt-fixes-1893108-46.patch | 8.18 KB | Berdir |
#40 | entity-dubt-fixes-1893108-40.patch | 13.07 KB | Berdir |
#40 | entity-dubt-fixes-1893108-40-interdiff.txt | 1.52 KB | Berdir |
#36 | entity-dubt-fixes-1893108-36.patch | 12.82 KB | Berdir |
#36 | entity-dubt-fixes-1893108-36-interdiff.txt | 2.39 KB | Berdir |
Comments
Comment #1
BerdirHere is a patch.
Notes:
- Some of these tests have a quite a list of dependences, I added a base test class for entity tests to simplify the dependency/setUp() code.
- Moved over EntityPropertiesTest from field.module to the Entity tests and renamed to EntityLabelTest, that's the only thing that it does.
- As you can see in the screenshots, the test time in the UI goes down from 2min to 48s. It's still that high because there are a few web/form tests remaining and two that I didn't manage to convert:
- The entity access tests are weird. They do a drupalLogin() but that doesn't log in the user within the tests, I guess they are relying on the fact that by default the gobal user object for tests has uid 1. I suggest a separate issue to figure out what to do with those.
- Entity info tests special cases during the module enable process and should probably remain a web test.
Comment #2
klausi@param docs always have to be fully namespaced.
I don't like setup tasks in the actual test method. On the other hand, you would have to create separate classes for each then, which is also tedious :(
Should be "Contains ...", see http://drupal.org/node/1354#files
missing "\"
Otherwise this looks like a good idea.
Comment #3
BerdirThanks for the review!
Fixed the documentation issues. Yes, the hook tests is ugly but I think refactoring that into separate classes is out of scope in this issue and doing those table installations in the test methods makes the whole test class ~twice as fast.
Comment #4
BerdirUh, patches.
Comment #6
dawehnerThis looks good from my perspective, beside of the ugly hook test case already mentioned before.
Comment #7
Berdirrole table is no more, this should pass again.
Comment #8
Berdiruser data is a service, so we could write a memory implementation of that too but that's something for another issue I think :)
Comment #9
sunComment #10
alexpottThis halves the time the Entity API group of tests takes to tun... great work!
With patch
without patch
EDIT: The entity translation test had one of it's random failures... replaced "with patch" test data.
Comment #11
sunThanks for converting these!
However, since there are new calls to
enableModules()
andconfig_install_default_config()
in this patch, let's wait for #1891516: Remove $install parameter from DrupalUnitTestBase::enableModules(), encourage individual schema tables, please.Comment #12
BerdirFine with me.
But while we wait on there, here's an update that moves the label test specific types to entity_test.module (nicely shows the problem with hardcoded label() methods of EntityTest and a bunch of config entities. They essentially remove support for the label key/callback in entity info).
Also fixed EntityAccessTest:
- The hardest part was to actually make that test fail when it's supposed to as I had to create a non-uid 1 user
- Added very simple support to create users with permissions left out all the checks and validations done by WebTest. Not sure if we want to move that to TestBase?
- Also fixed the bogus isset() check that resulted in always displaying "null" in the test assertions..
Comment #13
BerdirRemoved an unecessary $modules.
Comment #14
BerdirOk, here is a new patch that removes all instances of enableModule() and instead uses installSchema() only.
This should mean that, apart from a few small changes like loading default config, this shouldn't conflict with #1891516: Remove $install parameter from DrupalUnitTestBase::enableModules(), encourage individual schema tables anymore.
Comment #15
BerdirThis is why I asked for a $this->installSchema() in the other issue :)
Good news is that, thanks to these changes, we're down to 30s from initially ~2min on my system.
Comment #16
tim.plunkettWell, the other issue does allow you to specify an array of tables from a module, so the hunk shown in #15 could be one method call after that other issue goes in.
Comment #17
Berdir#14: entity-tests-dubt-1893108-14.patch queued for re-testing.
Comment #19
dawehnerRerolled.
Comment #20
aspilicious CreditAttribution: aspilicious commented:(
Comment #21
BerdirThis will need a re-roll anyway after #1891516: Remove $install parameter from DrupalUnitTestBase::enableModules(), encourage individual schema tables is in, that can be fixed then.
Comment #23
BerdirRe-rolled, changed a lot of installSchema() to use an array() and adjusted EntityUriTest to use the new base class.
Execution time is now 36 seconds instead of 2m 13s.
Comment #24
dawehnerSome small points which are not worth to be reviewed.
Comment #25
fagoDocumentation does not say it's just a base-test case, what it is - right? So should it be abstract also? Else improvements look just great!
Comment #26
dawehnerGood point.
Comment #27
BerdirI'm not sure if that role even exists in a DUBT test and if it does, then it probably has no permissions :)
Would have to check to be sure but those permissions would be saved in a table that does not exist :)
(It works in the EntityAccessTest because we install the table there manually but only there. So you might want to document that this is necessary. I'm not doing it by default because all other tests don't need it.)
Comment #29
BerdirUpdated the comment.
Comment #30
dawehnerSome tiny nitpicking.
Comment #31
fagoGreat, I agree this is RTBC!
Comment #32
webchickFaster tests++ :)
Committed and pushed to 8.x. Thanks!
Comment #33
sunThanks all! This is a great improvement :)
Sorry for my late review, but I've discovered some issues:
s/EntityUnitBaseTest/EntityUnitTestBase/
The *Test suffix normally denotes a final test class. The *Base suffix denotes an abstract/base class.
Really not happy about the "dual-purpose" here.
For unit tests, there should really be a cleanly separated
createUserRole()
method.1) $status defaults to 1 already, so I don't really see why we need to explicitly set it?
2) enforceIsNew() on a newly created entity object looks superfluous to me?
Comment #34
BerdirThanks for the review.
- Renamed the test class, you're totally right of course, not sure why I missed that. A bit unfortunate because other patches are already starting to pick up that class.
- Separated the user role creation into a separate method.
- removed status but kept enforceIsNew(). The reason I'm using it that because there is no default user in a DUBT test, the first created user would be uid 1 which would make it impossible to do permission related tests. Adding that call allows me to specify a fixed uid when creating a new user.
Comment #35
sunMuch better, thanks! :)
Eh? This @todo refers to this issue here? ;)
I did not really understand your reply. I understand the concern about uid 1, but fail to see how and why this method call would work around that situation in any way. I fear that some non-trivial magic is going on with this additional method call.
We should make sure to document that magic right above this call.
Comment #36
BerdirHah, fixed the @todo. That was a search/replace :)
Let me try to explain the enforceIsNew().
What will happen here is that the storage controller assumes this is an existing entity because the uid is set. So it will try to do an update query to update that entity, which won't do anything.
To prevent that, I'm calling enforceIsNew(). It doesn't hurt when there is no uid and it allows me to specificy a specific uid when needed.
Added an inline comment, is that clear enough?
Comment #37
sunAh-ha! :)
So you're actually not preventing uid 1 from getting created (by default). Instead, you require all callers to pass a random 'uid' in $values, which in turn gets unset and enforced to be new? I guess that could use some additional clarification in the phpDoc?
That said... I still do not understand why this trick would skip over uid 1 from being created (if there is none yet). enforceIsNew() only unsets the entity ID, no? In turn, the new ID would still be 1 if there is none yet...?
So... actually less ah-ha than I thought :P :D
Comment #38
BerdirNo, enforceIsNew() does not reset the uid, it does set a flag that says "I'm a new entity" *despite* having an id set.
Passing an uid is not required. If there is none, it is new anyway, the user storage controller will detect that and request a new id from db_next_id(). But if there is one, it will save it as a new entity with that id.
You're welcome to provide a better description. I don't think I can explain it better :)
Comment #39
sunThanks! Hm... Perhaps I slowly get it now... :)
So let me try:
...
Right, or still wrong? Thanks for enlightening me/us! :)
Comment #40
BerdirClose :)
*If* you specify a uid, you are responsible for using one that is not yet used. If you try to create two new users with uid 2, it will explode. I think this is a case of "We assume you know what you are doing" and picking a different uid would be weird as you explicitly chose that it should be X and said it is new, so it must not yet exist.
A default is only created if you didn't specify any.
Maybe it would help to do something like this:
To explicitly document it but technically, it makes absolutely no difference if enforceIsNew() is always called or not, so it's kinda useless.
What about this? We shouldn't go too far to document this IMHO, EntityInterface::enforceIsNew() already documents how it works.
Comment #41
sunThank you!
I think my understanding level hovers around ~90% by now (still some gaps, but I'm also super busy with $dayjob right now), so I think we can move forward with this. :)
Perhaps @webchick wants to commit this ;)
Comment #42
BerdirThanks for the useful review. If you have remaining questions, maybe it can be better discussed in IRC :)
Comment #43
webchickGoing from 1 line of code to 4 lines of code makes me :( but I guess I can see the logic in granular methods.
Whenever you need a book and a half to explain something, it's usually a sign that you should probably change the implementation. ;)
So I can understand totally why a user with the UID of 1 coming out of that function would totally screw any permission-based tests in an odd way. However, I would also posit that creating a non-UID1 user is the 99% case.
Therefore, how I would do this instead is something like:
So that you could still create a uid1 if you really wanted to for some reason, but you wouldn't need to worry about this detail at the "developer calling the function" level.
In other words, this:
...is way cleaner than this:
Wondering if we should split that part out into its own patch and just do the rename here, which is totally uncontroversial and also blocks a few other things.
Comment #44
sunThanks for the review, @webchick!
Note that the double-saving of $user is a bug... The roles can be specified in the values being passed to createUser() already. Well spotted.
Regarding uid 1: It's actually only access/permission-related tests that may want to skip over uid 1. The vast majority of tests should actually use uid 1 or uid X, because user permissions should be irrelevant.
Closely related anecdote: In D8, tests are finally able to log in with $this->root_user (uid 1), which allows plenty of web tests to skip over the creation of test users and just log in. Since the facility is new and isn't widely known yet, we still have plenty of tests that still create custom "admin" users, even though that's not strictly required anymore. Leveraging the root user not only speeds up tests but also simplifies them.
Due to that, I do not think that we generally want to skip over uid 1. Instead, I imagine that there can be many tests that just need a user record.
If we wanted to keep this super simple, I could foresee the following two paths:
A) Make the test setup automatically create a $this->root_user, similar to a web test, and case closed (though with negative test performance impact).
B) Make each test that needs to create non-uid 1 users simply create $this->root_user first. Provide a helper method for that, but otherwise, as usual, in a unit test, you're on your own, case closed.
Both options would be a lot more clear than the currently proposed "magic." ;) I personally don't have strong preference between both, but I think I'd lean more towards B), partially because I think that a unit test shouldn't do anything automatically.
Comment #45
BerdirNot sure about the root_user thing. I think an important aspect of writing tests is making sure that the access checks are correct, those are bugs that you often don't catch when testing with uid 1. So I would encourage to write tests with users that have an explicit permission set.
Comment #46
BerdirAs suggeted by @webchick, re-rolled with just the re-name, opened #1932780: Clean up EntityUnitTestBase::createUser() for the createUser part as this needs more discussion.
Comment #48
Berdir#46: entity-dubt-fixes-1893108-46.patch queued for re-testing.
Comment #49
ParisLiakos CreditAttribution: ParisLiakos commentedcouldnt find anything to complain about and since most webchick's concerns are in another issue, i am rtbc'ing this
Comment #50
webchickPerfect, thanks!
Committed and pushed to 8.x.