PHPUnit and "Mark Directory As"

I am primarily a Java Developer and have used IntelliJ for years.  So I set up my project and moved all my php files under ./src and create a PHPUnit test under ./test.  I used the IDE "Mark Directory As" feature to mark the sources and test sources.  I am using composer to pull in PHPUnit.  I created a phpunit.xml file in the root of my project and configured PHPUnit to use it.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true">
    <testsuites>
        <testsuite name="Application Test Suite">
            <directory>./test/</directory>
        </testsuite>
    </testsuites>
</phpunit>

When I run my test, it cannot find the source PHP class it is testing.  I get an error:

PHP Fatal error:  Class 'com\acme\RFPHelper' not found in C:\Users\frederickb\Documents\Projects\ProjectService\Configurator\test\RFPHelperTest.php on line 17
PHP Stack trace:
PHP   1. {main}() C:\Users\frederickb\AppData\Local\Temp\ide-phpunit.php:0

The test class and the class being tested have the same namespace "com\acme".  I also have a test data file that is failing to be loaded using file_get_contents().  It would be nice if there were a "test resources" directory that could be marked.  It isn't clear what the "current directory" is when tests are being run.  I apologize that I am not more conversant with the PHP ecosystem, but the "Mark Directory As" feature implies that the unit test framework would be able to load php files from both the marked "src" directory and the "test" directory.  What am I misunderstanding?  Thank you.

Fred

5 comments
Comment actions Permalink

Hi there,

With PHPUnit you are responsible for making sure that PHP is able to find your (source) classes.

Since you are using Composer already, you can configure it (via composer.json) to do that for you. For example (quick edit):

"autoload": {
    "psr-4": {
        "com\\acme\\": "src/com/acme"
    }
}


Or, if you have your own autoloader -- use it in your bootstrap.php which will be used by PHPUnit to load your dependencies/do global initialisation etc (if you tell PHPUnit to use it, of course; be it via phpunit.xml or as part of IDE integration).

0
Comment actions Permalink

Hi Andriy,

I tried the composer.json autoload.  I even added an autoload-dev to the tests/ directory, but same error.  I tried removing the use of the phpunit.xml file from the test's Run/Debug configuration.  I switch from Test scope "Directory" to method.  Same error.  Then removed the check from TestRunner Default configuration file.  No change.  The PHPUnit library is "Load from include path".  What other configuration might I be missing?  Thank you for the help.

Fred

0
Comment actions Permalink

Hi Andriy,

I followed your link and made one more change, which I had missed, that of "Use custom loader" and specifying the autoload.php in vendor for the "Path to script".  Same error.  Thank you.

Fred

0
Comment actions Permalink
The PHPUnit library is "Load from include path"

If you are using this then most likely composer's autoloading functionality is not used. In this case you most likely need to require composer's "path/to/your/vendor/autoload.php" in your bootstrap.php file manually.

If you would use "Custom loader" option (which makes much more sense, since you are using Composer to get your PHPUnit) then it should use autoloader automatically.

----

I personally prefer and use PHAR version of PHPUnit (a bit less space/faster sync; does not contain tests and other not needed to run files that would usually come if installed via Composer).

This is very simplified project structure of what I use in couple of projects.

PROJECT_ROOT
  |-- [src]
    |-- [MyCode]

  |-- [tests]
    |-- [MyCode]

    |-- bootstrap.php
    |-- phpunit.xml
  |-- [vendor]
    |-- [composer]

    |-- ...

    |-- phpunit.phar
    |-- autoload.php

  |-- composer.json


In bootstrap.php I have (the important part)

<?php
...
require_once __DIR__ . '/../vendor/autoload.php'; // I need it because I'm using PHAR version


In composer.json (important part)

    "require": {
        "php": ">=5.4"
    
},
   ...
   "autoload": {
      "psr-4": {
         "MyCode\\": "src/MyCode/"
      
}
   }
}


If composer's autoloading does not work for some reason (e.g. you have dumped autoloading info into an array so it only takes info from there and does not do "dynamic" loading (searching actual file system for files each time)) .. you can always write and register your own autoloader (few lines of code).

My suggestion here: try going via bootstrap file and require_once autoload.php file there -- that's if autoloader as it is now does not work.

Unfortunately I cannot tell why it still does not work for you -- you may want to debug execution (set breakpoints in composer's autoloader) and see where it looks for files/classes when PHP is asking where to find you classes.

0
Comment actions Permalink

Your links led me to solve the problem.  I did not end up using psr-4, although I am going to read more about it.  I ended up trying classmap based on a Net Tuts video.

"autoload":{
    "classmap":[
      "src","src/com/acme"
    ]
  },
  "autoload-dev":{
    "classmap":[
      "tests/com/acme"
    ]
  },

I was also missing the bootstrap="vendor/autoload.php" attribute in the phpunit XML element.  Andriy, thank you very much!

Fred

0

Please sign in to leave a comment.