Problem/Motivation

BrowserTestBase currently only does verbose HTML output logging for a requested page if the methods drupalGet() and similar are used, which have explicit logging. We want the logging at all times, even if developers use the native mink methods directly to click a link for example.

Proposed resolution

Add a Guzzle middleware for browser tests that always performs logging. Remove the explicit logging from drupalGet() and friends since it will be done for all requests anyway.

Remaining tasks

Patch.

User interface changes

None.

API changes

None.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

klausi created an issue. See original summary.

klausi’s picture

Status: Active » Needs review
FileSize
3.95 KB

This is what I have in mind.

Advantages: catch all middleware, no request is lost. Very little code for us to maintain.

Disadvantage: only works with GoutteDriver, so it does not work for JavascriptTestBase.

This will also print redirect responses to the debug output. When you view the redirect responses in your browser then the http-equiv="refresh" meta tag is invoked and the browser redirects away. We should avoid this somehow.

klausi’s picture

If only Mink had the concept of middlewares on the driver level same as Guzzle has :-(

The alternative to this is using the proxy pattern and implement a transparent DrupalTestDriver for Mink which wraps the actual driver class. And then implement request logging on many methods of DriverInterface.

klausi’s picture

FileSize
5.09 KB
2.02 KB

We should also print the calling test class method and line number to help people find the offending line in their test.

klausi’s picture

FileSize
5.65 KB
1.35 KB

And here is the fix to remove the refresh meta tag to avoid browser redirects when looking at the HTML file.

The middleware is now getting a bit long and should be moved to a dedicated method in BTB in the next iteration of this.

klausi’s picture

FileSize
13.28 KB

Here is a patch that experiments with a decorator/proxy for Mink drivers. The problem is that the drivers also perform requests internally which are not routed through the public function of DriverInterface. Example: a click() call can mean that a form is submitted with the push of a button, but the call does not go through submitForm() of the driver, so we cannot log it.

So I think that approach is not feasible for us and we will have to stick to a Guzzle middleware for BrowserTestBase. Pus explicit logging in JavascriptTestBase for now until we can come up with a better idea.

klausi’s picture

FileSize
6.4 KB
5.15 KB

Continuing with the Guzzle middleware approach, moving it to a dedicated method.

Restored the explicit logging in drupalGet() and submitForm() to keep logging when using JavascriptTestBase with the PhantomJS driver.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

In general this looks really nice!

  1. +++ b/core/tests/Drupal/Tests/BrowserTestBase.php
    @@ -365,6 +375,43 @@ protected function getDefaultDriverInstance() {
    +   *   The callablke handler that will do the logging.
    

    nitpick: typo in callablke

  2. +++ b/core/tests/Drupal/Tests/BrowserTestBase.php
    @@ -641,7 +688,9 @@ protected function drupalGet($path, array $options = array()) {
    +    // Log only for non Goutte drivers because for those log with
    +    // ::getResponseLogHandler.
    
    @@ -944,7 +993,10 @@ protected function submitForm(array $edit, $submit, $form_html_id = NULL) {
    +    // Log only for non Goutte drivers because for those log with
    +    // ::getResponseLogHandler.
    

    Just a suggestion: I would just mention JavascriptTestBase for convencience

  3. +++ b/core/tests/Drupal/Tests/BrowserTestBase.php
    @@ -1636,19 +1689,24 @@ protected function htmlOutput($message) {
    -  protected function getHtmlOutputHeaders() {
    

    we could do a formatHtmlOutputHeaders

dawehner’s picture

Status: Needs review » Needs work
Issue tags: +Drupalaton
klausi’s picture

Status: Needs work » Needs review
FileSize
6.42 KB
3.15 KB

Rerolled and addressed your comments. Thanks!

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you for addressing the feedback!

benjy’s picture

Looks good to me, just one small improvement, for less lines of code :)

+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -1561,15 +1614,28 @@ protected function htmlOutput($message) {
+    $flattened_headers = array_map(function($header) {
+      if (is_array($header)) {
+        return implode(';', array_map('trim', $header));
       }
       else {
...
+        return $header;

This could just be return return implode(';', array_map('trim', (array) $header));

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: mink-log-2763401-11.patch, failed testing.

klausi’s picture

Status: Needs work » Reviewed & tested by the community

Seems like a random test fail, green again.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 11: mink-log-2763401-11.patch, failed testing.

klausi’s picture

Status: Needs work » Reviewed & tested by the community

Test is green, back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

Neat fix. Committed 761657a and pushed to 8.3.x. Thanks!

Setting to patch to be ported for eventual cherry-pick to 8.2.x once 8.2.0 is released.

  • alexpott committed 761657a on 8.3.x
    Issue #2763401 by klausi: PHPunit browser tests should log all Mink...
alexpott’s picture

Status: Patch (to be ported) » Needs work
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -396,6 +406,43 @@ protected function getDefaultDriverInstance() {
+  protected function getResponseLogHandler() {

@@ -1561,15 +1614,28 @@ protected function htmlOutput($message) {
+  protected function formatHtmlOutputHeaders(array $headers) {

@@ -1754,4 +1820,24 @@ protected function getConfigSchemaExclusions() {
+  protected function getTestMethodCaller() {

If we want this in 8.2.x then we need to prefix these methods with an underscore. Alternatively if we are happy to have this fix in 8.3.x only we can just mark it as fixed.

dawehner’s picture

Given that we do most of the conversions hopefully in 8.3.x the win is probably not that high. On the other hand we want to make things easier for contrib and custom modules.

Sam152’s picture

Status: Needs work » Needs review
FileSize
3 KB
6.43 KB

I'd like to see this in 8.2.x. I have client projects with test suites that could benefit from this.

I haven't seen internal class methods prefixed with an underscore or where this is documented? You'd think that's what private was for? In any case if that's the approach, patch attached.

Status: Needs review » Needs work

The last submitted patch, 22: mink-log-2763401-22.patch, failed testing.

Sam152’s picture

Version: 8.3.x-dev » 8.2.x-dev
Sam152’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 22: mink-log-2763401-22.patch, failed testing.

Sam152’s picture

Status: Needs work » Needs review

This passes against 8.2.x. Back to review.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

This looks alright for me

klausi’s picture

@alexpott: Why do we prefix those methods with an underscore? Then they are different in 8.3.x and 8.2.x and cause headaches for people working with them in both branches?

dawehner’s picture

@alexpott: Why do we prefix those methods with an underscore? Then they are different in 8.3.x and 8.2.x and cause headaches for people working with them in both branches?

This is our BC policy, see https://www.drupal.org/core/d8-bc-policy and Underscore-prefixed functions and methods

xjm’s picture

When @catch and @alexpott raised this issue this morning, my thought was that the underscore prefixes were only a workaround to allow us to backport fixes for (e.g.) major bugs when we could not do so otherwise. I don't think it was ever intended as a way to backport API additions to patch releases. But worth discussing the case of this issue in #2773087: [policy, maybe patch] Clarify backport policy for testing framework changes, including new BTB tests.

For me #22 alone as a reason to do this violates semver in principle, and there is a risk of disruption from it because BTB is intended as an extension point. On the other hand, I think we all consider BTB experimental in our heads, which means it's a pre-release version that we can add API to. But adding protected methods to a base class that is intended to be directly subclassed does risk breaking people's BTB tests.

Let's discuss more on #2773087: [policy, maybe patch] Clarify backport policy for testing framework changes, including new BTB tests?

jhedstrom’s picture

+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -1766,4 +1832,24 @@ protected function getConfigSchemaExclusions() {
+    while (($caller = $backtrace[1]) &&
+      (!isset($caller['class']) || $caller['class'] !== get_class($this))
+    ) {

I haven't pinned down the exact cause yet, but this logic can lead to Undefined offset: 1 errors, but only on certain GET requests.

jhedstrom’s picture

Wim Leers’s picture

Title: PHPunit browser tests should log all Mink requests » [PP-1] PHPunit browser tests should log all Mink requests
Status: Reviewed & tested by the community » Postponed
Wim Leers’s picture

Wim Leers’s picture

Title: [PP-1] PHPunit browser tests should log all Mink requests » PHPunit browser tests should log all Mink requests
Status: Postponed » Needs work
Issue tags: +Needs reroll

#2822387: Undefined offset 1 in BrowserTestBase::getMethodCaller() landed. This can now continue for 8.2.x. But it'll need a reroll, to incorporate the fixes from #2822387: Undefined offset 1 in BrowserTestBase::getMethodCaller().

The last submitted patch, 37: mink-log-2763401-37-8.3.x.patch, failed testing.

  • alexpott committed 761657a on 8.4.x
    Issue #2763401 by klausi: PHPunit browser tests should log all Mink...

  • alexpott committed 761657a on 8.4.x
    Issue #2763401 by klausi: PHPunit browser tests should log all Mink...
jofitz’s picture

Issue tags: -Needs reroll

Remove "Needs reroll" tag.

dawehner’s picture

We probably won't get this into 8.2.x, so we on the other hand don't need underscores then.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

klausi’s picture

Status: Needs review » Fixed

OK, so let's call this fixed in 8.3.x without 8.2.x backport.

Status: Fixed » Closed (fixed)

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