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.

CommentFileSizeAuthor
#36 update_test.patch318 bytescatch
#1 hook-update-2447573.1.patch3.13 KBlarowlan

Comments

larowlan’s picture

Status: Active » Needs review
StatusFileSize
new3.13 KB

Here's the dump script, works.
Still needs a generate script.

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/scripts/dump-database-d8.php
@@ -0,0 +1,95 @@
+  $schema = drupal_get_schema();

Does drupal_get_schema still return everything? It does not look like it does. We need to get entity schema too.

catch’s picture

It 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).

catch’s picture

So 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.

benjy’s picture

Migrate does something similar direct from the database, not sure if that is any help here: core/scripts/migrate-dump-d6.sh

alexpott’s picture

@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?

catch’s picture

Yes 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.

xjm’s picture

@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.

jhedstrom’s picture

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.

If we went this route, the task would be to insure that each issue that added a hook_update_N included a test, so then this issue would be about making the base test class to facilitate those?

webchick’s picture

Tagging. I feel like if we got a good list of todos here someone could bang it out.

amateescu’s picture

I 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.

cpj’s picture

I'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.

amateescu’s picture

Discussed 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 :)

fabianx’s picture

Issue summary: View changes
Issue tags: -Needs technical direction

+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.)

benjy’s picture

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

With 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...

amateescu’s picture

@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...

benjy’s picture

@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 :)

That'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!

dawehner’s picture

We 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.

amateescu’s picture

@dawehner, that's what I tried to communicate in this issue, see #13 :)

jhedstrom’s picture

There'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:

2. Write a test to use the output of that script
3. Proof that hook_update_N is now testable.

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.

webchick’s picture

IMO 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.

jhedstrom’s picture

re #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.

webchick’s picture

That one got committed, so using Console for this is now unblocked.

jhedstrom’s picture

Assigned: Unassigned » jhedstrom

Since 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.

jhedstrom’s picture

Assigned: jhedstrom » Unassigned
Status: Needs work » Active

I'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.

jhedstrom’s picture

alexpott’s picture

jhedstrom’s picture

Issue summary: View changes

Updating 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.

webchick’s picture

Title: [meta] Make sure 8.x - 8.x hook_update_N() testing is possible » [meta PP-2] Make sure 8.x - 8.x hook_update_N() testing is possible
Status: Active » Postponed

Explicitly noting that this one is postponed on those other two.

webchick’s picture

Issue summary: View changes

Massive issue summary update to try and explain what we're doing here. Might need double-checking for accuracy.

jhedstrom’s picture

Title: [meta PP-2] Make sure 8.x - 8.x hook_update_N() testing is possible » [meta PP-1] Make sure 8.x - 8.x hook_update_N() testing is possible
webchick’s picture

Category: Task » Plan
catch’s picture

Issue summary: View changes
jhedstrom’s picture

Title: [meta PP-1] Make sure 8.x - 8.x hook_update_N() testing is possible » [meta] Make sure 8.x - 8.x hook_update_N() testing is possible
Status: Postponed » Reviewed & tested by the community

All the child issues are now resolved.

dawehner’s picture

Congrats!

3. Proof that hook_update_N is now testable.

I guess we should try it out on an actual issue

catch’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new318 bytes

This should test it?

Status: Needs review » Needs work

The last submitted patch, 36: update_test.patch, failed testing.

catch’s picture

Status: Needs work » Reviewed & tested by the community

So a real update with its own test and an assertion would be better, but back to RTBC given implicit testing definitely works.

xjm’s picture

Excellent!

Hiding the file so that testbot doesn't keep marking this issue NW.

effulgentsia’s picture

What's left to do before this can be marked fixed?

dawehner’s picture

@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.

catch’s picture

I 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?

catch’s picture

Status: Reviewed & tested by the community » Fixed

So 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.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.