Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class not found #3889

Closed
longmayar opened this issue Oct 9, 2019 · 17 comments
Closed

Class not found #3889

longmayar opened this issue Oct 9, 2019 · 17 comments
Labels
type/backward-compatibility Something will be/is intentionally broken type/bug Something is broken

Comments

@longmayar
Copy link

Q A
PHPUnit version 8.4.0
PHP version 7.2.23
Installation Method Composer

Summary

Trying to start test, got 'Process finished with exit code 0' with trace:
Class 'Tests\Service\ClassTest' could not be found in '/tests/Service/ClassTest.php'

Previous Behavior

It works in 8.3.5

Current Behavior

It's broken it 8.4.0

How to reproduce

Run test

@longmayar longmayar added type/backward-compatibility Something will be/is intentionally broken type/bug Something is broken labels Oct 9, 2019
@sebastianbergmann
Copy link
Owner

Thank you for your report.

Please provide a minimal, self-contained, reproducing test case that shows the problem you are reporting.

Without such a minimal, self-contained, reproducing test case I will not be able to investigate this issue.

@sebastianbergmann sebastianbergmann added status/waiting-for-feedback Waiting for feedback from original reporter and removed type/backward-compatibility Something will be/is intentionally broken labels Oct 10, 2019
@sebastianbergmann
Copy link
Owner

Also please try with PHPUnit 8.4.1 and see if your problem still exists.

@sirn-se
Copy link

sirn-se commented Oct 10, 2019

EDIT: Found the issue. The reason is that the test class name did not exactly match the file name in which the test class is written. This mismatch was allowed in earlier versions, but causes a class load error in 8.4.*.

Not an issue with PHPUnit really, although behavior has changed.

Original post below;


Same problem for me with 8.4.1, backed to 8.3.5 which works. Running PHP 7.3.5.

Only backtrace for now, will look into it later.

Uncaught PHPUnit\Runner\Exception: Class 'MyTest' could not be found in 'project/tests/MyTest.php'.

PHPUnit\Runner\StandardTestSuiteLoader->load(…) in project/include/deps/phpunit/phpunit/src/Runner/BaseTestRunner.php, line 141
PHPUnit\Runner\BaseTestRunner->loadSuiteClass(…) in project/include/deps/phpunit/phpunit/src/Runner/BaseTestRunner.php, line 101
PHPUnit\Runner\BaseTestRunner->getTest(…) in project/include/deps/phpunit/phpunit/src/TextUI/Command.php, line 177
PHPUnit\TextUI\Command->run(…) in project/include/deps/phpunit/phpunit/src/TextUI/Command.php, line 159
PHPUnit\TextUI\Command::main() in project/include/deps/phpunit/phpunit/phpunit, line 61

@dmlogic
Copy link

dmlogic commented Oct 10, 2019

I have the same issue going from 8.3.5 => 8.4.1. I suffix my tests with ".test.php" and make use of <directory suffix=".test.php"> in phpunit.xml.

In 8.3.5 I could run a test directly with ./vendor/bin/phpunit tests/path/to/Class.test.php. In 8.4.1 this gives the following error:

PHP Fatal error:  Uncaught PHPUnit\Runner\Exception: Class 'Class.test.php' could not be found in '/project/path/tests/path/to/Class.test.php'. in /project/path/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php:69
Stack trace:
#0 /project/path/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php(141): PHPUnit\Runner\StandardTestSuiteLoader->load('Class.t...', '/project/path/dir...')
#1 /project/path/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php(101): PHPUnit\Runner\BaseTestRunner->loadSuiteClass('tests/client-lm...', '/project/path/dir...')
#2 /project/path/vendor/phpunit/phpunit/src/TextUI/Command.php(177): PHPUnit\Runner\BaseTestRunner->getTest('tests/client-lm...', '/project/path/dir...', Array)
#3 /project/path/vendor/phpunit/phpunit/src/TextUI/Command.php(159): PHPUnit\TextUI\Command->run(Array, true)
#4 /project/path/vendor/phpunit/phpunit/phpunit(61): PHPUnit\TextUI\ in /project/path/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php on line 69

Fatal error: Uncaught PHPUnit\Runner\Exception: Class 'Class.test.php' could not be found in '/project/path/tests/path/to/Class.test.php'. in /project/path/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php:69
Stack trace:
#0 /project/path/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php(141): PHPUnit\Runner\StandardTestSuiteLoader->load('Class.t...', '/project/path/dir...')
#1 /project/path/vendor/phpunit/phpunit/src/Runner/BaseTestRunner.php(101): PHPUnit\Runner\BaseTestRunner->loadSuiteClass('tests/client-lm...', '/project/path/dir...')
#2 /project/path/vendor/phpunit/phpunit/src/TextUI/Command.php(177): PHPUnit\Runner\BaseTestRunner->getTest('tests/client-lm...', '/project/path/dir...', Array)
#3 /project/path/vendor/phpunit/phpunit/src/TextUI/Command.php(159): PHPUnit\TextUI\Command->run(Array, true)
#4 /project/path/vendor/phpunit/phpunit/phpunit(61): PHPUnit\TextUI\ in /project/path/vendor/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php on line 69

@sebastianbergmann
Copy link
Owner

CC @flow-control

@realFlowControl
Copy link
Sponsor Contributor

Hey @sirn-se and @dmlogic,

could you provide me the class names in your files? I will then create a test for these and try to fix the regression.

/Flo

@dmlogic
Copy link

dmlogic commented Oct 10, 2019

An example for a file tests/MyTest.test.php would be:

<?php

use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    /**
     * @test
     */
    public function my_sample_test()
    {
        $this->assertTrue(true);
    }
}

and the testsuite would be defined in phpunit.xml as:

<testsuite name="sample">
    <directory suffix=".test.php">./tests</directory>
</testsuite>

I use this approach as I sometimes need php includes in the tests folders and don't want them to be considered tests

@sirn-se
Copy link

sirn-se commented Oct 10, 2019

File tests/MyLoadTest.php

<?
class LoadTest extends PHPUnit\Framework\TestCase
{
    // Doesn't matter, will not be loaded to begin with
}

Obviously class and file name doesnt't match, but before it ran anyway. @flow-control

realFlowControl added a commit to realFlowControl/phpunit that referenced this issue Oct 10, 2019
realFlowControl added a commit to realFlowControl/phpunit that referenced this issue Oct 10, 2019
@realFlowControl
Copy link
Sponsor Contributor

I fixed that in #3891 by restoring a few lines i removed in #3830

I like to add, that naming your test class FooTest while naming the file MyFooTest.php seems not intentionally supported (at least to my knowledge), but possible due to another feature.

If the runner can not find a class with the name of the file (minus suffix) it checks all classes loaded from the given test file for not being abstract and being a subclass of PHPUnit\Framework\TestCase. Therefore, not intentionally (at least to my knowledge) you can name your test class whatever you like ;-)

@sebastianbergmann
Copy link
Owner

@flow-control Can you please send a pull request that reverts #3891 (after I have merged it)? I would like to schedule that for PHPUnit 9 as I agree that this should not be supported.

@sebastianbergmann sebastianbergmann added type/backward-compatibility Something will be/is intentionally broken and removed status/waiting-for-feedback Waiting for feedback from original reporter labels Oct 10, 2019
@dmlogic
Copy link

dmlogic commented Oct 10, 2019

I fixed that in #3891

Thank you!

Therefore, not intentionally (at least to my knowledge) you can name your test class whatever you like

Understood

I would like to schedule that for PHPUnit 9 as I agree that this should not be supported

@sebastianbergmann does this mean I will be able to continue using a .test.php suffix for 8.x but not for 9.x?

@realFlowControl
Copy link
Sponsor Contributor

realFlowControl commented Oct 10, 2019

Hey @dmlogic,

calling the test directly as you stated above with ./vendor/bin/phpunit tests/path/to/Class.test.php is at this moment only possible due to the loader checking on every class in that file. The suffix option and the --test-suffix command line switch at this moment are only used to find files if you are giving phpunit a directory and not a file. So calling ./vendor/bin/phpunit --test-suffix .test.php tests/path/to/ should do the trick, but then again this will execute all other *.test.php test files aswell.

Calling the test file directly as you did will not be possible when reverting this pull request in version 9. What's your opinion on that @sebastianbergmann?

/Flo

@dmlogic
Copy link

dmlogic commented Oct 10, 2019

Sounds like I need to move from ClassName.test.php to ClassNameTest.php. I find the former a lot clearer when scanning over large numbers of files, which is why I started doing it. But it's not that big-a-deal.

thanks for your help.

realFlowControl added a commit to realFlowControl/phpunit that referenced this issue Oct 11, 2019
sebastianbergmann pushed a commit that referenced this issue Oct 12, 2019
@nicoder
Copy link

nicoder commented Jun 16, 2020

is this described in the breaking changes?

I could not find it and we will have many test classes to rename

(especially in older tests before namespaces were introduced,

where for example we would have a class named Tests_PHPUnit_Lib_DatesTest in a DatesTest.php file)

(not a problem, but it would be nice to mention it in the breaking changes if it is not already the case)

@realFlowControl
Copy link
Sponsor Contributor

Hey there 🖖

this is stated in https://github.com/sebastianbergmann/phpunit/blob/9.1.0/ChangeLog-9.1.md at the bottom:

#4105: Deprecate multiple test case classes in single file and test case class name differing from filename

Maybe this could help you prepare for PHPUnit 10: https://github.com/rectorphp/rector/blob/master/docs/rector_rules_overview.md#pseudonamespacetonamespacerecto

Hope I could help

/Flo

@nicoder
Copy link

nicoder commented Jun 25, 2020

thanks a lot Flo, it did help.

(I looked at the 9.0 changelog on the website and tried to find more on master,

I did see a changelog for 8.5, 9.2 and 9.3, but not 9.1,

and did not think to look at the tags)

@stronk7
Copy link
Contributor

stronk7 commented Feb 19, 2021

Hi,

was planning our upgrade to 9.5.x when I saw these 2 lovely details in the PHP 9.1 release notes:

Basically this is going to "destroy" us. We both use a custom loader and custom naming. I'm sure there are good reasons to start adding all those restrictions, but they, specially together, will kill any other naming schema completely.

For example, we call to our files: xxxx_test.php (using the _test.php suffix when defining suites), and to the corresponding test case core_xxxx_testcase (where core, can be, instead, the name of plugins for tests belonging to them, for example mod_forum or anything else). And the files are under the "tests" directories of each of the plugins (or core).

And we know where our tests are because the plugin defines it (and our custom loader knows about the structure).

With this changes we are forced to call to the files like the testcases, which is horrible and also, all our custom loader abilities are gone.

We "only" have 1146 test cases in core (files to rename that will make specially hard to backport things), but also have some good hundreds of plugins from 3rd parties, each one with their own test cases following the same schema.

And everything has worked perfectly since we switched to PHPUnit, some good years ago.

Note I'm not asking to reconsider the decision to increase the restrictions (although I must confess that I don't understand the "need" to do so) but, at very least, make it more prominent in current documentation, because phpunit 10 will bee too late for such a surprising and drastic change!

Just my 2 cents, ciao :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/backward-compatibility Something will be/is intentionally broken type/bug Something is broken
Projects
None yet
Development

No branches or pull requests

7 participants