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

  1. fixes the phpunit script command location
  2. 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.

Comments

Status: Needs review » Needs work

The last submitted patch, test.phpunit-windows.0.patch, failed testing.

berdir’s picture

The 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

sun’s picture

@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.


Drupal\simpletest\Tests\PhpUnitErrorTest::testPhpUnitXmlParsing

file_get_contents(foobar): failed to open stream: No such file or directory

/var/lib/drupaltestbot/sites/default/files/checkout/core/modules/simpletest/simpletest.module:818
/var/lib/drupaltestbot/sites/default/files/checkout/core/modules/simpletest/tests/src/PhpUnitErrorTest.php:52

Other PhpUnitErrorTest.php 29 Drupal\simpletest\Tests\PhpUnitErrorTest->testPhpUnitXmlParsing()

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?

sun’s picture

Title: Simpletest fails to locate PHPUnit binary on Windows » Simpletest fails to run PHPUnit on Windows and in extracted tarballs of Drupal
Status: Needs work » Needs review
StatusFileSize
new1.56 KB

Alright, let's shortcut this:

  1. Use the phpunit PHP script instead of the Composer binary in all cases.
  2. Revert and ignore the error-suppression issue for now (separate issue).
sun’s picture

Let's move forward here?

anavarre’s picture

I 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/phpunit only 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.json

Add the below lines to your new composer.json file:

{
    "require": {
        "phpunit/phpunit": "4.1.*",
        "phpunit/phpunit-mock-objects": "dev-master#e60bb929c50ae4237aaf680a4f6773f4ee17f0a2"
    }
}

Then run:

$ php composer.phar install

Obviously, 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.

$ curl https://www.drupal.org/files/issues/test.phpunit-windows.4.patch | git apply -v
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1600  100  1600    0     0   1792      0 --:--:-- --:--:-- --:--:--  1791
Checking patch core/modules/simpletest/simpletest.module...
Hunk #1 succeeded at 287 (offset 46 lines).
Hunk #2 succeeded at 300 (offset 46 lines).
Applied patch core/modules/simpletest/simpletest.module cleanly.

Did I miss anything?

sun’s picture

@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:

$ php ./core/scripts/run-tests.sh [...] --class Drupal\Tests\SomePHPUnitTest

(alternatively, use the UI to run a PHPUnit test; same code path)

The /core/vendor/bin/phpunit script/link/file is not changed or "fixed" in any way by this patch. Instead, the file is not used anymore.

anavarre’s picture

I 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.

$ for i in tarball head ; do echo ========== ; cd /var/www/html/$i/core && ./vendor/bin/phpunit ; done
==========
You need to set up the project dependencies using the following commands:
wget http://getcomposer.org/composer.phar
php composer.phar install
==========
PHPUnit 4.1.3 by Sebastian Bergmann.

Configuration read from /var/www/html/head/core/phpunit.xml.dist

.............................................(snipped)

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.

sun’s picture

The ./core/vendor/bin/phpunit does 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.sh works 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).

berdir’s picture

Which 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.

sun’s picture

The 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/phpunit is 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:

$ phpunit -c core [...]

Instructs a globally installed phpunit to consume a phpunit.xml[.dist] file from the ./core/ directory, which is guaranteed to load ./core/tests/bootstrap.php only. 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:

ln -s ./core/vendor/phpunit/phpunit/phpunit

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.

anavarre’s picture

Thanks 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/phpunit be replaced with ./core/vendor/phpunit/phpunit/phpunit but we can live with it :-)

sun queued 4: test.phpunit-windows.4.patch for re-testing.

sun queued 4: test.phpunit-windows.4.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 4: test.phpunit-windows.4.patch, failed testing.

Status: Needs work » Needs review

sun queued 4: test.phpunit-windows.4.patch for re-testing.

sun’s picture

Can 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))

sun queued 4: test.phpunit-windows.4.patch for re-testing.

mile23’s picture

core/vendor/phpunit/phpunit/phpunit will 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 do composer install whenever 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.

daffie’s picture

daffie’s picture

Or maybe this will help: #2389287: Missing PhpExecutableFinder.

hass’s picture

Status: Needs review » Needs work

The 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?

daffie’s picture

Issue tags: +Needs reroll
dawehner’s picture

@hass
The only sane way to run the phpunit tests are using the command line.

Ketan Harit’s picture

StatusFileSize
new1.57 KB
daffie’s picture

Status: Needs work » Needs review

For the testbot to work.

sivaji_ganesh_jojodae’s picture

Issue tags: -Needs reroll
othermachines’s picture

Status: Needs review » Needs work

Patch no longer applies. Bummer. I would attempt to reroll but I'm really not sure what's going on here.

mikeker’s picture

Status: Needs work » Needs review
StatusFileSize
new1.57 KB

Rerolled.

Status: Needs review » Needs work

The last submitted patch, 29: 2294731-29-phpunit-windows.patch, failed testing.

The last submitted patch, 29: 2294731-29-phpunit-windows.patch, failed testing.

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 29: 2294731-29-phpunit-windows.patch, failed testing.

othermachines’s picture

This is great, thanks! I'll definitely test, just need to find a moment.

mikeker’s picture

@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!

othermachines’s picture

Status: Needs work » Needs review
StatusFileSize
new1.57 KB

I've swapped the params in join() which should (hopefully!) take care of it.

Status: Needs review » Needs work

The last submitted patch, 36: 2294731-36-phpunit-windows.patch, failed testing.

The last submitted patch, 36: 2294731-36-phpunit-windows.patch, failed testing.

othermachines’s picture

Well, 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 SimpleTestBrowserTest the rest of it, beats me. Right now all I'm getting is an internal server error and a mess to clean up afterwards. Argh.

othermachines’s picture

StatusFileSize
new1.17 KB

I'm pretty sure $ret should 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.

othermachines’s picture

Status: Needs work » Needs review
mikeker’s picture

But I'm pretty certain we don't need an implode *and* a join. Do we need to change this line?

Yes, 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.

othermachines’s picture

StatusFileSize
new307.91 KB

Well, 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.

Testing PHPUnit screenshot

mikeker’s picture

Sorry, 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.

david_garcia’s picture

There are other serveral thing broken with simpletest. Adding related and/or possible duplicate issue.

#2605284: Testing framework does not work with contributed database drivers

hongpong’s picture

The 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)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

Status: Needs review » Fixed

Given that we use composer now to deal with the dependencies I guess this is no longer an actual issue.

mikeker’s picture

Title: Simpletest fails to run PHPUnit on Windows and in extracted tarballs of Drupal » Simpletest fails to run PHPUnit on Windows
Status: Fixed » Needs review
Issue tags: -Needs beta evaluation
StatusFileSize
new20.99 KB
new10.24 KB

(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.)

mile23’s picture

Issue summary: View changes
StatusFileSize
new1.17 KB

Re-uploading #40 for the new testbot.

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.

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

mikeker’s picture

Are you sure it's the PHP binary and not a problem finding the PHPUnit executable?

Yeah, pretty sure. When I was stepping through the code it was the PhpExecutableFinder that was failing to return an valid php.exe. In other words,

+++ b/core/modules/simpletest/simpletest.module
@@ -310,17 +310,18 @@ function simpletest_phpunit_command() {
     $php = $php_executable_finder->find();

would return null.

david_garcia’s picture

Issue summary: View changes
generalredneck’s picture

david_garcia’s picture

Version: 8.2.x-dev » 8.3.x-dev
Status: Needs review » Reviewed & tested by the community

With the latest patch, tests properly run from both UI and run-tests.sh

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs issue summary update
+++ b/core/modules/simpletest/simpletest.module
@@ -310,17 +310,18 @@ function simpletest_phpunit_command() {
+  $phpunit = $vendor_dir . '/phpunit/phpunit/phpunit';
   if (substr(PHP_OS, 0, 3) == 'WIN') {
...
   else {
-    $phpunit_bin = $vendor_dir . '/phpunit/phpunit/phpunit';
+    $command = $phpunit;
   }
-  return $phpunit_bin;
+  return $command;

If 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.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new993 bytes
new1.22 KB

Like so.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

droplet’s picture

StatusFileSize
new1.57 KB
new579 bytes

Tested on Cli & UI.

david_garcia’s picture

Why are we running the PHP executable through escapeshelllargs?

+ $command = escapeshellarg($php) . ' -f ' . escapeshellarg($command) . ' --';

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.

david_garcia’s picture

StatusFileSize
new1.56 KB
new568 bytes

This should do it. BTW, @droplet, great find about --printer argument breaking autolading.

david_garcia’s picture

Priority: Normal » Major

Tests not working on an OS that has > 80% desktop market share should be Major.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new716 bytes
new1.79 KB

Just a tidy clean up of how we're getting the classname.

othermachines’s picture

Lost 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 -

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 41eda3b to 8.4.x and ec943f0 to 8.3.x. Thanks!

  • alexpott committed 41eda3b on 8.4.x
    Issue #2294731 by alexpott, othermachines, sun, droplet, mikeker,...

  • alexpott committed ec943f0 on 8.3.x
    Issue #2294731 by alexpott, othermachines, sun, droplet, mikeker,...
xjm’s picture

Version: 8.4.x-dev » 8.3.x-dev
Assigned: sun » Unassigned
Issue tags: +8.3.0 release notes

This is also worth mentioning in the testing improvements in the release notes/changelog, I think.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.