PHPUnit via WP-CLI: Warning: Cannot modify header information … bootstrap.php:68
-
23-02-2021 - |
Pergunta
I'm trying to setup unit tests for a plugin I am developing. I just followed the steps at... https://make.wordpress.org/cli/handbook/plugin-unit-tests/
However, when I run phpunit
I get the following...
$ phpunit
Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Warning: Cannot modify header information - headers already sent by (output started at /private/tmp/wordpress-tests-lib/includes/bootstrap.php:68) in /Users/<USERNAME>/Sites/<MYSITE.COM>/wp-load.php on line 64
I am running...
- Mac OS 10.12.6
- PHP v5.6.30
- PHPUnit 4.8.36
- MAMP Pro 4.2
The error noted, bootstrap.php:68
which is the start of the program outputting the "Installing..." text from the output noted above. Line 68 reads...
system( WP_PHP_BINARY . ' ' . escapeshellarg( dirname( __FILE__ ) . '/install.php' ) . ' ' . escapeshellarg( $config_file_path ) . ' ' . $multisite );
Solução
The error is telling you that the code tried to output a HTTP response header with the header()
function after the response body has already begun to be sent. As you noted, line 68 of bootstrap.php
is calling that script that outputs Installing...
. So after that output has already been sent, you can't send a response header.
The next step to debug this is to find out why a response header is being sent. That isn't supposed to be happening, because here we are running the tests from the command line, we're not actually sending a page to the browser.
So, we need to see where header()
is being called. The error tells you that it is in wp-load.php
on line 64:
header( 'Location: ' . $path );
This line itself doesn't tell us much, but we find that it is within a big if ... else
statement:
/*
* If wp-config.php exists in the WordPress root, or if it exists in the root and wp-settings.php
* doesn't, load wp-config.php. The secondary check for wp-settings.php has the added benefit
* of avoiding cases where the current directory is a nested installation, e.g. / is WordPress(a)
* and /blog/ is WordPress(b).
*
* If neither set of conditions is true, initiate loading the setup process.
*/
if ( file_exists( ABSPATH . 'wp-config.php') ) {
/** The config file resides in ABSPATH */
require_once( ABSPATH . 'wp-config.php' );
} elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
/** The config file resides one level above ABSPATH but is not part of another install */
require_once( dirname( ABSPATH ) . '/wp-config.php' );
} else {
// snip
header( 'Location: ' . $path );
// snip
}
Essentially what this tells us is that wp-load.php
is looking for the wp-config.php
file, and isn't finding it. So it is initiating the set-up process, and as part of that it is trying to redirect to the installation page by sending the Location
header.
So you apparently have not set up your wp-config.php
file correctly.
The wp-config.php
file was supposed to be set up by the script you ran though, so this is likely an indicator that something failed. In fact, since we are running the tests here, the wp-tests-config.php
file is expected to be used instead. So the next step is figuring out why wp-tests-config.php
isn't being loaded. You should be able to find that file in the /tmp/wordpress-tests-lib/
directory.
Outras dicas
That problem sounds like your code is sending text/characters to the screen, then it sends out a page 'header' (the <head>
part of an HTML page). PHP doesn't like that; once you put any characters on the screen, you can't send out page headers (the <head>
part).
Sometimes it is as simple as a space character in front of the <?php
code. Check for that, or any other text sent out before the page header.