Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
simpletest.module
Priority:
Normal
Category:
Task
Assigned:
Issue tags:
Reporter:
Created:
23 Dec 2011 at 04:25 UTC
Updated:
29 Jul 2014 at 20:15 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #0.0
sunUpdated issue summary.
Comment #1
sunProposal 3) in code. I like.
Comment #1.0
sunUpdated issue summary.
Comment #2
sunWithout the debugging madness. ;)
That's my favorite, really. Eliminates the entire argument and manual processing.
Especially beneficial for cross-project tests in contrib.
Tests can be mixed and merged and sub-classed in any way, without having to care for proper processing of a $modules argument in any way.
Comment #3
sunComment #4
dave reidUsing a static property makes it hard to extend a base class and not have to manually specific the base class's modules. This is especially useful in contrib, not core.
Comment #5
sun@Dave Reid: The $modules of any parent class in between are explicitly taken into account. That's why I really like this.
Comment #5.0
sunUpdated issue summary.
Comment #6
sunAdditional benefit of the static $modules property:
Allows to check module dependencies of a test case without instantiating the class / invoking setUp().
Updated the issue summary accordingly.
Comment #7
sunComment #8
Crell commentedIf what we actually want here is a class name, from $class, then we should probably do $class = get_class($this); instead, to be more precise.
Static anything tends to make me queasy, but in this case we're already using a static getInfo() method as a declaration mechanism so it's no worse than that, and the advantages sun lists are valid. For completeness I would rather a static getModules() method to a public property, but the concept I'm OK with.
Failing that, option 2 from the OP would be my next choice. (You want an array, pass an array, fatal if not.)
-27 days to next Drupal core point release.
Comment #9
sun1) Fixed the get_class($this).
2) Not sure/convinced about $modules vs. getModules() yet. I'd prefer the simplicity of $modules, TBH, and don't see any serious problems with it being directly accessible (sounds rather like a hidden feature to me).
3) Re-rolled against HEAD. Sadly, FieldUITestCase is no longer a prime example for multiple class inheritance and proper accounting for additional $modules defined in classes in between, but I hope that the fact that previous patches passed are sufficient to clarify that this actually works. ;)
Comment #10
Crell commentedI don't get the hidden-feature comment. It's good OO principle to default to an accessor unless there's a solid reason not to; in this case, I don't see a compelling argument to make it a public property rather than a method.
A method would also allow us to skip the if(property_exists()) check, and just call getModules() in every case. The base class implementation returns an empty array, so nothing happens. Child classes can then override it to return something as needed. Also, that means the method can be defined and documented as a method, and included in an interface, whereas a member variable cannot.
Comment #11
tstoecklerIf I'm not mistaken, because we traverse the class tree like that, calling
$modules += parent::getModules()from your getModules() implementation would add the modules twice. Now, I imagine that wouldn't be *terrible*, but with a simple property, you really can't do anything wrong. Of course we could document not to call the parent implementation manually, but, again, what's the point?Comment #12
Crell commentedEh? How would it add elements twice?
This turns into...
The only reason that would return duplicates is if you call parent::getModules() in your getModules() method, which is by no means a requirement. We'd just document "well don't do that."
Or, now that you mention it, that would be even better. Replace that entire code block with:
(static being the late-static-binding version of self, introduced in PHP 5.3, that makes static methods work intelligently when doing inheritance.)
And the if you specify your own getModules() method, you DO call parent::getModules() yourself:
OO working as it should. :-) (I haven't tried running the above code, but give or take a syntax error it should all work, and work the way the language wants to work.)
Comment #13
tstoecklerYeah, that's kind of what I said...
Anyhow, I guess we have to decide if not having to call parent::getModules() is worth the traversal in DrupalWebTestCase or not. I personally would say yes, but either way is better than now, I guess.
Comment #14
sunAlright, bigger picture:
setUp()and very similar$modules = func_get_args()drama, which requires to copy the same code all over again, and making sure it is correct, is one of the key reasons for the proposal 3).setUp()method, and it's probably OK to leave the option for extreme edge-cases, but it should be discouraged.getModules()sounds wonky to me, because the definition actually sets modules. ButsetModules()would be wonky too, because the method doesn't actually set a property or similar. Thus, it would have to beinstallModules()or similar... (which is again not correct, 'cos the method does not actually perform the installation of modules...) And when comparing all that with a simple$modulesproperty, then I feel lost in a fruitless OO purity discussion. (KISS)$modulescould be renamed to$dependencies, but unfortunately, that would clash withgetInfo()'s'dependencies'key - which is used to determine whether all dependent modules required by a test (but not necessarily directly installed) exist, before trying to execute the test (and AFAIK, is also used by the d.o testing infrastructure to provide the proper projects on testbot checkouts when running tests). Also, the specified $modules are not necessarily all required dependencies, so renaming $modules to $dependencies could give the wrong impression.getInfo(), I'd like to get rid of it and replace most of it with phpDoc parsed via ReflectionMethod instead; see #697760: Replace getInfo() in tests with native phpDoc + annotations (following PHPUnit)$modules, there is also the$profileproperty, the installation profile to use for running tests.$profileis not static but protected property, so the last override in the hierarchy takes effect. Unlike$modules,$profilehas a default value of'testing'.$modulesin D8.$modules, too. There will be another test case specific property that allows the test to omit/skip the testing configuration for specified modules. There's no proposal for that property name over there yet, but let's simply consider$skipConfigurationsfor now.So in an ideal world, with all aspects combined, a test case that specifies/overrides everything would look along the lines of:
If you take away the inline comments, then we have a very simple test case definition that is easily understood, even by novice test authors.
Comment #15
Crell commentedsun, let's back up a moment. Isn't there ongoing discussion of switching out Simpletest in favor of PHPUnit anyway? Shouldn't we resolve that question first before we spend time on heavy architectural changes of our custom testing framework?
If we're investing that much time, I think it would be better spent in migrating to a more standard and capable system than continuing to evolve our own, knowing that there's a good chance we'll replace it.
Comment #16
catchCurrently Upal extends PHPUnit classes so that DrupalWebTestCase can be used as is - afaik the only thing that's incompatible with current tests at the moment is that PHPUnit doesn't return from assertions, and we have a few core tests that rely on that behaviour. So at least in the first instance, even with a switch to PHPUnit, all of this stuff likely wouldn't change that much.
Comment #17
sunRighto - as the name implies, PHPUnit is a framework for unit tests, which doesn't help with or resolve any of the challenges we're facing with our functional/integration tests, especially not on the scale of our modular aspects. I'm very open to look into standardization of our testing system, but that's a separate issue, and regardless of its outcome, we'll have to find a solution for this issue (and the others).
Comment #18
Crell commentedcatch: Yes, but isn't the intent to then start removing our extra intermediary layers where what's underneath is good enough? Ideally we would be able to just use vanilla PHPUnit directly in time. (At least that's my ideal.)
Comment #19
sunAlright, can we go ahead with the patch in #9?
Comment #20
tstoecklerI'm going to be bold and mark this RTBC.
If we decide to change this to a getModules() or whatever later on, this patch will actually make that easier (because it separates the modules from the rest of the code). More importantly, this allows to remove the hackish func_get_args() dance from the dozen or so helper test classes in core (see the op).
Since we're only at #20 comments, I think it's OK to handle the conversion to the static $modules property in this issue, but in a follow-up patch.
Comment #21
catchWell we might get there eventually, but that's got absolutely nothing to do with switching to PHPUnit.
For example to remove DrupalWebTestCase we'd need Drupal to be at the point where you never actually install it - rather you'd simply start with a blank slate (apart from config directory and database connection), then start enabling modules from there. That's a very long way off (optional system and user modules will not be easy), so it's very likely improvements to DrupalWebTestCase will last at least a full release cycle.
Comment #22
sun#9: drupal8.test-setup-modules.9.patch queued for re-testing.
Comment #24
sunRe-rolled against HEAD.
Comment #25
sunClarifying issue title.
Can we move forward here?
Please also note that I'm actively looking into ways for replacing Simpletest with PHPUnit and/or alternatives. This issue here, however, needs to happen independently from that, since swapping out the base testing framework does not imply that we won't have any web tests anymore. (And fwiw, I just recently talked to a Behat developer, who was quite impressed by our WebTestBase infrastructure [not it's code, but what it allows us to do].)
Comment #26
tim.plunkettToday was my 5th time explaining simpletest to those new to core at a sprint, and far and away the biggest WTF was how setUp() was used to enable modules.
I think this is great.
Comment #27
catchThanks. Committed/pushed to 8.x, this will need a change notification.
Comment #28
tim.plunkettIn addition to writing the change notice, do we want to repurpose this as a meta for tracking conversions, or should that be a new issue?
I opened #1710300: Convert node tests to use ::$modules property instead of parent::setUp($modules) just to see how easy/hard it was.
grep -nr "parent::setUp([^)]" * | wc -lshows 279 places this will need changing, node module was 19 tests worth. That's about a 250K patch if it's done all at once.Comment #29
sunOne or more separate issues make more sense. Given how large the patch in #1710300: Convert node tests to use ::$modules property instead of parent::setUp($modules) is, I guess that any larger patch would have to be constantly re-rolled due to other changes... So perhaps one issue per module would be better? Ideally, we'd bundle all of them in a nice issue tag.
Comment #30
tim.plunkettI've added a change record: http://drupal.org/node/1710766
Comment #31
sunThank you!
Comment #32
tim.plunkettI added #1711070: Convert tests to use ::$modules property instead of parent::setUp($modules) as the followup meta.
Comment #33.0
(not verified) commentedUpdated issue summary.