Problem/Motivation
Follow up to #3129043: Move core database drivers to modules of their own and to #3230714-11: ConnectionUnitTest should be skipped for any database not psql or mysql:
Once #3129043: Move core database drivers to modules of their own is complete, it would be good to split the Database tests in 'core' ones and 'driver specific' ones, with the 'driver specifc' ones running dependent on the db driver in use by the SUT.
Proposed resolution
At the moment we have 4 possible solutions:
1: From the MR. Split Database tests in 'core' ones and 'driver specific' ones for the kerneltests in Drupal\KernelTests\Core\Database only. For most contrib database drivers this is enough, only for the one for MongoDB this is not the case.
2: No patch/MR. Move the core/phpunit.xml.dist file to the root of the database driver module and let every module with a database driver have its own phpunit.xml.dist. Use that file for the testbot and in that file the tests that must be skipped for the module can be added to the file. The Drupal testbot must be changed for this to work. The advantage is that all tests can be overridden.
3: From the patch (comment #18): Change the class Drupal\Core\Test\TestDiscovery, so that the method
getTestClasses() only returns the tests that need to be run. It skips the tests from the modules with a database driver that is not fromthe active database connection. The script run-tests.sh will need to be changed a bit and the option "--list" will need the "--dburl" to have it return the correct list of test classes.
4: From the patch (coomment #19): The method Drupal\KernelTests\KernelTestBase::setUp() now has code that skips tests that are from module with a database driver that is not from the active database connection and it skips tests that have been overridden by the module with the databse driver that is used in the active database connection. It only works for kerneltests, but the same solution can also be used for browsertests.
This issue implements option #1.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #67 | interdiff_57-67.txt | 820 bytes | pradhumanjain2311 |
| #67 | 3231950-67.patch | 58.12 KB | pradhumanjain2311 |
| #62 | interdiff_61-62.txt | 595 bytes | pradhumanjain2311 |
| #62 | 3231950-62.patch | 48.9 KB | pradhumanjain2311 |
| #61 | interdiff_57-61.txt | 572 bytes | pradhumanjain2311 |
Issue fork drupal-3231950
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3231950-split-database-tests
changes, plain diff MR !1593
Comments
Comment #2
mondrakeThis can be started also in 9.3 already, provided that #3129043: Move core database drivers to modules of their own happens. See a PoC here, built on top of #3129043: Move core database drivers to modules of their own. This would split
ConnectionUnitTestkernel test in 3 tests classes, one with a method relevant for core, then one for MySql and one for PostgreSql.Comment #3
daffie commentedI do not think that extending a test from another database driver is going to work, because when we are running the testbot for PostgreSQL the mysql module will NOT be enabled.
I like the idea of making the base test class abstract and letting each driver override that abstract class in a way that is best for the driver. Or not override at all when they do not want to use the test. Good idea!
Comment #4
mondrake#3 I think it works - at least my tests seem to: https://github.com/mondrake/d8-unit/actions/runs/1217939693
In kernel tests as long as the class is autoloadable, it does not matter the module to be installed.
Comment #5
mondrakeComment #7
mondrakeI am working on this.
Comment #9
mondrakeReady for review - this only moves tests for the
@group Database- other may be moved but I'd leave that for other issues after this one has been done.DrupalCI does not report currently skipped tests (see #2905007: Allow run-tests.sh to report skipped/incomplete PHPUnit tests), you can see locally the new
DriverSpecificDatabaseTestBaseclass in action withvendor/bin/phpunit -v -c core --color=always --group=DatabaseIn a test run with an Sqlite based SUT, the MySql tests will skip with
Comment #10
mondrakeComment #11
mondrakeComment #12
daffie commented@mondrake: Thank you for working on this.
To me this a good solution for the by core supported database drivers.
I am not sure how it is for contrib database drivers. If I have some core test that will not pass for my contrib database driver and that test is not extending DriverSpecificDatabaseTestBase, then I will have a problem. I will need to create a patch that will change the test to one that is extending DriverSpecificDatabaseTestBase and add for each by core supported database driver a new test (with a comment that it is needed for a contrib database driver). It works, only the idea that I will need to get a patch to land in core, just so that I can override a core test is to me a bit hmmm. It is not how overriding core should be.
My preference would be to place a phpunit.xml.dist file in every database drivers module and let the testbot use that instead of the one in the core directory. Each phpunit.xml.dist file can then add element to skip the tests in the other 2 by core supported database driver modules and also skip any other test it need to and replace it by its own version.
Contrib database drivers can place phpunit.xml.dist in their module. They will need to exclude the 3 by core supported database driver modules and add any other core test they want to override. No need to patch core.
We can write a test that will keep the different versions of the phpunit.xml.dist files in sync (with the exception of the element). Just as the as the core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ScaffoldTest.php does for the files core/assets/scaffold/files/default.settings.php and sites/default/default.settings.php.
To me, this is more the way the PHP community would expect it to be fixed. Feel free to disagree.
Comment #13
mondrakeYes, I disagree. To me, the 'core' tests should ideally be driver-abstract, and test the Database API regardless of what is the real DBMS under the hood. If contrib cannot match an API behaviour, then either a) the API is not abstract enough, and therefore core should change or b) contrib should try to adjust to support. Or, c) core should not make an API of it and demote to driver-specific. There's no easy way, I know, but for me it's stellar to adhere to the concept of abstract API.
Swapping the phpunit configuration file to manage different backends seems to me awkward, and would require DrupalCI infra changes. doctrine/dbal does have separate phpunit.xml per backend, but that's to provide test credentials for the DBMS spinned up, and actually ALL the tests are run on every workflow run, then tests are skipped if not relevant for the SUT's DBMS. Here we are doing the same.
Comment #14
daffie commentedI took some time to think about your solution in this issue. The problem is that for my MongoDB database driver it is just not enough. Let me give some examples:
(int)to make the test also pass for MongoDB?For MongoDB is just allowing the test in Drupal\KernelTests\Core\Database just not enough. Maybe splitting the tests in 'core' tests and 'driver specific' ones works when it is part of a larger solution. Sorry.
Comment #15
mondrakeLooks like your problem in #14 is to run Database API tests on a non-SQL backend... which is not the scope of this issue (and, yes, I'm pretty certain they do not and most likely will never work - can your MongoDB database driver be installed as a inplace replacement of a core db driver?).
This issue's scope is just moving some of the Database API tests (i.e. those marked
@group Database) around. If a test can only pass on a specific driver, what's the reason to keep it in the core namespaces?Comment #16
daffie commentedI am afraid that when we do this your way (@mondrake), then it will work for all contrib databse driver with the exception of the one for MongoDB. And for MongoDB will it never be solved.
Comment #17
daffie commentedThis patch has a different approach for overriding tests by the module that is proving the current database driver. The Drupal testbot uses the script
core/scripts/run-tests.sh. That script uses the classcore/lib/Drupal/Core/Test/TestDiscovery.phpto create the list of tests that need to be run. I have made some modifications to that class to exclude the test from the database modules that not providing the current database driver. Also only the module that is providing the current database driver can override tests with the annotation "overrideTastClass".The problem with the current patch is that the testbot is failing with;
Comment #18
daffie commentedShould fix it for the testbot.
Comment #19
daffie commentedThe method
Drupal\KernelTests\KernelTestBase::setUp()now has code that skips tests that are from module with a database driver that is not from the active database connection and it skips tests that have been overridden by the module with the databse driver that is used in the active database connection. This solution is is a mix between the solution #1 and #3.Comment #20
mondrakeI'm still not very convinced @daffie, this still seems some sort of magic where if you place a class with a specific name in a module, then you disable running another test class somewhere else.
Can I suggest we split off moving the unit tests to a separate issue? I think that's not controversial and would make reviewing the patch here simpler.
Wouldn't it be better to
implodethe relevant remaining parts rather than hardcoding the offset?The comments on what's happening are not very clear.
if we have a contrib database driver module in the codebase and run all the tests, then other db drivers (include core) will run the tests of the contrib driver, no? And we don't want that.
Comment #21
mondrakeFiled #3260227: Move driver specific database Unit tests to their modules
Comment #22
daffie commented@mondrake: Thank you for reviewing my patch. Hopefully the new patch makes it more clear how it works.
I have removed the UnitTests and moved the code in KernelTestBase::setUp() to its own method.
For #20.1: Fixed.
For #20.2: I did my best to improve them.
For #20.3: Yes, this is something we need to support, only we need #3256642: Introduce database driver extensions and autoload database drivers' dependencies for that. My suggestion is to that in a followup.
Comment #23
daffie commentedThe missing interdiff file.
Comment #24
daffie commentedComment #26
mondrakeRebased the MR onto 9.5.x
Comment #27
mondrakeAs discussed in slack, let's focus this issue on splitting core tests in a way that those that are specific to only a subset of the database drivers supported by core, can be moved to the appropriate module namespaces.
And have a separate issue to discuss how to enable custom/contrib db drivers to run core tests when needed.
Comment #28
daffie commented@mondrake: Let go for your solution.
Comment #29
mondrakeThanks @daffie. Let's wait for #3260007: Decouple Connection from the wrapped PDO connection to allow alternative clients to get in, too, so we can also move testPrepareStatementFailOnExecution() to the pgsql and mysql modules only.
Comment #30
daffie commented#3260007: Decouple Connection from the wrapped PDO connection to allow alternative clients has landed.
Comment #31
mondrakeOn this.
Comment #32
mondrakeThanks @daffie for the inline comments in the MR.
Before moving further, a conceptual thing I think we need to discuss - IMHO we should do this only for kernel tests, and only for tests of the
@group Database.If a non-db test (kernel or functional) needs to skip or switch depending on the db driver, that would smell like our DB API need to be fixed not being 'abstract' enough. In other words, if the test does that, probably it's the runtime code that behaves differently on the driver under the hood, and that means that core would potentially not be compatible with non-core drivers. In that case, I think we should strive to fix the API rather than giving the testing framework ways to workaround. Yes, it's for SQL db-drivers only, but I think that support for non-SQL drivers is a totally different story.
Comment #33
daffie commentedAs far as this issue is concerned, yes lets do that.
Some of the tests in that category are extending
DataBaseTestBaseand some are extendingKernelTestBase. Can we make the baseDriverSpecificKernelTestBaseextendKernelTestBaseand haveDriverSpecificDatabaseTestBaseextendDriverSpecificKernelTestBase. To do that we can/need to move the DatabaseTestBase table creations and the sample data to a trait. We can than removed the new class variable$installSchemaAndData.+1 for this solution. Not sure if this solution will work for every SQL-database driver. I also think that some of the Database API testing is done in tests that are outside of the directory
core/tests/Drupal/KernelTests/Core/Databaseand/or @group Database, but that is another problem.Comment #34
mondrakeLet's do then. On it. Thanks @daffie.
Comment #35
mondrakeMoved the reusable code to a trait as suggested by @daffie.
Comment #36
daffie commentedI have refactored the MR a bit to get rid of the variable
$installSchemaAndData.For the rest does it look great.
Comment #37
mondrakeI was not very convinced on the need of a
DriverSpecificKernelTestBase, but this makes sense.I'm RTBCing since I cannot see who else would.
This issue is doing what it says in the title, using option 1 from the list of options in the IS.
Comment #39
mondrakeComment #40
joegraduateRe-rolled patch from #36 against current 9.5.x branch.
Comment #41
daffie commentedThe reroll in comment #40 looks good to me.
Now we need a version for D10.0 and D10.1.
Back to needs work.
Comment #42
mondrakeA D10 patch
Comment #43
mondrakeComment #44
mondrakePHPStan found quite some stuff in the 9.5 patch. So I am retargeting 10.1 first, and we'll backport in case.
Comment #45
mondrakeFix
Comment #46
mondrakeComment #47
daffie commentedThe version for D10.0 and D10.1 looks good to me.
Back to RTBC.
Comment #48
daffie commented@mondrake: In your D10.0 patch you have created 2 traits called DatabaseTestSchemaDataTrait and DatabaseTestSchemaInstallTrait. The 9.5 version only has the trait InstallDatabaseTestSchemaAndDataTrait. Could you update either one, so that they both do the same thing. Or explain why you made them different.
Comment #49
mondrakeSee the test failure in #42.
PHPStan is quite right here,
installSchema()is not defined for functional tests. So, we need the sample data adding in both kernel and functional tests (one trait), and the schema install in two kernel base tests (the other trait).Let's backport to 9.5 only once we have cleared out the D10.0 and D10.1 are ok, if you don't mind. Too much effort to try and keep many versions in sync.
Comment #50
daffie commented@mondrake: Thank you for the explanation.
Back to RTBC.
For the comitter: The patch for D9.5 has the trait InstallDatabaseTestSchemaAndDataTrait and the patch for D10.X has the traits DatabaseTestSchemaDataTrait and DatabaseTestSchemaInstallTrait. I leave it up to you to determine if the difference is acceptable or that it must be the same for both patches.
Comment #51
alexpottCommitted and pushed d755c76eb1 to 10.1.x and 8d8b24055f to 10.0.x. Thanks!
So we need to backport the changes talked about in #48/#49 to the 9.5.x version (might even got for 9.4.x given this is all test related).
Please make sure the patch passes on PHP 7.3 as I see some things in the 10.x patch that require a higher PHP version.
Comment #54
mondrakeHere's a new 9.5 patch
Comment #55
mondrakeComment #56
daffie commentedTestbot is not happy
Comment #57
anchal_gupta commentedfix cs error. Please review it
Comment #58
alexpottComment #59
daffie commentedThe patch for D9.5 looks good to me.
Comment #60
alexpottNeeds to pass on PHP7.3
Comment #61
pradhumanjain2311 commentedFix
PHP Parse error: syntax error, unexpected 'Connection' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST) in /var/www/html/core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php on line 20. Needs Review
Comment #62
pradhumanjain2311 commentedChecking core/modules/system/tests/src/Functional/Database/DatabaseTestBase.php
FILE: ...odules/system/tests/src/Functional/Database/DatabaseTestBase.php
----------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
----------------------------------------------------------------------
5 | WARNING | [x] Unused use statement
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY.
Fix unused use statement.
Comment #64
daffie commentedTestbot is failing.
Comment #65
pradhumanjain2311 commentedHi @daffie @alexpott
i m new to contribution would you please guide how to solve this error
ERROR: PHP Fatal error: Trait "Drupal\KernelTests\Core\Database\DatabaseTestSchemaDataTrait" not found in /var/www/html/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php on line 14
Comment #66
daffie commented@pradhumanjainOSL: The patch for D10.0 is adding 2 traits and they are not in your patch for D9.5 (DatabaseTestSchemaDataTrait and DatabaseTestSchemaInstallTrait). Please look carefully how it is done in the patch for D10.0.
Comment #67
pradhumanjain2311 commented@daffie Thanks for your guidance.
But i fix the patch now please review and apologies.
Comment #69
daffie commentedThe D9.5 looks good to me.
It passes the testbot for all by 3 by core supported databases.
It passes the testbot for PHP7.3 and PHP8.0.
For me it is RTBC.
Comment #70
alexpottCommitted b855673 and pushed to 9.5.x. Thanks!