[SETUP ISSUE] Document and explore Bedrock compatibility
Environment OS: Linux 5.4.10 PHP version: 7.4.1 Installed Codeception version: 3.1.2 Installed wp-browser version: 2.2.32 WordPress version: 5.3 Local development environment: Valet-Linux WordPress structure and management: Bedrock
Did you use the codecept init wpbrowser command?
Yes.
Did you take a look at Codeception and wp-browser documentation? Yes.
Codeception configuration file
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
commands:
- Codeception\Command\GenerateWPUnit
- Codeception\Command\GenerateWPRestApi
- Codeception\Command\GenerateWPRestController
- Codeception\Command\GenerateWPRestPostTypeController
- Codeception\Command\GenerateWPAjax
- Codeception\Command\GenerateWPCanonical
- Codeception\Command\GenerateWPXMLRPC
params:
- .env.testing
Suite configuration file
# Codeception Test Suite Configuration
#
# Suite for unit or integration tests that require WordPress functions and classes.
actor: WpunitTester
modules:
enabled:
- WPDb
- WPLoader
- \Helper\Wpunit
config:
WPDb:
dsn: 'mysql:host=%TEST_DB_HOST%;dbname=%TEST_DB_NAME%'
user: '%TEST_DB_USER%'
password: '%TEST_DB_PASSWORD%'
dump: 'tests/_data/dump.sql'
populate: true
cleanup: false
url: '%TEST_SITE_WP_DOMAIN%'
tablePrefix: '%TEST_TABLE_PREFIX%'
WPLoader:
wpRootFolder: "%WP_ROOT_FOLDER%"
dbName: "%TEST_DB_NAME%"
dbHost: "%TEST_DB_HOST%"
dbUser: "%TEST_DB_USER%"
dbPassword: "%TEST_DB_PASSWORD%"
tablePrefix: "%TEST_TABLE_PREFIX%"
domain: "%TEST_SITE_WP_DOMAIN%"
adminEmail: "%TEST_SITE_ADMIN_EMAIL%"
title: "Site Title"
theme: <themename>
configFile: web/test-config.php
pluginsFolder: '../app/plugins'
plugins: ['woocommerce/woocommerce.php', 'advanced-custom-fields-pro/acf.php']
activatePlugins: ['woocommerce/woocommerce.php', 'advanced-custom-fields-pro/acf.php']
loadOnly: true
Describe the issue you're encountering
I have a Bedrock setup in which I want to integrate tests. I set up WPUnit tests, but when I run them, the database given in DB_NAME in the Bedrock .env file is wiped clear (wp_post, wp_postmeta, wp_termmeta, wp_term_taxonomy empty etc.), even though I defined a different database in the variable TEST_DB_NAME in the .env.testing file.
I assume this to be a configuration error, but I cannot figure how to properly set up wpbrowser to have mercy on my database.
@dorni1234 thanks for reporting the issue. Iām currently traveling and will look into this next week.
Are tests installed in Bedrock root directory? Any particular step I should take to reproduce other than default Bedrock project scaffolding?
Yes, the tests directory is located in the root of the Bedrock project. And no, this is a regular Bedrock setup.
@dorni1234 Now I'm back at work I can see something a bit "off".
Usually wpunit test suites, composed of test cases generated using codecept g:wpunit <suite> <case>, use the WPLoader module only w/ loadOnly: false (default value, hence usually not specified).
Could you provide an example of the test you're trying to run? I cannot quite grasp what kind of test you're trying to run and how.
Sorry for the late reply. Yes, I see the logical error I made with loadOnly: true, I somehow still had the acceptance tests in mind that rely on the production contents being present in the database.
Nonetheless, even with loadOnly: false, the database specified in DB_NAME is wiped clean.
The test I run looks like this:
<?php
namespace HABTests;
class WoocommerceProductHelperTest extends \Codeception\TestCase\WPTestCase
{
protected $product = [<Mock Data>];
/**
* @var \WpunitTester
*/
protected $tester;
public function setUp(): void
{
parent::setUp();
}
public function tearDown(): void
{
parent::tearDown();
}
public function testSetSku(): void
{
$wcProduct = new \WC_Product_Simple();
$this->assertTrue(WoocommerceProductHelper::setSku($wcProduct, $this->product));
}
public function testSetDuplicateSku(): void
{
$wcProduct = new \WC_Product_Simple();
WoocommerceProductHelper::setSku($wcProduct, $this->product);
$wcProduct->save();
$secondWcProduct = new \WC_Product_Simple();
$this->assertFalse(WoocommerceProductHelper::setSku($secondWcProduct, $this->product));
}
}
I run the test with vendor/bin/codecept run wpunit and the tests succeed.
Then, when I try to load the page of my development environment (using the database in DB_NAME), the site is devoid of any contents and uses the default Wordpress theme.
EDIT: I dumped the $wpdb object in the teardown function, and saw that it indeed used the prod database from DB_NAME.
I now implemented a workaround. In the test-config.php specified int the wpunit.suite.yml, I chaged the path of the application.php to test-application.php. And in the test-application.php, I edited the env variables used to define the database connection credentials.
So, I went from this:
Config::define('DB_NAME', env('DB_NAME'));
Config::define('DB_USER', env('DB_USER'));
Config::define('DB_PASSWORD', env('DB_PASSWORD'));
Config::define('DB_HOST', env('DB_HOST') ?: 'localhost');
Config::define('DB_CHARSET', 'utf8mb4');
Config::define('DB_COLLATE', '');
to this:
Config::define('DB_NAME', env('TEST_DB_NAME'));
Config::define('DB_USER', env('TEST_DB_USER'));
Config::define('DB_PASSWORD', env('TEST_DB_PASSWORD'));
Config::define('DB_HOST', env('TEST_DB_HOST') ?: 'localhost');
Config::define('DB_CHARSET', 'utf8mb4');
Config::define('DB_COLLATE', '');
$table_prefix = env('TEST_TABLE_PREFIX') ?: 'wp_';
And now my prod database is safe for now.
@dorni1234 thanks for the detailed information.
Usually the configFile is loaded to add some required parameters to the test configuration.
Could you share what is in the test-config.php file?
The test-config.php looks like this:
<?php
require_once(dirname(__DIR__) . '/vendor/autoload.php');
require_once(dirname(__DIR__) . '/config/test-application.php');
I followed the instructions from your blog post when setting it up to this point.
I've re-read the article and think there's space for improvement here:
- update the article
- add a Bedrock-specific setup guide
The article did work because, at the time of writing, the default environment file created, and used, by wp-browser, was the .env one.
That would coincide with the one used by Bedrock and make things work.
Since this is not the case anymore the article and guide need an update.
I will update this issue when that is up and running.
yay. I'd really like an update for the article https://www.theaveragedev.com/setting-wpbrowser-bedrock/
and or a section in the documentation for setting up all tests with bedrock.
on a current site and a new one.
I will get to that, the problem is time, not will.
I completely understand š. I just want to say I really appreciate your efforts with this repo!
I completely understand š. I just want to say I really appreciate your efforts with this repo!
Thanks, I really appreciate. I'm currently working to move wp-browser own testing structure to Docker and containerization and am having a lot of epiphanies along the way. When that is done, it will be Documentation Day(s).
Hi, anything new on this ?
I'm stuck with using WPLoader in a bedrock context, using loadOnly: true.
I have a separate .env.testing containing specific test values for wordpress constants (DB_NAME, DB_USER ...) but I can't find a solution to load them, as wp-load.php is requiring wp-config.php, which in turn points to /config/application.php .
I thought wp-config.php wasn't supposed to be loaded when using WPLoader, but apparently, this is the case.
I'm a bit lost...
Hi @LucasDemea,
I've set up Bedrock installations for testing a number of times, but it's been a while I've done it and things might have changed.
Would you be willing to walk me through how you've set up your project and wp-browser and what you're trying to test and how?
Again not being intimate with Bedrock, why use loadOnly=true? Asking out of ignorance.
The more information you could provide, the easier it would be for me to explore the issue.
Hi @lucatume I finally got this working, but I'm not sure it's the best way to do. I'm open to any advice.
I'm using WPLoader with loadOnly: true in functional tests because I need to use some wp core functions like get_bloginfo( 'name' ).
I didn't succeeded to use loadOnly: true without WPLoader loading the original wp-config.php.
I have a .env.testing where I mirror wp constants names :
# .env.testing
DB_DSN='mysql:host=localhost;dbname=tests'
DB_HOST='localhost'
DB_NAME='tests'
DB_PASSWORD='wordpress'
DB_USER='wordpress'
#...
I have a test-config.php where i setup some test specific configs:
// web/test-config.php
use Env\Env;
// getenv (used by Env\Env by default seems to be disabled in codeception context. Therefore we must use another method to get env vars
Env::$options |= Env::USE_ENV_ARRAY;
define( 'WP_LOADER', true );
Then, in application.php I load .env.testing and I define constants only if they are not already defined.
This is the part I feel is wrong somehow. I would have prefered not to change anything in this application.php, but as I can't get WPLoader to work without loading wp-config.php (and subsequent application.php), it's the only way I found for now. I would have prefered to use a different file than application.php for this.
// config/application.php
if (defined("WP_LOADER")) {
$env_files = [ '.env.testing' ];
} else {
$env_files = file_exists( $root_dir . '/.env.local' )
? [ '.env', '.env.local' ]
: [ '.env' ];
}
//...
/**
* DB settings
*/
if (!defined('DB_NAME')) {
Config::define('DB_NAME', env('DB_NAME'));
}
if (!defined('DB_USER')) {
Config::define('DB_USER', env('DB_USER'));
}
if (!defined('DB_PASSWORD')) {
Config::define('DB_PASSWORD', env('DB_PASSWORD'));
}
if (!defined('DB_HOST')) {
Config::define('DB_HOST', env('DB_HOST') ?: 'localhost');
}
if (!defined('DB_CHARSET')) {
Config::define('DB_CHARSET', 'utf8mb4');
}
if (!defined('DB_COLLATE')) {
Config::define('DB_COLLATE', '');
}
What I understand is that wordpress loads once, setting up the constants as expected, and then WPLoader requires application.php again, thus the need of these if (!defined(...)). If i don't use these conditions, Config::define() throws this exception: (here we can also see that WPLoader is loading wp-config.php)
In Config.php line 106:
[Roots\WPConfig\Exceptions\ConstantAlreadyDefinedException]
Aborted trying to redefine constant 'DB_NAME'. `define('DB_NAME', ...)` has already been occurred elsewhere.
Exception trace:
at /srv/www/site/current/vendor/roots/wp-config/src/Config.php:106
Roots\WPConfig\Config::defined() at /srv/www/site/current/vendor/roots/wp-config/src/Config.php:26
Roots\WPConfig\Config::define() at /srv/www/site/current/config/application.php:75
require_once() at /srv/www/site/current/web/wp-config.php:14
require_once() at /srv/www/site/current/web/wp/wp-load.php:55
include_once() at /srv/www/site/current/vendor/lucatume/wp-browser/src/Codeception/Module/WPLoader.php:618
Codeception\Module\WPLoader->bootstrapWP() at /srv/www/site/current/vendor/lucatume/wp-browser/src/Codeception/Module/WPLoader.php:470
Codeception\Module\WPLoader->_loadWordpress() at /srv/www/site/current/vendor/symfony/event-dispatcher/EventDispatcher.php:230
...
Next, i set up my functional tests this way:
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- WPDb
- WPLoader
- WPWebDriver
- Asserts
- \Helper\Functional
config:
WPDb:
dsn: "%DB_DSN%"
user: "%DB_USER%"
password: "%DB_PASSWORD%"
dump: "tests/_data/dump.sql"
populate: true
cleanup: false
waitlock: 10
url: "%WP_URL%"
urlReplacement: true
originalUrl: "%ORIGINAL_URL%"
tablePrefix: "%DB_PREFIX%"
WPWebDriver:
url: "%WP_URL%"
adminUsername: "%ADMIN_USERNAME%"
adminPassword: "%ADMIN_PASSWORD%"
adminPath: "%WP_ADMIN_PATH%"
window_size: false
port: 4444
browser: chrome
start: true
capabilities:
"goog:chromeOptions":
args:
[
"--headless",
"--no-sandbox",
"--disable-gpu",
"--user-agent=wp-browser",
"allow-insecure-localhost",
"--ignore-certificate-errors",
"--disable-dev-shm-usage",
]
WPFilesystem:
wpRootFolder: "%WP_ROOT_FOLDER%"
plugins: "../app/plugins"
mu-plugins: "../app/mu-plugins"
themes: "../app/themes"
uploads: "../app/uploads"
WPLoader:
wpRootFolder: "%WP_ROOT_FOLDER%"
dbName: "%DB_NAME%"
dbHost: "%DB_HOST%"
dbUser: "%DB_USER%"
dbPassword: "%DB_PASSWORD%"
tablePrefix: "%DB_PREFIX%"
loadOnly: true
domain: "%WP_DOMAIN%"
configFile: "web/test-config.php"