Problem/Motivation
In order to support the beta-to-beta update path in Drupal 8 core, we need to ensure we can write automated tests to verify each update hook. See Writing upgrade path tests documentation on the process for D7, and the list of D7 upgrade tests.
Upgrade tests are "normal" tests in every way except they don't start off with a fresh Drupal installation. They need a database dump of an older Drupal version to be imported first. Because in Drupal 8 much of the database schema is generated dynamically, the Drupal 7 updates need to be revised for this.
We need to be able to programmatically create scripts that can provide both "bare" and "full" database dumps (basically a collection of db_create_table() and db_insert() statements) for each of the installation profiles (drupal-8.bare.minimal.database.php.gz, drupal-8.filled.standard_all.database.php.gz, etc.). See filled example for D6.
We also need to the ability to create smaller, targeted "diff" DB dumps that provide data for a particular test, such as drupal-7.aggregator.database.php, which prefills some aggregator data.
In Drupal 7 these were generated from a script like dump-database-d7.sh.
Finally, we need a base class (in D7 this was UpgradePathTestCase) to facilitate loading one of the base DBs and setting various environment variables necessary for executing the upgrade path programmatically. This will be used by individual upgrade path tests, such as update.aggregator.test.
Based on the 8-to-8 update paths we already know about in http://cgit.drupalcode.org/head2head/tree/head2head.module, we should be able to write a few sample update tests to ensure the script/base class is functioning properly.
Proposed resolution
- Create a script / commands to dump the database
- Create some commands to load the old state
- Create test hook_update_N to proof it works
Remaining tasks
1. #2497323: Create a php script that can dump a database for testing update hooks
2. Write a test to use the output of that script (#2498625: Write tests that ensure hook_update_N is properly run)
3. Proof that hook_update_N is now testable.
User interface changes
- None
API changes
- None
Original Post
We have upgrade path tests, and self-tests of the upgrade path, but I'm not convinced that everything works. i.e. when we last had hook_update_N() in Drupal 8, we were testing the upgrade path from Drupal 7 to Drupal 8, not from Drupal 8 to Drupal 8.
We need to be able to dump an 8.x site into the upgrade path test format (i.e. PHP) which the upgrade path tests can then import. For 7-8 upgrade path testing we used
dump-database-d7.sh generate-d7-content.sh
Not sure anything like that exists for 8.x at all.
Reviewing the test coverage and probably a dry-run on the test infra would be worth doing as well.
| Comment | File | Size | Author |
|---|
Comments
Comment #1
larowlanHere's the dump script, works.
Still needs a generate script.
Comment #2
alexpottDoes drupal_get_schema still return everything? It does not look like it does. We need to get entity schema too.
Comment #3
catchIt doesn't, also see #2124069-90: Convert schema.inc to the update.update_hook_registry service (UpdateHookRegistry) - we don't actually use drupal_get_schema() anywhere important at the moment and I was suggesting possibly removing it as dead code (or at least marking it @deprecated with no replacement).
Comment #4
catchSo not sure the old way is feasible without a lot of work. We need to fill in all the schema gaps that are missing now, in addition we'd need to add the ability to dump and generate YAML config since a lot of updates that would have been database in 7.x are now to YAML files.
One possible idea:
Only test one update hook at a time for now. So a kernel test where we create the table(s) with the old schema definition, add some data, manually call the hook_update_N() and verify the result.
Similar process for YAML updates - write/copy the old file from somewhere, run the update hook, verify the result.
This won't catch update dependency issues, so it's not ideal, but possibly better than nothing to allow hook_update_N() to go in at all.
Yet another option is to collectively decide that beta to beta updates weren't such a great idea for core after all, put that responsibility onto head2head module (which has less implications for broken updates than doing it in core, and can have less strict testing criteria), and then from RC say we won't change YAML structure at all, or database structure except for index changes - at least until 8.1.0.
Comment #5
benjy commentedMigrate does something similar direct from the database, not sure if that is any help here: core/scripts/migrate-dump-d6.sh
Comment #6
alexpott@catch I'm not sure that we have to deal with YAML config files. Config is now in the DB so we just have to export the config table - no?
Comment #7
catchYes I realised that after typing the comment but failed to post here.
We can export the table I think. There'd be some benefit to being able to use the config storage itself to do the export/import so that contrib storage backends could also do update testing, but not that important.
Comment #8
xjm@alexpott, @webchick, @effulgentsia, and I discussed this issue awhile back and agreed that it is critical. We need to be able to test a full site upgrade and add regression tests for
hook_update_N()in order to support an upgrade path.Comment #9
jhedstromIf we went this route, the task would be to insure that each issue that added a
hook_update_Nincluded a test, so then this issue would be about making the base test class to facilitate those?Comment #10
webchickTagging. I feel like if we got a good list of todos here someone could bang it out.
Comment #11
amateescu commentedI started looking into this and it seems that the new dump script added for migrate in #2469623: Process for creating migration source DBs for automated tests can be used as a base for a more generic database dump script for upgrade path testing.
However, it uses CLI arguments and options, and it will quickly grow into a big and hard to maintain script (much like run-tests.sh), so I was thinking that we could use symfony's Console component for it.
One advantage is that php code (the Commands) will be in .php files, so the .sh files will contain just a few lines needed to invoke those commands. The DrupalCI project is also using this component.
A good task for 8.1 can be to convert run-tests.sh to it.
Disadvantages: I don't see any :)
Adding the new shiny tag to get the attention of framework managers.
Comment #12
cpj commentedI've used the Console as an extension / configuration mechanism in a couple of Symfony applications, and agree that it could be useful here. Another alternative could be the Symfony Fixtures bundle, but it might be too closely tied to Doctrine and perhaps not flexible enough to be used here.
Comment #13
amateescu commentedDiscussed a bit in IRC with @alexpott and he pointed me to some previous discussion about it: #2242947: Integrate Symfony Console component to natively support command line operations
So just to be perfectly clear, I'm not proposing anything like that since it's definitely 8.1 material. I just want to write the code for the dump script in a Command so we can take advantage of the clean API for input options and arguments, nicely formatted output, and, why not, testability of that command. Then have core/scripts/database-dump.sh as three lines of code that executes the command, that's it :)
Comment #14
fabianx commented+1 to using the console framework here:
https://github.com/msonnabaum/XHProfCLI/blob/master/src/XHProfCLI/Aggreg...
is a very good example of how clean such a component looks.
The advantage is that then the classes, etc. are unit testable, configurable, etc.
TODO:
1. Create a script to dump the necessary database tables
2. Write a test to use the output of that script
3. Proof that hook_update_N is now testable.
--
Technical direction has been provided, so removing tag. Still needs approval by framework managers to allow using clean commands via Symfony console for dumping the database. (Technically the dumper could even be its own project as only the tests are needed.)
Comment #15
benjy commentedWith this approach though, you'd need to install symfony/console to run the command though right? Because the command execute method has type hinting for the Input/Output interfaces etc? Maybe i'm missing something...
Comment #16
amateescu commented@benjy, not sure what you mean by "install symfony/console". If it's about adding it to core's composer.json then yes, that would be the start :)
I also posted a link in #11 that shows how the two scripts, the command and .sh runner, would look like. Maybe it was too hidden in the text so here's the full url: http://symfony.com/doc/current/components/console/introduction.html#crea...
Comment #17
benjy commentedThat's exactly what I meant, I thought you were saying somehow we could write it as a Command without symfony/console which is why I was utterly confused. Great, big +1 for adding symfony/console to core!
Comment #18
dawehnerWe should clearly communicate that adding symfony/console does NOT add a console to Drupal but rather just add a console for a specific command as dependency.
Comment #19
amateescu commented@dawehner, that's what I tried to communicate in this issue, see #13 :)
Comment #20
jhedstromThere's a lot of discussion about the script to generate a db for testing, but what still isn't clear to me are the other 2 tasks:
Would the script be used for testing every new update hook added to core in the future, or is it intended to just be used by a single test that ensures update hooks work? If the later is the case, we may be able to test update hooks in a functional test without a starting database by using the State API in a test module to alter the schema throughout the course of the test.
Comment #21
webchickIMO we'd want parity with Drupal 7's update testing, so I believe that means a separate test for each update hook, as well as a test to make sure the update process itself works.
Comment #22
jhedstromre #21 that makes sense--I actually didn't realize we had this for all update hooks in 7.
I opened #2493807: Add symfony/console component to core as a first step.
Comment #23
webchickThat one got committed, so using Console for this is now unblocked.
Comment #24
jhedstromSince there's already a start and much discussion of the db-generation script here, it probably makes sense to continue using this issue for that. I'm working on that now.
Comment #25
jhedstromI've realized the script will need a child issue (as we can't close this until all tasks are done). I've added #2497323: Create a php script that can dump a database for testing update hooks, with a suggested commit message for larowlan since he worked on the script in #1.
Comment #26
jhedstromComment #27
alexpott#2493807: Add symfony/console component to core has landed.
Comment #28
jhedstromUpdating the issue summary. I added #2498625: Write tests that ensure hook_update_N is properly run after talking with Webchick in IRC since we can start on the really simple tests without the script.
Comment #29
webchickExplicitly noting that this one is postponed on those other two.
Comment #30
webchickMassive issue summary update to try and explain what we're doing here. Might need double-checking for accuracy.
Comment #31
jhedstrom#2497323: Create a php script that can dump a database for testing update hooks has landed, changing title.
Comment #32
webchickTentatively testing our new "Plan" issue type now that #2504039: Adjust critical issue counter/link at /drupal-8.0/get-involved to account for "Plan" issue category is in.
Comment #33
catchComment #34
jhedstromAll the child issues are now resolved.
Comment #35
dawehnerCongrats!
I guess we should try it out on an actual issue
Comment #36
catchThis should test it?
Comment #38
catchSo a real update with its own test and an assertion would be better, but back to RTBC given implicit testing definitely works.
Comment #39
xjmExcellent!
Hiding the file so that testbot doesn't keep marking this issue NW.
Comment #40
effulgentsia commentedWhat's left to do before this can be marked fixed?
Comment #41
dawehner@effulgentsia
Comment #38 describes it pretty good. There should be a real usecase for hook_update_N. Once we have proven that, we should be save here.
Comment #42
catchI think we could probably track the real example in #2465053: Drupal 8 only allows one user every 6 hours to register when page caching is enabled — caused by entity UUID in form state - that meta gets closed when we actually support an upgrade path so anything unexpected can be handled as a new sub-issue of that I think?
Comment #43
catchSo yes marking this fixed, since #2341575: [meta] Provide a beta to beta/rc upgrade path is fine as a meta to track our overall ability to support/test the upgrade path.