Configuring File Names for PHPUnit - php

I am a new user of PHPUnit, and I am converting our existing tests (asserts) into the PHPUnit framework to provide a better test environment and code coverage. However, I need to know how to try to get PHPUnit working with our testing code structure.
Our project directories are similar to the following:
Application1/
CREDIT_CARD.class - Class naming convention for CREDIT_CARD
CREDIT_CARD.class.test - Automated Tests for CREDIT_CARD.class
File.php - Application File
File.php.test - Automated tests for File.php
File2.php
File2.php.test - Automated tests for File2.php
Application2/
ANOTHER_CLASS.class
ANOTHER_CLASS.class.test
DifferentFile.php - Application File
DifferentFile.php.test - Automated tests for File.php
lib/
UTIL/
SHARED_CLASS.class
SHARED_CLASS.class.test
VISUAL/
VISUAL_TOOL.class
VISUAL_TOOL.class.test
I need to know how to configure the PHPUnit tests so I can run the tests in lib/UTIL/.test (which load the class file using the setUp() method) then the lib/VC/.test, followed (if successful) by the Application1 and Application2 tests. I saw mention of a PHPUnit_xml file and a bootstrap file, but I can not find a reference template to see if these are what I need. Any help would be appreciated.
I know the documentation refers to a test.php addition to the file names, but I am hoping to not have to change our structure and naming conventions as I would like to be able to run a mix of the files until they are all converted over to the PHPUnit framework. Changing names will cause a procedure change in our company and training for the developers, which I am trying to avoid.
Thanks in advance for any assistance.

So you have files named Foo.class.test instead of the PHPUnit default FooTest.php ?
That shouldn't be a big problem as PHPUnit allows you to configure what file suffixes are to be treated as "tests". The Test.php is just the default.
Have a look at the xml config part of the docs regard test organisation
What you want is:
<testsuites>
<testsuite name="Our new shiny phpunit test Suite">
<directory suffix=".test">./sourceFolder</directory>
</testsuite>
</testsuites>
PHPUnit will then scan through the source folder including all files that end in .class.test and leaving the other files as is.

Related

Getting InvalidArgumentException - Unknown format from fakerphp/faker library in laravel while testing in custom testsuite using pest

I am using Pest library to write tests in laravel. I created the my-laravel-application/tests/Integration directory in laravel
and defined a new test suite in phpunit.xml
<testsuite name="Integration">
<directory suffix=".test.php">./tests/Integration</directory>
</testsuite>
So that laravel acknowledges the test files in Integration directory and I could write my integration tests in a separate directory with a proper name(Integration directory), And I put my test files in the my-laravel-application/tests/Integration directory and I got the following error while running php artisan test:
InvalidArgumentException - Unknown format "name"
vendor/fakerphp/faker/src/Faker/Generator.php:657
which indicates that the $this->faker->name() line of code in my UserFactory (I am using UserFactory class in my tests) has something wrong with, it says that name() method does not exist on $this->faker. But my tests used to work fine, before moving them to my-laravel-application/tests/Integration directory. What is the real problem and how can I fix this?
I found the solution based on this answer. You should enforce the use of Tests\TestCase (instead of PHPUnit\Framework\TestCase) for all the tests written in your newly created directory (Integration directory) by adding the following code to /tests/Pest.test:
uses(Tests\TestCase::class)->in('Integration');
This thread saved me lots of time.
I made sure an using right test case in the entire test dir...
uses(Tests\TestCase::class)->in(__DIR__);

PHPUnit - suffix argument ignored in directory tag under testsuite

I recently realized that I cannot run all my phpunit tests at once unless I use the "php artisan test", and I don't understand why. I would use the other option but I can't do coverage with that.
I assume it's somehow related to my configuration file being wrong because of a syntax change, or my directory being set wrong or something, because I can't find anything else.
The suite is found, but the suffix is not applied, whether I write it as ".php" or "Tests.php" or anything else. I know, because if I rename all my test files with Test at the end instead of Tests, then they suddently get recognized by phpunit. I also tried all numbers of directory options, like "./tests/Unit" and "./tests/Unit/*" but to no avail.
I would really appreciate some help if anyone has any idea what is happening, because it's driving me crazy. It took me a day to figure out I needed to rename my files just to make it work, and at this point I don't even want to do that unless I absolutely must, since there is this suffix feature.
I just want to understand why it does not work, and how to use it properly, in hopes of being able to learn how to use phpunit in the right way.
I can see two potential causes:
1) Your phpunit.xml may not be configured properly.
Try to change the "testsuite" and "coverage" section as shown below:
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
2) Make sure all your tests methods use the #test annotation in the method’s DocBlock:
/** #test */
public function your_test_method_name()
{
...
}
See: https://phpunit.readthedocs.io/en/9.5/annotations.html
As an alternative to prefixing your test method names with test, you can use the #test annotation in a method’s DocBlock to mark it as a test method.
If you don't include the docblock, make sure your test method names start with "test":
public function test_method_name()
{
...
}
See: https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html
The tests are public methods that are named test*.
Nothing worked to fix the suffix. I tried reinstalling xdebug, php, and phpstorm. I ended up just renaming the files as I said. Only working solution I could find.
I know, because if I rename all my test files with Test at the end instead of Tests, then they suddenly get recognized by phpunit.
That sounds like the default configuration for phpunit and could be a sign that your configuration file you're trying to control the behaviour with is not effective. That is, however you run Phpunit, it is without the configuration file and the path only, e.g.:
/path/to/phpunit -- /path/to/test/directory
Phpunit then will work with the default configuration - but it must find it in the working directory. So either the configuration files have a name different to the names that phpunit uses for auto-detecting or they are not in the working directory, phpunit will start without loading a configuration file and just execute what it can find in the directory with the default suffix "Test.php".
(In Phpstorm the working directory can vary when invoking Phpunit, even between runs of the same action, but that just as a comment.)
What you can do in Phpstorm: Configure the Phpunit configuration file to load. A good way to do that is to specify a default Phpunit configuration file in Settings -> PHP -> Test Frameworks in the Test Runner Section for Default configuration file.
Another thing is to specify the working directory explicitly in either the run action you already created which does not do what you want or by modifying the Phpunit run action template. Here a screenshot for the template:
A way to check the effectiveness is to make use of a bootstrap file in configuration and make it explode. Then you know whether or not something was effective.
Also PHpunit normally writes out the name of the configuration file if one is in use.

What is .phpunit.result.cache

When I run tests with PhpUnit on a new package I'm creating for Laravel, it generates the file .phpunit.result.cache.
What to do with that? Do I add it to my .gitignore file or not?
I'm using PHPUnit 8.0.4
This file helps PHPUnit remember which tests previously failed, which can speed up your testing flow if you only re-run failed tests during development. This is useful for test-driven workflows in which you have configured tests to run automatically, such as on file save, and the same collection of tests is being run repeatedly.
It is also a good idea to add the cache file .phpunit.result.cache to
your .gitignore so that it does not end up being committed to your
repository.
https://laravel-news.com/tips-to-speed-up-phpunit-tests
If you would prefer not to generate the file then you can run phpunit with the --do-not-cache-result option, as pointed out by #Slack Undertow in the comments. This might be desired when running tests as part of a build pipeline, for example. Or, as #codekandis pointed out, the same option is available as the cacheResult attribute in phpunit.xml.
You can also change this file location by editing phpunit.xml:
<phpunit
...
cacheResultFile="../.temp/fs_cache/.phpunit.result.cache"
>
Or completely disable it by
<phpunit
...
cacheResult ="false"
>
Official PHPUnit explanation (I currently don't find any other useful official details).
This caching is required for certain other features to work.
You can disable it with:
<phpunit
...
cacheResult="false">

Is there any difference in naming the PHPunit configuration file phpunit.xml.dist or phpunit.xml

Can someone explain to me what is the difference between using PHPunit configuration files named phpunit.xml.dist or phpunit.xml.
The official documentation mentions both names:
PHPUnit's XML configuration file (Appendix C) can also be used to compose a test suite. Example 5.1 shows a minimal phpunit.xml file that will add all *Test classes that are found in *Test.php files when the tests directory is recursively traversed.
with giving phpunit.xml a higher priority when loading configuration without the configuration parameter.
If phpunit.xml or phpunit.xml.dist (in that order) exist in the current working directory and --configuration is not used, the configuration will be automatically read from that file.
I did find some questions (e.g. is this .xml.dist file really required to be used) relating to the fact, that .dist files usually are used as a template (distribution) which should be copied to a version without the .dist ending to activate them (e.g. .htaccess.dist). But this seems not to be the case with PHPunit as it picks up and runs the dist file as well. Other questions (Can I use phpunit.xml for credentials and phpunit.xml.dist for testsuites?) seem to deal with other weird usage ideas about these two files.
In the Symfony world, it is mandatory for reusable bundles to include a phpunit.xml.dist file and I wonder why not a phpunit.xml file instead.
A test suite must not contain AllTests.php scripts, but must rely on the existence of a phpunit.xml.dist file.
So if anyone can shed some light onto this I would be happy ;-)
If phpunit.xml or phpunit.xml.dist (in that order) exist in the current working directory and --configuration is not used, the configuration will be automatically read from that file.
The idea behind the fallback (to phpunit.xml.dist when phpunit.xml does not exist) is that phpunit.xml.dist can be checked into version control and phpunit.xml can be ignored from version control. This allows a developer to use a custom configuration without running the risk of accidentally checking it into version control.
File .dist are versioned with git for example and you usually don't version phpunit.xml because is a configuration file of your machine.
File .dist are often configuration files which do not contain the real-world deploy-specific parameters
If there is phpunit.xml and phpunit.xml.dist phpunit takes phpunit.xml
phpunit.xml.dist It's a standard file, phpunit.xml It's a customization and aren't versioned to avoid publishing personal data

PHPUnit configuration (phpunit.xml) -- loading in a bootstrap?

Situation
We're using PHPUnit in our project and are using a phpunit.xml to ensure things like backupGlobals is turned off.
To further ensure the include path is set and autoloading is active, we also cascade our test bootstraps. That is to say, every test and alltests-suite has a require_once(__DIR__ . '/../bootstrap.php'); at the top, all the way up to the base folder level, where it obviously reads require_once(__DIR__ . '/bootstrap.php');, and the actual bootstrap file resides.
Essentially, our tests are autonomous. You can call any AllTests.php in any folder and any *Test.php by itself and they'll run with the right configuration.
Except no. 'Wait a moment.'
That's only true if we either force our developers to use phpunit --configuration=path/to/phpunit.xml or they're in the folder with the phpunit.xml (so that PHPUnit pulls it out of the current working directory when it is executed).
Occasionally, this makes it incredibly hard to determine why tests on one developer's machine are breaking and why they're running on another. It just takes forgetting that the bootstrap is not the only thing we need to have the same test environment. Keep in mind that since you couldn't forget the bootstrap if you tried, because it's in the tests themselves, forgetting other settings, especially usually-optional ones like that (if you're in the folder with the phpunit.xml, it's automatically pulled), is easy.
In fact - it's happened a few times.
Question
Is there a way I can supply which phpunit.xml to use in the test file being run, such as in our conveniently ubiquitous bootstrap file, rather than supplying it to PHPUnit beforehand, be that by command-line switch or by being in its directory ?
A cursory glance at the code suggests the answer is no - configuration well and truly seems to be loaded before test files are even pulled:
[PHPUnit/TextUI/Command.php]
...
if (isset($this->arguments['configuration'])) {
$configuration = PHPUnit_Util_Configuration::getInstance(
$this->arguments['configuration']
);
$phpunit = $configuration->getPHPUnitConfiguration();
...
That does make some sense, given that the configuration can contain test white- or blacklists.
Really, it wouldn't make sense to load test filters in the test bootstrap itself, so that's half the potential configuration out the window with, but the actual behavioural flags of PHPUnit...
[sample of part of our phpunit.xml]
<phpunit
backupGlobals="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
syntaxCheck="false"
processIsolation="false"
colors="true">
...perhaps with the exception of 'colors' strikes me as something that the test itself should be able to decide on some level.
Consolation prize for...
Admittedly, right now I'd be happy just knowing if I can teach PHPUnit backupGlobals="false" from the bootstrap file, if someone knows of a way.
(If fruitless, the practical answer I'll pursue will probably be to copy the phpunit.xml into all subfolders. I'd like to avoid that solution since it creates redundant copies, and if we ever choose to change a setting... yeah, ouch!)
Direct answer: No, you cant do that.
Longer story - this kind of problem is better solved by changing the habits of developers.
Here is we do it:
All developers always run the tests from the tests root directory, which has the sole phpunit.xml with all the necessary configuration - including bootstrap, which sets up an class autoloader.
We dont have testsuites as such, tests are grouped using directories, no AllTests.php anywhere, because its not necessary. PHPUnit can take a name of directory and run all tests inside it.
Its still possible to run any single test by giving a path to it or whole testsuite (by giving path to the directory). It just has to be done from the tests root directory all the time or it wont work.
Doing it like this means giving up the freedom of starting PHPUnit from any directory, but to be honest - I dont feel like thats a loss at all.
The gains are much bigger: the amount of housekeeping code is reduced, developers cannot forget anything and results are therefore consistent.
My solution is to add a bash function
function phpu ()
{
phpunit --colors --bootstrap ~/path/to/bootstrap.php "$#";
}
Then add this to all dev .bashrc files and they can switch to using that.
We like to call them from vim so I had to add this to .vimrc: set shellcmdflag=-ic
Then you add nmap ;t :! phpu % to run the test file you're currently in.
You could update the start script (Windows bat file, or shell on *nix) and have logic in there to configure to the location of the phpunit.xml. If it is in the current directory, use it, otherwise point to the main one.
I also agree with Anti though, that all the tests should always be run, as you want to ensure that the changes, even in a directory branch, do not affect other code. Therefore, always run from the top of the tree. This also requires that the test execute quickly, but I have not really had a problem with PHPUnit on that.
Maintaining the PHPUnit.xml in each directory would be a maintenance nightmare, unless is was symbolically linked from other paths to ensure there was only one actual file.

Categories