Problem/Motivation
Follow-up to #2114823: Update PHPUnit to 4.x
The update to PHPUnit 4 moved the phpunit executable to a different location:
/core/vendor/bin/phpunit
However, the update was performed on a Linux platform, so the phpunit executable installed by Composer is not the executable for Windows.
The above is just a *nix link to phpunit's main shell script:
/core/vendor/phpunit/phpunit/phpunit
...which also happens to work on Windows.
Proposed resolution
Use phpunit from the vendor folder instead of the one if Composer's bin directory, which does not work when extracted from a tarball and generally not on Windows.
Remaining tasks
RBTC
User interface changes
None.
API changes
None.
Data model changes
None.
Original report
Follow-up to #2114823: Update PHPUnit to 4.x
The update to PHPUnit 4 moved the phpunit executable to a different location:
/core/vendor/bin/phpunit
However, the update was performed on a Linux platform, so the phpunit executable installed by Composer is not the executable for Windows.
The above is just a *nix link to phpunit's main shell script:
/core/vendor/phpunit/phpunit/phpunit
...which also happens to work on Windows.
Attached patch
- fixes the phpunit script command location
- removes the error suppression for reading the JUnit XML result file, as it only hides an early error condition that blows up later on anyway.

| Comment | File | Size | Author |
|---|---|---|---|
| #63 | 2294731-2-63.patch | 1.79 KB | alexpott |
| #63 | 61-63-interdiff.txt | 716 bytes | alexpott |
| #61 | interdiff.txt | 568 bytes | david_garcia |
| #61 | 2294731-60.patch | 1.56 KB | david_garcia |
| #59 | interdiff.patch | 579 bytes | droplet |
Comments
Comment #2
berdirThe same is true on *nix platforms when you download a tar.gz, because there vendor/bin/phpunit is no longer a symlink and then the relative path to find autoload.php fails
Comment #3
sun@Berdir: True. But at the same time, /core/vendor/bin is most likely not within your PATH, so the malformed binary link/file isn't used by anyone.
umph. We're using error-suppression to make tests pass?
Not sure how to resolve that. What's the point of that test? Delete it?
Comment #4
sunAlright, let's shortcut this:
Comment #5
sunLet's move forward here?
Comment #6
anavarreI found this issue when I was about to file a new one for what I believe to be the same issue. Please correct me if I'm wrong.
On Linux, running
./vendor/bin/phpunitonly works from a Git checkout and not from within a codebase extracted from a tarball. To temporarily fix the issue, you have to do the following from within the vendor/bin directory:$ wget http://getcomposer.org/composer.phar && touch composer.jsonAdd the below lines to your new composer.json file:
Then run:
$ php composer.phar installObviously, now that I know this is related to a wrong symlink it all makes more sense to me. I did try to apply #4 on a fresh tarball (from July, 9th) and it unfortunately didn't help.
Did I miss anything?
Comment #7
sun@anavarre: Can you clarify what exactly did not work for you?
After applying this patch, the (Drupal) test runner should be able to run PHPUnit tests; i.e., the following should work:
(alternatively, use the UI to run a PHPUnit test; same code path)
The
/core/vendor/bin/phpunitscript/link/file is not changed or "fixed" in any way by this patch. Instead, the file is not used anymore.Comment #8
anavarreI didn't experience any issue with run-tests.sh and was under the impression that this issue was addressing problems with vendor/bin/phpunit only?
What exactly is not working for me is running PHPUnit tests (as described here) from an extracted tarball while it works flawlessly from within a 8.x git clone.
In the above testing scenario, I don't have the patch applied and it fails immediately from within a tarball and succeeds with a git checkout.
Comment #9
sunThe
./core/vendor/bin/phpunitdoes not and cannot work when being extracted from a tarball (nor on Windows), because it is a symlink.The symlink points to the actual PHP script
./core/vendor/phpunit/phpunit/phpunit.run-tests.shworks for you (in a git clone), because you're on Linux (in which case the test runner executes the symlink).This patch removes all usages of that symlink and makes all scripts execute the target of the symlink instead.
I wasn't aware of the drupal.org PHPUnit handbook page. Of course, that needs to be updated after this fix has been committed.
With this patch applied, PHPUnit can be executed under all circumstances. However, you have to execute
./core/vendor/phpunit/phpunit/phpunit(instead of./core/vendor/bin/phpunit).Comment #10
berdirWhich is sad, because we have been documenting and communicating the other for a long time now and it only broke with PHPUnit 4 AFAIK.
The only reason it breaks in the tarball is because the relative path inside is is no longer correct. It's already checking in two locations, would be easy to add a third.
IMHO, this is a bug in PHPUnit and should be fixed there, either by not using a symlink for this in a first place and/or fixing the path where it looks for autoload.php.
And run-tests.sh is a *very* crappy DX for running unit tests, it's slow, has no filter possibilities or any of the other useful arguments and the output is much worse, so we really shouldn't suggest to use that for unit tests.
Comment #11
sunThe symlink will still not work on Windows though, because *nix symlinks are not understood by Windows. (Not even Cygwin understands them.)
That breaks the Simpletest UI, run-tests.sh, as well as extracted tarballs (as you rightfully pointed out yourself).
The sudden change in
./core/vendor/bin/phpunitis caused by two independent changes of upstream libraries: (1) Composer changed how + where binaries are generated + supplied recently. (2) PHPUnit 4 has been completely refactored to use Composer + instruct Composer to auto-generate a binary symlink to the actual phpunit CLI script.For all platforms, the drupal.org handbook page for running PHPUnit tests should IMO be changed into the following:
Instructs a globally installed phpunit to consume a
phpunit.xml[.dist]file from the./core/directory, which is guaranteed to load./core/tests/bootstrap.phponly. This command also boots the rest of PHPUnit from Drupal's committed version.Developers who are not able to install PHPUnit globally should use the Simpletest UI. Alternatively, they can manually execute:
However, most of that is off-topic for this issue. Are there any concrete issues with the trivial patch here or can we move forward? :)
The d.o handbook pages can be updated after the fact only.
Comment #12
anavarreThanks for the clarification, now I understand the confusion. I don't want to hold up this patch either and we can update the documentation afterwards.
It's only a pity (as in less elegant) that
./core/vendor/bin/phpunitbe replaced with./core/vendor/phpunit/phpunit/phpunitbut we can live with it :-)Comment #17
sunCan we move forward here?
Currently have to apply this patch in order to debug weird fatal errors that only occur in the simpletest → phpunit code path (for #2260121: PHPUnit Tests namespace of modules is ambiguous with regular runtime namespace (+ Simpletest tests))
Comment #19
mile23core/vendor/phpunit/phpunit/phpunitwill always be a canonical location for the PHPUnit binary.bin/just saves some typing, and lets you have a place for PATH to use.The work-around is to delete
core/vendor/and then docomposer installwhenever you download Drupal and want to run tests.I'd say this issue demands some attention, but I don't have Windows and can't review the patch.
Comment #20
daffie commentedMaybe this will help: #2036705: Drupal 8 doesn't work well on WAMP stack.
Comment #21
daffie commentedOr maybe this will help: #2389287: Missing PhpExecutableFinder.
Comment #22
hass commentedThe patch no longer applies.
Every unit test I'm running ends with "No test results to display." There is no change with this patch applied. Does this have any installation requirements in XAMPP?
Comment #23
daffie commentedComment #24
dawehner@hass
The only sane way to run the phpunit tests are using the command line.
Comment #25
Ketan Harit commentedComment #26
daffie commentedFor the testbot to work.
Comment #27
sivaji_ganesh_jojodae commentedComment #28
othermachines commentedPatch no longer applies. Bummer. I would attempt to reroll but I'm really not sure what's going on here.
Comment #29
mikeker commentedRerolled.
Comment #34
othermachines commentedThis is great, thanks! I'll definitely test, just need to find a moment.
Comment #35
mikeker commented@othermachines, If you could figure out why SimpleTestBrowserTest is failing, that would be wonderful! I haven't had time to look into that failure yet and Windows-only (ok, not technically correct in this case) bugs don't get a lot of attention from the rest of the crowd.
Thanks!
Comment #36
othermachines commentedI've swapped the params in join() which should (hopefully!) take care of it.
Comment #39
othermachines commentedWell, there. I didn't know join() could accept args in any order. But I'm pretty certain we don't need an implode *and* a join. Do we need to change this line? SimpletestPhpunitRunCommandTest passes if we leave it as is. Err, that's good right?
As for
SimpleTestBrowserTestthe rest of it, beats me. Right now all I'm getting is an internal server error and a mess to clean up afterwards. Argh.Comment #40
othermachines commentedI'm pretty sure
$retshould contain an integer, not the last line of the output, which is what you get with$ret = exec(join(" ", $command), $output);.I can't test this locally at the moment but I'm curious to know if it will pass.
Comment #41
othermachines commentedComment #42
mikeker commentedYes, I believe I added that in #29 in what can only be described as a total reroll failure! Clearly working too late... :(
Thanks for continuing to work on this -- I'll be able to review your last patch in the morning.
Comment #43
othermachines commentedWell, terrific. With latest patch I can now run PHPUnit tests via UI on Windows. To be on the safe side I ran the same tests from the command line and they all sync up.
Comment #44
mikeker commentedSorry, haven't had the time to test the latest patch... Regardless, the issue summary needs and update and beta eval, which would help folks who are starting to look at this issue.
Potentially needs docs update as per #9 with much of that @sun mentions in #11, though I'm not sure what @sun says in #11 is what we want to use as our default way to run phpunit. As clunky as it is
cd core; ./vendor/phpunit/phpunit/phpunit ...is the only guaranteed way. Anyhow, though I through that out there in case someone disagrees.Comment #45
david_garcia commentedThere are other serveral thing broken with simpletest. Adding related and/or possible duplicate issue.
#2605284: Testing framework does not work with contributed database drivers
Comment #46
hongpong commentedThe symlink wouldn't clone in an OSX 10.10 environment when I was working with vdd Vagrant setup virtualizing Linux. I filed a bug here. It's easy enough to fix by making a link manually but enough a problem to be worth filing a bug. #2659650: Cloning Drupal 8.0.x head: unable to create symlink vendor/bin/phpunit (Protocol error)
Comment #49
dawehnerGiven that we use composer now to deal with the dependencies I guess this is no longer an actual issue.
Comment #50
mikeker commented(removing beta eval tag since we're no longer in beta...)
Sorry, @dawehner, I wish that were the case but running PHPUnit tests via the Simpletest UI still fails on Windows because it calculates the wrong path the PHPUnit executable:
Without the patch:
With the patch:
Note that on Windows (and maybe other platforms -- haven't had a chance to investigate and update docs) one needs to set their PHP_PATH environment variable to the PHP executable they want to use. It could be considered in-scope for this issue to have a better error message if this is not set. (Currently fails with a blank error.)
Comment #51
mile23Re-uploading #40 for the new testbot.
Are you sure it's the PHP binary and not a problem finding the PHPUnit executable?
If so, it's similar to this: #2476139-17: Fix UI test fail in SimpleTestBrowserTest
Comment #52
mikeker commentedYeah, pretty sure. When I was stepping through the code it was the
PhpExecutableFinderthat was failing to return an valid php.exe. In other words,would return null.
Comment #53
david_garcia commentedComment #54
generalredneck@mikeker
What you are experiancing is part of #2748883: Use the PHP_BINARY constant in addition to --php in run-tests.sh
Comment #55
david_garcia commentedWith the latest patch, tests properly run from both UI and run-tests.sh
Comment #56
alexpottIf we call this variable command then we don't need the else below. So the result code is simpler. Less logic to stare at and wonder what is going on.
Comment #57
alexpottLike so.
Comment #59
droplet commentedTested on Cli & UI.
Comment #60
david_garcia commentedWhy are we running the PHP executable through escapeshelllargs?
This breaks the fact that the PHP executable ($php) itself can have arguments. It's not just the executable.
I.e:
$php = "c:\tools\php\php.exe";
or
$php = "c:\tools\php\php.exe -c \"c:\myscutomphp.ini\""
Current escapeshellargs on $php will break second usage.
Comment #61
david_garcia commentedThis should do it. BTW, @droplet, great find about --printer argument breaking autolading.
Comment #62
david_garcia commentedTests not working on an OS that has > 80% desktop market share should be Major.
Comment #63
alexpottJust a tidy clean up of how we're getting the classname.
Comment #64
othermachines commentedLost track of this issue, nice to see it moving forward. FWIW tests pass for me from UI and CLI with #63 applied (8.4.x branch). Cheers and thx -
Comment #65
alexpottCommitted and pushed 41eda3b to 8.4.x and ec943f0 to 8.3.x. Thanks!
Comment #68
xjmThis is also worth mentioning in the testing improvements in the release notes/changelog, I think.