Skip to content

Draft: Enable database in unit tests

I've had these patches lying around for a while, so thought I'd just submit them as is for now, and we can work on streamlining it more in public.

Why?

A lot of the code in Hubzilla core is very tightly coupled to the database backend. So to be able to get that code under test, we need some way to either stub or mock the database, or simply test with it. Given the structure of the code it's by far easier to test with the database in place.

How?

We set up a separate database for testing. This is for two reasons. 1) We don't want to mess with the main db (even in a dev environment), and 2) we want complete control over the contents of the database, so the tests become deterministic.

I have expanded the (until now empty) UnitTestCase base class in tests/unit/UnitTestCase.php, to actually connect to the test db, and to wrap every test case in a db transaction, so that the db is restored to it's original state again after every test.

The Unit test case will also load fixtures (the content that we want to populate the db with) for each transaction. This should probably be optimized to only load them for each test suite or something, but we can look at that if it becomes a problem. The fixtures does for now just reuse the existing fixtures that seems to have been used previously.

I've also created a script (again pretty much based on what already existed) for setting up the test db. Currently only for PostgreSQL, as that's what I'm using and testing on. We will want to set up a test db for MySQL/MariaDB too!

Running the tests

Make sure the dev dependencies are installed:

$ composer install

Create the test db:

$ DB_ROOT_USER=postgres ./tests/create_test_db_pgsql.sh

Replace the value of DB_ROOT_USER with whatever is apropriate for your setup. The user must have a role that allows creating new users and databases.

Run the tests:

$ ./vendor/bin/phpunit tests/
PHPUnit 9.5.23 #StandWithUkraine

...................................................PHP Deprecated:  strlen(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/core/vendor/simplepie/simplepie/idn/idna_convert.class.php on line 792
PHP Deprecated:  strlen(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/core/vendor/simplepie/simplepie/idn/idna_convert.class.php on line 792
.
Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/core/vendor/simplepie/simplepie/idn/idna_convert.class.php on line 792

Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/core/vendor/simplepie/simplepie/idn/idna_convert.class.php on line 792
...........  63 / 133 ( 47%)
.I..........PHP Deprecated:  hash(): Passing null to parameter #2 ($data) of type string is deprecated in /var/www/html/core/Zotlabs/Web/HTTPSig.php on line 33
.
Deprecated: hash(): Passing null to parameter #2 ($data) of type string is deprecated in /var/www/html/core/Zotlabs/Web/HTTPSig.php on line 33
..........................................II...... 126 / 133 ( 94%)
.......                                                         133 / 133 (100%)

Time: 00:00.420, Memory: 8.00 MB

OK, but incomplete, skipped, or risky tests!
Tests: 133, Assertions: 276, Incomplete: 3.

What's missing?

  • Testing this setup for MySQL and MariaDB
  • Currently the defaults used by the UnitTestCase class assumes a PostgreSQL database with the name and credentials as outlined above, but they can be overridden with environment variables. We may instead want to be able to specify an alternate .htconfig, or some other way to specify the test db and credentials.

Merge request reports