I have written a post a while ago about Eloquent with PHP 8.4 features. And more recently I commented on an Eloquent builder post about the problems I see with scopes.
Now it is time to put my money where my mouth is, and make things better for my taste.
The setup
I'm not going to pretend that my improvements will land in the official Laravel code any time soon, or ever. So I am going to use the illuminate/database repository.
Because it is a sub module of the laravel/framework this has a few problems.
The biggest problem is that there are no tests.
The quick fix is to take the tests/Database directory from the framework and create the test/Database directory in my fork.
Also stealing the phpunit.xml.dist file.
The next step is obviously adding phpunit/phpunit to the require-dev section of the composer.json file.
And then prepare to be disillusioned by the massive number of errors when I run the tests.
I forgot to record the initial result but a bit into fixing the tests I still got this result;
Tests: 2270, Assertions: 6212, Errors: 104, Failures: 12, Warnings: 1, Deprecations: 177, PHPUnit Deprecations: 1, Skipped: 1.
Making the tests run good enough to get started
The goal at this moment is to get as much tests a possible to be positive, comment out negative tests that are going to be changed during the improvement process, and remove tests that are tightly coupled to the framework.
The first step is fixing the composer.json file.
Because I already added phpunit to the require-dev section, I needed to added a few more libraries.
"require-dev": {
"fakerphp/faker": "2.0.x-dev",
"illuminate/console": "^13.0@dev",
"illuminate/events": "^13.0@dev",
"illuminate/filesystem": "^13.0@dev",
"illuminate/pagination": "^13.0@dev",
"illuminate/testing": "^13.0@dev",
"mockery/mockery": "2.0.x-dev",
"phpunit/phpunit": "^12.1@dev"
}
The fakerphp/faker, illuminate/console, illuminate/events, illuminate/filesystem and illuminate/pagination come from the suggest section of the composer.json file.
Mockery/mockery classes show up missing in the errors.
Illuminate/testing is added because there are tests that need the Assert class.
The next errors that can be fixed in the composer.json file are the errors because test classes can't be found. Another steal from the framework.
"autoload-dev": {
"files": [
"tests/Database/stubs/MigrationCreatorFakeMigration.php"
],
"psr-4": {
"Illuminate\\Tests\\": "tests/"
}
}
Next I see quite a few tests with the gmp_init function missing. I saw the tests were all in the EloquentModelCustomCastingTest class. Because I didn't want to add the extension to docker at the moment I removed that class.
Another error I saw returning a few times was the pipe
method of the Builder
class that was not found. It were a few tests with multiple calls to the method so I just put them in comments.
Next error that got my attention was the now
function. When I searched the tests I found it is due to an inconsistent use of the now
helper function and the Carbon::now
method. Because the helper function is a wrapper for the latter method I replaced the function in the tests.
Seeing the number of errors going down is satisfying, but there are still more to go before I could check the test failures.
Mockery\Exception\BadMethodCallException: Received Mockery_13_Illuminate_Database_Eloquent_Builder::removedScopes(), but no expectations were specified
This error is likely to be removed or changed during the improvement process so I put those tests in comments.
Following errors flagged id a an ambiguous column name, and because of that threw a sql exception. I commented them out.
The Post
and User
classes where not found by some tests. Adding the Post
class from the framework was easy.
For the User
class it was a bit trickier because some of the tests required the Illuminate\Foundation\Auth\User class and some required a User
test class.
I decided to go with User
test class for all the tests, and comment out failing tests that are related to the Auth\User
latter on.
My eye caught a single error; InvalidArgumentException: Illegal operator and value combination.
I just commented out the test.
Next on the list were, Class "Illuminate\Foundation\Application" not found, errors. They were all in the PruneCommandTest
class.
I commented out the whole class, so that creates a warning in the phpunit report. When I start the improvements I'm going to check If I can save those tests or not.
These changes removed all the errors, so now I had to go over the failures. After a quick look what each test did, I commented them out.
The phpunit report now looks like this.
Tests: 2237, Assertions: 6426, Warnings: 2, Deprecations: 179, PHPUnit Deprecations: 1, Skipped: 1.
I'm happy with this result.
Conclusion
While I understand the reasoning to have all the framework tests in a single directory, I think it would be beneficial to have tests in the sub modules.
After this exercise I learned a bit more about Eloquent, and this will help me when I start making changes.