Problem/Motivation

MigrateDrupal6Test.

This class is intended to run all of the Migrate Drupal integration tests at once as a unified way to test a full-site migration. Unfortunately, it creates more problems than it solves.

The main problem is that, when running sub-tests, MigrateDrupal6Test does not execute setUp() methods. The effect that this has is that a given migration test can fail (exceptions and/or fatals) depending on whether it is run by itself or by MigrateDrupal6TestBase.

I think this creates several serious problems:

  • It makes migration tests needlessly brittle.
  • It is undocumented and hard to wrap your mind around, regardless of your experience level.
  • It is extraordinarily hard to debug. Debugging migration tests is tricky in the best of times, and this effectively means that any broken test must be debugged twice -- once as a standalone test, and again as a component of MigrateDrupal6Test.
  • It makes tests hard to read and review (unless you have intimate knowledge of the system), since they need to do certain acrobatics that make no sense in one context or the other.
  • It is aggressively bad DX and has been an impediment and source of frustration for crucial Migrate developers.
  • The poor DX disincentivizes less-experienced developers from contributing to Migrate or writing tests for migrations.
  • I'm not sure what a test proves when it can effectively be run (and pass) from two completely different initial states.

Proposed Resolution

Abolish MigrateDrupal6Test:

  1. Move all existing migration tests into the migrate_drupal_6.x group so they can be run in one fell swoop.
  2. Rather than having tests "mock" the results of the migrations they depend on, they should actually run those dependencies for real in their setUp() method ($this->executeMigration('dependency_id')). This means that if a dependency is broken, the dependent migration will break as well -- but this is still only a single debugging session, rather than two.
  3. Removing MigrateDrupal6Test, MigrateFullDrupalTestBase and prepareMigrations() (along with all calls to it) means we will shed hundreds of lines of code and make tests much, much easier to write, review, and understand.

One con is that it will be slower to run all the tests. But since the tests will always begin from a consistent, known state, they will also be more predictable.

Remaining Tasks

Write the patch, review it, and commit. Then we can go drinking.

API Changes

MigrateTestBase::prepareMigrations() will be removed, as well as the base MigrateFullDrupalTest class and MigrateDrupal6Test itself.

Comments

phenaproxima created an issue. See original summary.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes

Last one, I swear.

quietone’s picture

+1 !!

For me, phenaproxima's statement of the problem is excellent. I agree with the proposed resolution, I just don't know enough to comment on how it will be implemented. But, I will gladly accept tests that run slower if I am able to have consistent results and an easier to understand environment.

benjy’s picture

MigrateDrupal6Test has been a great test, catching many bugs that actually reflect real life and which aren't caught in setUp() because developers kindly setup everything just how they need it for their code to work where as MigrateDrupal6Test relies on running migrations to do your setup, no cheating!

Running the individual tests are much easier to debug than MigrateDrupal6Test and they catch 80% of the bugs. The proposed solution sounds like making every test as slow and as hard to run as MigrateDrupal6Test

Given we've just moved half of the Migrate API around to accommodate builders and are soon to remove load plugins removing this test would probably be a disaster and I don't believe the proposed solution makes things easier.

I don't see why it's so confusing, maybe we just need to do some renaming. The individual tests are simply being reused for their assertions, we could rename something to reflect that?

phenaproxima’s picture

MigrateDrupal6Test has been a great test, catching many bugs that actually reflect real life and which aren't caught in setUp() because developers kindly setup everything just how they need it for their code to work

I'm not opposed to MigrateDrupal6Test on principle, because yes, it is absolutely a more realistic test than the individual ones.

The problem is that it is a very different thing to assert based on what was expected to happen (standalone tests with setUp()) versus what actually happened (MigrateDrupal6Test). We cannot have it both ways, and our tests should not provide that impression or possibility. All the pain of our integration test suite stems from the fact that the ground can shift from under the feet of the assertions.

If we're going to keep MigrateDrupal6Test -- and I think we *should* maintain the approach of asserting the results of real-world migrations, which is what I described in #2 of the proposed resolution -- then the individual tests cannot be considered effective tests and should not be individually runnable or even appear as tests. They should be invisible to SimpleTest and invisible to DrupalCI/testbot.

What I'm proposing here is the best of both worlds, because the individual tests would be able to unambiguously assert on real-world results (by running their dependencies for real, à la MigrateDrupal6Test) while still being individually runnable. I see nothing disastrous about that.

Given we've just moved half of the Migrate API around to accommodate builders and are soon to remove load plugins removing this test would probably be a disaster and I don't believe the proposed solution makes things easier.

By no means whatsoever should this be done now. It's not a priority. Although I very much dislike the current solution, I have to concede that it's workable. We need a Drupal 7 migration path in core a lot more than we need this. This issue should never be escalated to major or Migrate-critical, and I won't be working on the patch until the D6 migration path has stabilized and at least the Big Four D7 migrations are in core.

benjy’s picture

Well i'm glad we're not actively working on this now because as you say, there are plenty more important things to stabilise.

All the pain of our integration test suite stems from the fact that the ground can shift from under the feet of the assertions.

I agree this certainly can be problematic when you're trying to test one specific type of failure, maybe that's something we could solve by breaking out the assertions trying to catch specific problems into new tests and keeping our current tests which started off trying to test/assert that the data was imported correctly into D8. Those assertions should be the same whether you used the actual migration path or used setUp() to get things started.

phenaproxima’s picture

Those assertions should be the same whether you used the actual migration path or used setUp() to get things started.

Just to be clear, it's not the assertions that are the problem. The problem is the state of the system in which the assertions are being made. We can't allow it to differ based on how the test was run. That's the crucial thing I aim to solve in this issue. Exactly how we fix it is not important as long as the tests are always asserting from a consistent state.

phenaproxima’s picture

I just hit on a potentially more agreeable solution.

We could keep MigrateDrupal6Test exactly the way it is, and simply change all the individual tests' setUp() methods so that they execute their dependencies, rather than mocking things with prepareMigrations(). Then they would be putting the system into the same state that MD6T does, while still being individually runnable. Because MD6T never runs setUp(), there would be no conflicts or exceptions caused by running the same migrations twice. We would still be able to lose many lines of code by killing prepareMigrations() and all calls to it, and the tests would become easier to grok.

This, to me, this is a solution where everybody wins.

mikeryan’s picture

+1 to having individual tests actually execute their dependencies. I'm blocked on #2554003: isComplete() should not rely on RESULT_COMPLETED because the current system is mocking only the minimally-necessary data to pass, so changes that require more of the data context to make sense need to do a lot of work fixing tests. In general, as pointed out above, it's problematic that you can make tests pass by manipulating the fixture data, we're much better off testing against realistic data.

neclimdul’s picture

No, I don't think we can't keep the current system. Similar to #14, #2510160: d6 Imagecache -> d8 Image module migration should be included in core is also blocked on being able to provide test coverage.

The problem we have is that MigrateDrupal6Test runs all test and runs all tests cases in the same process. This is the fundamental design of the test. This breaks an assumption in testing though. Each test method must run in its own run wrapped by setUp and tearDown. To go even further, in a kernel or web tests like this it is a 100% different process with different databases. To run in these 2 vastly different context is not fair on people writing tests.

I'll go even further, we have to be able to support the standard method going forward because we can't just test "migrations work!" like is the assumption MigrateDrupal6Test. Qe also have to be able to setup certain invalid states and confirm that the fail correctly. If you change the state in a migration test now it completely breaks all other assertions when MigrateDrupal6Test runs through them.

While I'm not going to argue that this has caught real use cases in the past, that is awesome. The fact is it just isn't sustainable going forward and we're going to have to just build better test coverage of our code and rely on that instead.

benjy’s picture

Just to be clear, it's not the assertions that are the problem. The problem is the state of the system in which the assertions are being made. We can't allow it to differ based on how the test was run.

This is the whole point of the test, to assert that running all the migrations gives the same outcome as what we got in manually constructed setUp(). The data shouldn't be different as the individual tests should only assert data that came from the dumps.

+1 to having individual tests actually execute their dependencies.

This just sounds like you're turning every test into something as complex as MD6T to me, debugging one migrate test will become a huge PITA, stepping through half a dozen individual migrations :/ This is half of the pain of debugging MD6T, when you have a fail in migration 5, you have to step through 4 migrations to get there, slow and tedious.

While I'm not going to argue that this has caught real use cases in the past, that is awesome. The fact is it just isn't sustainable going forward and we're going to have to just build better test coverage of our code and rely on that instead.

Well it's not just real bugs, it's probably the only test that actually catches anything meaningful right now, including most importantly changes to other parts of core that broke Migrate, very important!

I'll go even further, we have to be able to support the standard method going forward because we can't just test "migrations work!" like is the assumption MigrateDrupal6Test.

This I agree with, I think we could look at some how having our current tests that work within MD6T and then additional tests outside of that for specifically testing other conditions such as testing invalid state etc.

phenaproxima’s picture

This just sounds like you're turning every test into something as complex as MD6T to me, debugging one migrate test will become a huge PITA, stepping through half a dozen individual migrations :/ This is half of the pain of debugging MD6T, when you have a fail in migration 5, you have to step through 4 migrations to get there, slow and tedious.

That is more or less correct.

BUT! The value here is that a failed test will be failing in the same way and for the same reasons that it would fail under MD6T, rather than fail over its mocked state. Right now, if a test fails to assert mocked state, it may also fail in MD6T. And if it does, it's usually for a different reason, with a completely different error/fatal. Which means you have to debug the stupid test twice. Once in standalone mode, once in MD6T mode. This sucks even harder than having to step through dependent migrations to determine the cause of a failure -- which you already need to do anyway when debugging the failure under MD6T.

EDIT: In my view, MD6T makes debugging harder because rather than simply knowing which few migrations you need to step through in order to debug, it could be ANY of the migrations in the ginormous list that MD6T runs. Debugging tests that fail under MD6T is like being dropped, blindfolded and disoriented, into a deep hole. An individual test would be easier to debug, I'd argue, since you'd know precisely which migrations ran beforehand.

benjy’s picture

I don't find that to be the case, more often than not, you debug the individual tests and then MD6T is working unless you have a genuine problem.

MD6T is painful to debug when you get a bad issue, if every test had the same debugging process, it would be excruciating.

phenaproxima’s picture

I don't find that to be the case, more often than not, you debug the individual tests and then MD6T is working unless you have a genuine problem.

That has not really been my experience. More than once I have fixed a standalone test which continues to choke MigrateDrupal6Test. I believe other developers have encountered this scenario too, and hopefully they will chime in here. More to the point, I feel we can do better than "more often than not" -- when a test is fixed, it should be fixed. Tests are crucial, and they should be reliable and confidence-inspiring.

benjy’s picture

Can you give me an example? I can't think of many occassions where a single test chokes MD6T where it hasn't either been a) a simple problem in setUp() or b) an actual bug

neclimdul’s picture

Yes, I can't write a complete test for #2510160: d6 Imagecache -> d8 Image module migration should be included in core. It requires a database with deprecated values that can't be migrated and so will stop the migration and tell the user why the migration can't complete.

Edit: Clarity, they where deprecated in 6. removed in 7 so don't exist in 8. there is no update path for 7 and no way to translate them or migrate them to 8.

benjy’s picture

@neclimdul, could make the changes in setUp() as needed or import a new fixture for that one test?

However, I do see the clumsyness in that approach and as I previously mentioned, we could have tests that aren't wrapped up in MD6T.

Just for reference, here are a couple of bugs that were only caught by MigrateDrupal6Test that I could remember. I'm sure there has probably been more.

https://www.drupal.org/node/2414651#comment-10227845
https://www.drupal.org/node/2374087#comment-9342947
https://www.drupal.org/node/2247903#comment-8806547
https://www.drupal.org/node/2346039#comment-9282251 (fixed multiple issues here)

phenaproxima’s picture

The only reason those bugs were caught my MigrateDrupal6Test is because it actually runs the inner tests' dependent migrations first. I maintain that allowing individual tests' setUp() methods to run dependencies would have the same effect and catch the very same bugs. As far as I can tell, there is no functional difference between doing things that way and using MigrateDrupal6Test.

benjy’s picture

I'm not arguing that running the dependant migrations wouldn't have caught those issues, simply giving everyone a few example issues to test against if we remove this test.

neclimdul’s picture

I don't how to say this without coming off wrong but I'm going to do my best. I really do appreciate your input and as I've said respect the way MD6T has slingshotted the migrate development. But I don't think we are going to agree on this because I don't really care what things where caught by this test. If we miss something, and it doesn't get caught by our tests we didn't have sufficient coverage and we write better tests, iterate, iterate, we have a solid test suite. This is actively blocking that process though which is why I keep pushing for its removal.

The current state of things with todays @group opt ins I think makes things ok because its easy enough to opt out of this test. If that where to change I would _strongly_ push for this again. An it is still a terrible trap for test developers though and I don't like it.

benjy’s picture

I'm open to running the dependant migrations as a possible solution although I foresee that making all migration tests much harder to debug.

It's fine everyone not liking this test but I haven't seen any proposals other than above that offer a solution to catch/test bugs that this test currently covers. It should stay until that point.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Status: Active » Needs review
StatusFileSize
new119.32 KB

People who hang out with me in IRC know that I frequently mention kaiju: https://en.wikipedia.org/wiki/Kaiju

Well, this patch is a kaiju. A magnum opus in 3,300 lines. It is a major refactoring of the entire Drupal 6 migration test suite. Here are the important things you should know:

  • This patch removes MigrateDrupal6Test and its parent, MigrateFullDrupalTestBase because it renders them obsolete. The main difference between the individual migration tests and the MigrateDrupal6Test meta-test is that the meta-test ran the dependent migrations for real, whereas individual tests were allowed to mock their initial state in setUp() using prepareMigrations(). The meat of this patch is to make the individual tests' setUp() methods run their dependent migrations, thus making them almost fully consistent with MigrateDrupal6Test.
  • I removed MigrateDrupalTestBase::testSourcePlugin(). I'm pretty sure this method is an artifact because it adds absolutely no value -- in fact, the things it asserted are already asserted in greater detail by our source plugin unit test suite! Considering how all setUp() methods now do a great deal more work (computationally speaking), having a pointless test method which will trigger setUp() creates significant overhead.
  • Virtually no assertions were removed. One assertion was deleted from MigrateNodeRevisionTest, because it was asserting something which was only created in setUp() and not migrated from the database fixture.
  • I did a lot of miscellaneous clean-up -- I removed deprecated procedural function calls (mostly to entity_load()), added the public modifier to the $modules property where it was missing, and changed some instances of array() syntax to [].
  • MigrateDrupal6TestBase has a battery of new methods to perform certain "chunks" of a migration: migrateUsers(), migrateContent(), migrateContentTypes(), migrateTaxonomy(), and migrateFields(). These methods are used liberally in the updated setUp() methods, and essentially hard-code the dependency chain of the D6 migrations. If the migrations' dependencies change, these methods will probably need to be changed as well.
  • MigrateDrupal6TestBase now enables several very commonly needed modules, thus reducing the number of module dependencies of its subclasses.
  • git tells me this patch has 400 insertions, and 1,508 deletions. Great success!

EDIT: Committers should note that, even though this patch removes tests, it does not remove test coverage. If you read MigrateFullDrupalTestBase, you'll see it carries no assertions of its own -- it's merely a test that runs other tests.

neclimdul’s picture

  1. +++ b/core/modules/book/src/Tests/Migrate/d6/MigrateBookTest.php
    @@ -17,39 +17,16 @@
    -    $this->installEntitySchema('node');
    

    Not needed anymore? Did something change in book migration since this was written or subtle change?

  2. +++ b/core/modules/comment/src/Tests/Migrate/d6/MigrateCommentVariableDisplayBase.php
    @@ -15,57 +15,22 @@
    -    entity_create('field_storage_config', array(
    -      'entity_type' => 'node',
    -      'field_name' => 'comment',
    -      'type' => 'comment',
    -      'translatable' => '0',
    -    ))->save();
    -    foreach ($this->types as $type) {
    -      entity_create('node_type', array('type' => $type))->save();
    -      entity_create('field_config', array(
    -        'label' => 'Comments',
    -        'description' => '',
    -        'field_name' => 'comment',
    -        'entity_type' => 'node',
    -        'bundle' => $type,
    -        'required' => 1,
    -      ))->save();
    -    }
    -    $id_mappings = array(
    -      'd6_comment_field_instance' => array(
    -        array(array('page'), array('node', 'comment', 'page')),
    -      ),
    -    );
    -    $this->prepareMigrations($id_mappings);
    -    $this->executeMigration(static::MIGRATION);
    -
    +    $this->installConfig(['comment', 'node']);
    +    $this->executeMigration('d6_node_type');
    +    $this->executeMigration('d6_comment_type');
    +    $this->executeMigration('d6_comment_field');
    +    $this->executeMigration('d6_comment_field_instance');
    

    Gosh darn this just just so much easier to understand.

  3. +++ /dev/null
    @@ -1,100 +0,0 @@
    -abstract class MigrateUploadBase extends MigrateDrupal6TestBase {
    

    I assume since this was all setup that the shared code isn't needed anymore.

  4. +++ b/core/modules/file/src/Tests/Migrate/d6/MigrateUploadTest.php
    @@ -14,22 +16,44 @@
    +    // Create new file entities.
    +    for ($i = 1; $i <= 3; $i++) {
    +      $file = File::create(array(
    +        'fid' => $i,
    +        'uid' => 1,
    +        'filename' => 'druplicon.txt',
    +        'uri' => "public://druplicon-$i.txt",
    +        'filemime' => 'text/plain',
    +        'created' => 1,
    +        'changed' => 1,
    +        'status' => FILE_STATUS_PERMANENT,
    +      ));
    +      $file->enforceIsNew();
    +      file_put_contents($file->getFileUri(), 'hello world');
    +
    +      // Save it, inserting a new record.
    +      $file->save();
    +      $id_mappings['d6_file'][] = array(array($i), array($i));
    +    }
    

    why do we still need to mock these?

  5. +++ b/core/modules/migrate_drupal/src/Tests/MigrateDrupalTestBase.php
    @@ -70,20 +70,4 @@ protected function installMigrations($version) {
    -  /**
    -   * Test that the source plugin provides a valid query and a valid count.
    -   */
    -  public function testSourcePlugin() {
    -    if (isset($this->migration)) {
    -      $source = $this->migration->getSourcePlugin();
    -      // Make sure a SqlBase source has a valid query.
    -      if ($source instanceof SqlBase) {
    -        /** @var SqlBase $source */
    -        $this->assertTrue($source->query() instanceof SelectInterface, 'SQL source plugin has valid query');
    -      }
    -      // Validate that any source returns a valid count.
    -      $this->assertTrue(is_numeric($source->count()), 'Source plugin returns valid count');
    -    }
    -  }
    -
    

    while this test was a sneaky sometimes annoying one, is removing it in scope?

  6. +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6TestBase.php
    @@ -14,6 +15,16 @@
     
    +  public static $modules = [
    

    This and probably others should have an inherit doc.

  7. +++ b/core/modules/node/src/Tests/Migrate/d6/MigrateNodeTest.php
    @@ -23,14 +23,12 @@ class MigrateNodeTest extends MigrateNodeTestBase {
    -    // on story and test_planet nodes.
    -    $this->executeMigration('d6_node__test_planet');
    
    @@ -83,10 +76,6 @@ public function testNode() {
    -
    -    $node = Node::load(3);
    -    // Test that format = 0 from source maps to filtered_html.
    -    $this->assertIdentical('filtered_html', $node->body->format);
    

    I admit, these removals aren't clear to me.

  8. +++ b/core/modules/user/src/Tests/Migrate/d6/MigrateUserProfileValuesTest.php
    @@ -37,99 +33,12 @@ class MigrateUserProfileValuesTest extends MigrateDrupal6TestBase {
    +    $this->executeMigration('user_profile_field');
    +    $this->executeMigration('user_profile_field_instance');
    +    $this->executeMigration('user_profile_entity_display');
    +    $this->executeMigration('user_profile_entity_form_display');
    +    $this->migrateUsers(FALSE);
    

    I guess this worked but seems reversed.

phenaproxima’s picture

  1. It's no longer needed because migrateContent() already does it.
  2. Definitely one of my goals here :)
  3. Yes, that is exactly what happened.
  4. The reason those still need to be mocked is because the physical files, as defined in the database fixture, don't exist. So the migration would likely fail if we tried to do it for real. That's why I kept prepareMigrations() -- because there are limited legitimate uses for it.
  5. I don't know if it's in scope, but neither is all the cleanup. IMO we should just re-title this issue, since it generally improves DX and clarifies/cleans up the tests.
  6. I guess I'll do whatever the Drupal coding standards dictate on this point.
  7. That particular assertion was removed because, if you look in the D6 database dump, node 3 is a test_planet node, and test_planet does not have a body field. The only reason that assertion worked to begin with is because the setUp() method was specifically creating the test_planet node type and adding a body field to it.
  8. It's in dependency order...
neclimdul’s picture

1. 2. 3. Thanks
4. ok. Maybe we can follow up with a vfs fix but that works for now.
5. eeeegh ok? not sure about it.
6. There is no standard I could see but there is precedence in places like Drupal\Core\Menu\MenuLinkDefault::overrideAllowed
7. Works for me.
8. I just would have guessed the normal user migration would have to go before the profile stuff. Seems to work though so ok.

mikeryan’s picture

  1. +++ b/core/modules/comment/src/Tests/Migrate/d6/MigrateCommentTest.php
    @@ -19,10 +19,13 @@ class MigrateCommentTest extends MigrateDrupal6TestBase {
    +    // Directly testing that comments' entity_id is populated upon importing is
    

    While moving the comment (which I'm sure I wrote), worth improving it to be clear that the entity_id issue is something that happens to stubs (or at least used to). "Directly testing that a stub comment's..." Don't reroll just for this, of course...

  2. +++ b/core/modules/migrate_drupal/src/Tests/MigrateDrupalTestBase.php
    @@ -70,20 +70,4 @@ protected function installMigrations($version) {
    -  public function testSourcePlugin() {
    

    I'm going to test locally to see if the issue this was designed to catch (specific source plugins not properly implementing query() and count() - #2499793: Several migrate_drupal migrations fatal error on count()) get caught without it.

mikeryan’s picture

StatusFileSize
new120.3 KB
new848 bytes

Here's a witch-dunking test - it reintroduces one of the buggy conditions from #2499793: Several migrate_drupal migrations fatal error on count(). If this patch fails, that means it is detecting the problem and everything's hunky-dory. If this patch succeeds, this means that without testSourcePlugin() we're no longer testing for the regression, and we need to either bring it back or find another way to generally test for source plugins with bogus query()/count() implementations (or decide we don't need to test that).

Future core committers - DO NOT commit this version of the patch (even if it is green)!

The last submitted patch, 28: 2554321-28.patch, failed testing.

phenaproxima queued 28: 2554321-28.patch for re-testing.

mikeryan’s picture

Issue tags: +blocker

This is now a blocker for #2554003: isComplete() should not rely on RESULT_COMPLETED - the current tests' incomplete fixtures cause failures all over the place with that patch, by properly executing all dependent migrations in this patch most if not all of those failures should go away.

benjy’s picture

Status: Needs review » Needs work

I think you've done a great job here, the tests are certainly much more readable, really good work!

  1. +++ b/core/modules/comment/src/Tests/Migrate/d6/MigrateCommentVariableEntityDisplayTest.php
    @@ -15,21 +17,19 @@
    +      $component = EntityViewDisplay::load('node.' . $type . '.default')->getComponent('comment');
    

    I wish core would add a method to EVD to replace entity_get_display()

  2. +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6TestBase.php
    @@ -29,4 +40,91 @@ protected function getDumpDirectory() {
    +  protected function migrateUsers($include_pictures = TRUE) {
    ...
    +  protected function migrateContent($with_revisions = FALSE) {
    

    Maybe $include_revisions?

  3. +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6TestBase.php
    @@ -29,4 +40,91 @@ protected function getDumpDirectory() {
    +    $this->executeMigration('d6_taxonomy_vocabulary');
    +    $this->executeMigration('d6_vocabulary_field');
    +    $this->executeMigration('d6_vocabulary_field_instance');
    +    $this->executeMigration('d6_vocabulary_entity_display');
    +    $this->executeMigration('d6_vocabulary_entity_form_display');
    

    We have a hardcoded dependency list here, I think what would be a better approach would be for executeMigration to take an array and then use loadMultiple() to allow the storage controller to resolve the dependencies. That would make our tests a little more robust.

Also, NW for #33

phenaproxima’s picture

Title: Abolish MigrateDrupal6Test » Clean up Migrate's test suite
Status: Needs work » Needs review
StatusFileSize
new174.89 KB
new75 KB

Things I changed in this iteration:

  • testSourcePlugin() has taken its rightful place in MigrateSqlSourceTestCase. I also added a new unit test (of UserPictureInstance) to prove that the assertions pass, which necessitated a change to DummyQueryTrait in order to pass them. I'd say the witches have been thoroughly dunked, and I cannot express how much I love the term "witch-dunking".
  • All the $modules properties in MigrateDrupal6TestBase subclasses have been marked public static and given an @inheritdoc annotation. I removed them in certain tests where the required modules were already enabled by parent classes.
  • Fixed @mikeryan's comment in #32-1.
  • Addressed #37-2.
  • To address #37-3, I have introduced a new method called executeMigrations() into MigrateTestBase. This method takes an array of migration IDs, loads them (so the storage handler puts them into dependency order), and executes them in sequence. I've converted all the Drupal 6 and Drupal 7 tests to use this method.
  • MigrateUserProfileEntityFormDisplayTest started non-deterministically failing on my localhost when I changed it use executeMigrations(). Adding an explicit migration dependency on user_profile_field_instance -- which it should have had to begin with -- solved the problem.

I tip my hat to the heroes who reviewed this patch. If y'all are OK with the interdiff (and testbot signs off) I think this is ready to go. How nice it is to have reliable, understandable tests!

Re-titling the issue to reflect the expanded scope. 734 insertions, 2016 deletions.

phenaproxima’s picture

StatusFileSize
new172.4 KB
new4.17 KB

After discussing in IRC with @mikeryan, I've decided to restore and deprecate testSourcePlugin() for the time being. It should be removed, but to do that without losing test coverage means creating unit tests for the plugins which caused its creation in the first place. This is enough work to deserve its own follow-up issue.

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community
phenaproxima’s picture

Spun off #2573559: Remove MigrateDrupalTestBase::testSourcePlugin() for the crusade to destroy testSourcePlugin().

benjy’s picture

RTBC +1

With executeMigration(), we could have made migrateExecution() work with both or maybe we should just remove executeMigration() entirely now and only use executeMigrations()?

phenaproxima’s picture

With executeMigration(), we could have made migrateExecution() work with both or maybe we should just remove executeMigration() entirely now and only use executeMigrations()?

As we discussed in IRC, I decided to leave both in, at least for now, because I imagine executeMigration() could be potentially useful -- especially with the way it allows you to pass a fully-loaded migration in, not just an ID. If it becomes cruft, we can easily remove it in a follow-up patch.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 39: 2554321-39.patch, failed testing.

The last submitted patch, 39: 2554321-39.patch, failed testing.

phenaproxima’s picture

Issue tags: +Needs reroll
neclimdul’s picture

Status: Needs work » Needs review
StatusFileSize
new171.36 KB

easy enough.

neclimdul’s picture

forgot to mention, conflict was that #2569703: When migrating to the same theme with different region names, block will not migrate properly changed the theme name used in d7/MigrateBlockTest so there was a chunk conflict with some cleanups.

quietone’s picture

StatusFileSize
new172.51 KB
new1.01 KB

Use executeMigrations in d7/MigrateBlockTest.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Noice.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Wow, this is a fantastic clean-up! Impressive diffstat as well. :)

  1. +++ b/core/modules/migrate/src/Plugin/migrate/source/DummyQueryTrait.php
    @@ -26,4 +26,11 @@ public function query() {
    +  public function count() {
    +    return 1;
    +  }
    

    This stood out as something not like the rest of the changes...

    It turns out this was part of an earlier attempt to move unit test assertions (e.g. number of rows returned by source plugin) out of integration tests.

    It doesn't hurt anything for now, and will be part of a follow-up issue (#2573559: Remove MigrateDrupalTestBase::testSourcePlugin()).

  2. +++ /dev/null
    @@ -1,103 +0,0 @@
    -abstract class MigrateFullDrupalTestBase extends MigrateDrupalTestBase {
    

    This is a lot of removed code. However, @phenaproxima pointed out that this doesn't have any assertions in and of itself. And so as a result, we end up doing this work twice. Now, the integration tests will set up their migrations properly with ->executeMigrations()

  3. +++ b/core/modules/user/src/Tests/Migrate/MigrateUserProfileEntityFormDisplayTest.php
    @@ -17,81 +17,23 @@
    -    // Create some fields so the data gets stored.
    -    entity_create('field_storage_config', array(
    -      'entity_type' => 'user',
    -      'field_name' => 'profile_color',
    -      'type' => 'text',
    -    ))->save();
    -    entity_create('field_storage_config', array(
    -      'entity_type' => 'user',
    -      'field_name' => 'profile_biography',
    -      'type' => 'text_long',
    -    ))->save();
    ...
    -    foreach ($field_data as $field) {
    -      entity_create('field_config', array(
    -        'label' => $field->title,
    -        'description' => '',
    -        'field_name' => $field->name,
    -        'entity_type' => 'user',
    -        'bundle' => 'user',
    -        'required' => 1,
    -      ))->save();
    -    }
    -
    -    $this->executeMigration('user_profile_entity_form_display');
    +    $this->executeMigrations([
    +      'user_profile_field',
    +      'user_profile_field_instance',
    +      'user_profile_entity_form_display',
    +    ]);
    

    This is really nice to be able to eliminate that much code with just 3 lines of human-legible stuff. :)

No complaints here! Committed and pushed to 8.0.x. Thanks!!

  • webchick committed 8477f6b on 8.0.x
    Issue #2554321 by phenaproxima, mikeryan, quietone, neclimdul, benjy:...

Status: Fixed » Closed (fixed)

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