add a way to manually use the test site from a Functional test

Created on 29 April 2021, almost 4 years ago
Updated 12 September 2024, 5 months ago

Problem/Motivation

When developing a test, it's easy to get stuck in a situation where the setup of the test is going wrong.

Manipulating a Drupal site at one remove, through the intermediary of browser requests in the test, is a difficult and slow process. Each time a change is made, the test must be run all over again.

This could be improved if there was a way to preserve the test site after the test has run, so that the developer can interact with it and debug it.

Steps to reproduce

Proposed resolution

- Add a switch property to the Functional test base class which preserves the database tables in the test tear-down
- Detect either this or an environment variable to preserve the site in tearDown().
- Document in example.sites.php how to access a preserved test site

The developer wishing to use the test site would then:

1. Override the switch property in their test class, setting it to TRUE
2. Set the switch in their settings.local.php
3. Run the test
4. After the test is complete, go to their site, with a query string ?testsite=test12345 where 'test12345' is the name of the folder in sites/simpletest that was created for the test

Remaining tasks

User interface changes

API changes

- new class property in the Functional test base class
- new setting in settings.local.php

Data model changes

Release notes snippet

Feature request
Status

Needs work

Version

11.0 🔥

Component
PHPUnit 

Last updated 1 day ago

Created by

🇬🇧United Kingdom joachim

Live updates comments and jobs are added and updated live.
  • Needs documentation

    A documentation change is requested elsewhere. For Drupal core (and possibly other projects), once the change has been committed, this status should be recorded in a change record node.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States smustgrave

    Could the MR be updated for 10.1 please.

  • Pipeline finished with Failed
    7 months ago
    Total: 643s
    #220726
  • Status changed to Needs review 7 months ago
  • 🇬🇧United Kingdom joachim

    Added control of this feature with a BROWSERTEST_PRESERVE_SITE env var, and added documentation to phpunit.xml.dist.

  • Pipeline finished with Failed
    7 months ago
    Total: 590s
    #220928
  • Pipeline finished with Failed
    7 months ago
    Total: 705s
    #220945
  • Pipeline finished with Success
    7 months ago
    Total: 482s
    #221023
  • Status changed to Needs work 6 months ago
  • 🇺🇸United States smustgrave

    Sounds like a useful idea.

    I usually have to look at screenshots in the pipeline to see what went wrong.

    Reading the comments not 100% sure how to get it working but maybe the CR will help clear that up.

  • 🇳🇿New Zealand quietone

    Let's have this documented in the wiki and the change record can just refer to that. I think this is the page, PHPUnit Browser test tutorial .

  • 🇬🇧United Kingdom joachim

    Proposed documentation text:

    Interacting with the test site

    The test site can be preserved after the test has run, to allow the developer to interact with it as with a normal site and to inspect the database tables. This is useful for debugging and developing tests, when the HTML output files are insufficient to understand a problem.

    To preserve a test site instead of having it be deleted in the test’s tear down phase, do one of the following:

    • Set the class property $preserveSiteInTearDown to TRUE in your test class
    • Set the environment variable BROWSERTEST_PRESERVE_SITE to ‘true’ on the command line when running phpunit
    • Set the environment variable BROWSERTEST_PRESERVE_SITE to ‘true’ in your phpunit.xml file

    Then, after the test has run, do the following:

    1. Find the test site prefix. You can get this from the test site directory which was created during the test in your sites/ directory. It will be of the form ‘simpletest/test_123456'. The ‘test_123456’ is the test site prefix.
    2. Set up the sites.php file if it is not already present.
    3. Add code to return the test site directory as the site. The simplest way is to completely replace the main site with the test site:
      $sites = [
      ‘example.com’ => ‘simpletest/TEST_PREFIX',
      ];</ol>
      

    You can then use your site as you would a normal Drupal site. The admin user login is ‘admin’/‘admin’.

    You will need to delete the site directory and the test site database tables manually.

    —————-

    TODO: it occurs to me writing these instructions that it would be a nice DX touch to output the test site prefix in the phpunit output when the site is being preserved.

    PS. It’s not a wiki!!!

  • Status changed to Needs review 6 months ago
  • 🇬🇧United Kingdom joachim

    Wrote CR & draft documentation.

    Ready for review again.

  • Status changed to RTBC 6 months ago
  • 🇺🇸United States smustgrave

    Read the Cr and feel comfortable removing that tag.

    Leaving the documentation tag as don't know the process for getting that page updated.

    But thinks seem clearer based on what's there. Going to mark.

  • Status changed to Needs work 6 months ago
  • 🇳🇿New Zealand quietone

    I have been wanting to test this and today I finally did. I am pleased to say that it works in my environment which is DDEV and with a separate database for testing.

    TODO: it occurs to me writing these instructions that it would be a nice DX touch to output the test site prefix in the phpunit output when the site is being preserved.

    Yes, that would be a nice to have.

    The text in #14 for the doc page is fine with me. It does help to see it here though instead of waiting for this to be committed.

    I left comments and suggestions in the MR, about the comments, that do need to be looked at.

  • Pipeline finished with Canceled
    6 months ago
    Total: 118s
    #253657
  • Pipeline finished with Canceled
    6 months ago
    Total: 200s
    #253658
  • Pipeline finished with Canceled
    6 months ago
    #253668
  • Pipeline finished with Failed
    6 months ago
    #253671
  • Status changed to Needs review 6 months ago
  • 🇬🇧United Kingdom joachim

    > Yes, that would be a nice to have.

    Done, but I suspect this is going to bog this issue down, as the way I've done it isn't ideal and I don't see a better way.

    It's not ideal because printing from within the test process causes PHPUnit to say the test was risky because it printed something. I think that's acceptable, because the developer knows they're doing something for debugging.

    I experimented with using a PHPUnit extension, same way that HtmlOutputLogger is a PHPUnit extension, but that doesn't work because outside of the test's process, we can't get the site ID.

    The only way that I can think of would be to either write the ID to a file, or have the PHPUnit extension look at all the folders in sites/simpletest and pick the newest one.

  • Pipeline finished with Failed
    6 months ago
    Total: 501s
    #253682
  • Status changed to Needs work 5 months ago
  • 🇺🇸United States smustgrave

    Re-ran unit test multiple times but unfortunately fails each :(

  • Status changed to Needs review 5 months ago
  • 🇬🇧United Kingdom joachim

    Fixed text, and tweaked the wording of the later paragraph as it says 'this' and 'it' for things which are really far away now.

  • Pipeline finished with Failed
    5 months ago
    Total: 550s
    #280912
  • Status changed to Needs work 5 months ago
  • 🇺🇸United States smustgrave

    Trying to keep up with this one quicker.

    So now it appears to be nightwatch failing consistently? Re-ran 4 times

  • 🇬🇧United Kingdom joachim

    I don't see how Nightwatch can be failing because of this??

  • heddn Nicaragua

    I'm running with this patch on a contrib project to see why its test are failing. Without this patch, the JS test randomly passes. With this patch, it gives me the following output, mainly: Test Printed Unexpected Output

    Assertion Succeeded (Constraint: is equal to 'pt-pt', Value: 'pt-pt')
    Post Condition Method Called (Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::failOnJavaScriptErrors)
    Post Condition Method Finished:
    - Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::failOnJavaScriptErrors
    Test Passed (Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::testMultipleLocalToSingleRemoteMapping)
    After Test Method Called (Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::tearDown)
    After Test Method Called (Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::tearDownErrorHandler)
    After Test Method Finished:
    - Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::tearDown
    - Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::tearDownErrorHandler
    Test Printed Unexpected Output
    Test site is preserved with site ID 75952671.
    
    Test Considered Risky (Drupal\Tests\tmgmt\FunctionalJavascript\TranslatorJavascriptTest::testMultipleLocalToSingleRemoteMapping)
    This test printed output: Test site is preserved with site ID 75952671.
    
  • 🇬🇧United Kingdom joachim

    That's normal.

    The test prints this:

    > This test printed output: Test site is preserved with site ID 75952671.

    so that you know how to access the test site. Without it, you'd have to do an ls of the sites/simpletest (IIRC) folder and find which numeric-named folder is the most recently created.

  • heddn Nicaragua

    Is there any way around that? A Risky test makes me think something in the test failed. If no way around, we should definitely mention that implication in the CR.

  • 🇬🇧United Kingdom joachim

    Not easily.

    The way to produce output in PHPUnit is with a PHPUnit extension, similar to how we handle HTML output with HtmlOutputLogger.

    But the test site ID is inside the test, and a PHPUnit extension doesn't have access to that data.

    The way that HtmlOutputLogger manages to pass information between the two systems is by setting an env variable when the test starts, which gives the location of a file to write to. The test can then use tat env var to write a list of written HTML files:

    HtmlOutputLogger extension:

        if ($this->browserOutputFile) {
          touch($this->browserOutputFile);
          putenv('BROWSERTEST_OUTPUT_FILE=' . $this->browserOutputFile);
        }
    

    In the test:

      protected function initBrowserOutputFile() {
        global $base_url;
        $browser_output_file = getenv('BROWSERTEST_OUTPUT_FILE');
    

    We'd have to do something similar: create a PHPUnit extension which sets and env var which is a filepath, and the test system writes the test ID into that file, and after the test has run the extension can output a message about the site ID.

    I don't think the test can write the site ID to an env var, as then IIRC PHPUnit will complain that the env has changed during the test.

    I wasn't sure it was worth that much effort to write all that, seeing as if you're enabling this for a test, it's probably that your test is failing anyway.

  • Pipeline finished with Failed
    3 months ago
    Total: 571s
    #333450
Production build 0.71.5 2024