I'm trying a basic UnitTest with Codeception. No frameworks are used.
My working root is as:
tests |
|-unit
|-Test.php
includes|
|-general
|-Custom.php
In Custom.php
<?php
namespace Custom;
class General {
public static function check(){}
}
My test case is:
<?php
use Custom\General;
use PHPUnit\Framework\TestCase;
final class Test extends TestCase
{
public function testPushAndPop(): void
{
General::check();
}
}
I also have in my composer.json:
"autoload": {
"psr-4":{
"Custom\\":"includes/general"
}
},
When I run
php vendor/bin/codecept run unit
...
1) Test: Push and pop
Test tests/unit/Test.php:testPushAndPop
[Error] Class 'DB\General' not found
#1 /var/www/html/prj/tests/unit/Test.php:9
Codeception Simple Unit Test Not Work To Find My Namespaces
This is less about Codeception but how PHP autoloading works in general and what the configuration of autoloading in Composer is in specific:
{
"autoload": {
"psr-4":{
"Custom\\":"includes/general"
}
}
}
Even the path-segment includes/general
does map on the file-system path includes/general/
(composer should have told you to add /
at the end of the path-segment), the error message
[Error] Class 'DB\General' not found #1 /var/www/html/prj/tests/unit/Test.php:9
shows that the namespace of Custom\\
in the Composer configuration is different to the namespace of the class that is not found (which is DB\\
).
So even the framework you have in use (you have one and that is the testing framework) may load the composer auto-loader (highly likely), its just that the class is not found.
As @Naktibalda already highlighted in a comment, it is just a plain autoloader configuration issue.
You are right, but why? The IDE does not claim any error... (your reaction)
These are two pair of shoes.
Your IDE most likely does not rely on the autoloader and just guesses the file from the file-system.
Depending how well maintained and configured your IDE is, it perhaps should and could have highlighted you that.
On the other hand, PHP can only rely on the autoloader, in your case you delegate the autoloading to composer(1)
, not to your IDE.
So maybe improve on that end as well, composer is more central for your projects development than the IDE can be.
So a suggestion:
Whenever changing the composer.json
file, I suggest to run composer validate --strict
to check your status, then follow with a composer update
.
Run this automatically before running your tests. You may not want to run composer update
, then run composer install
before running the test-runner if you have it as a development dependency.
Example to bind this for a single test run command within your composer.json
:
{
"scripts": {
"test": [
"@composer --no-plugins --version",
"@composer validate --strict",
"@composer --no-plugins -q install --no-scripts --no-progress",
"codecept run unit"
]
}
}
you then have a single call to run all the important things in your Composer based project:
$ composer test
...
Running unit-tests is a good way to verify the autoload configuration by the way. With the composer test-script you ensure it is always up-to-date when running the test-suite, too.
You don't need an IDE for this technically, which makes it more portable and stable giving you the peace of mind for your composer based project to grow.