A database module for Codeception.
PHP 8.0
or higher.
composer require "codeception/module-db" --dev
Codeception Module DB
is open-sourced software licensed under the MIT License.
© Codeception PHP Testing Framework
DB module for Codeception
License: MIT License
A database module for Codeception.
PHP 8.0
or higher.composer require "codeception/module-db" --dev
Codeception Module DB
is open-sourced software licensed under the MIT License.
© Codeception PHP Testing Framework
When I have a table with a primary key column that's also increment, it's valid to set it to null
on the insert statement. the last insert it will then return the auto increment value, which is the primary key in that case.
As already noticed in #44, the auto increment column doesn't have to be part of the primary key, so the return value of last insert id ironically doesn't necessarily belong to the primary key. However, #44 also broke the case, which one might perceive as more common, that the last insert id may also be the primary key.
So, haveInDatabase(table, ['id' => null, ...])
with id as autoincrement and pk will lead to the id being set to null
for cleanup, which results in the row not being removed at teardown.
I have prepared a fix for this case, which hopefully is specific enough to not interfere with other use cases.
I'm trying to use Docker to run module-db tests locally.
Steps to reproduce:
docker compose up -d
docker exec -it module-db-php81-1 bash -c "composer install"
docker exec -it module-db-php81-1 bash -c "php vendor/bin/codecept run unit Codeception/Module/Db/MySqlDbTest:testGrabColumnFromDatabase -vvv""
Output has error:
[PDOException] SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for host.docker.internal failed: Name or service not known
Console output with -vvv
mode:
Codeception PHP Testing Framework v5.0.10 https://helpukrainewin.org
actor is empty
Unit Tests (1) --------------------------------------------------------------------------------------------------------------------------------------------------------------
Modules:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
E MySqlDbTest: Grab column from database(0.08s)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Time: 00:00.110, Memory: 12.00 MB
There was 1 error:
1) MySqlDbTest: Grab column from database
Test tests/unit/Codeception/Module/Db/MySqlDbTest.php:testGrabColumnFromDatabase
[PDOException] SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for host.docker.internal failed: Name or service not known
/var/www/html/src/Codeception/Lib/Driver/Db.php:83
/var/www/html/src/Codeception/Lib/Driver/Db.php:58
/var/www/html/tests/unit/Codeception/Module/Db/AbstractDbTest.php:22
/var/www/html/vendor/codeception/codeception/src/PHPUnit/TestCase.php:10
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:2085
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:2027
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:626
/var/www/html/vendor/codeception/codeception/src/Codeception/Test/TestCaseWrapper.php:148
/var/www/html/vendor/codeception/codeception/src/Codeception/Test/Test.php:170
/var/www/html/vendor/codeception/codeception/src/Codeception/Suite.php:130
/var/www/html/vendor/codeception/codeception/src/Codeception/SuiteManager.php:148
/var/www/html/vendor/codeception/codeception/src/Codeception/Codecept.php:260
/var/www/html/vendor/codeception/codeception/src/Codeception/Codecept.php:216
/var/www/html/vendor/codeception/codeception/src/Codeception/Command/Run.php:435
/var/www/html/vendor/symfony/console/Command/Command.php:326
/var/www/html/vendor/symfony/console/Application.php:1063
/var/www/html/vendor/symfony/console/Application.php:320
/var/www/html/vendor/symfony/console/Application.php:174
/var/www/html/vendor/codeception/codeception/src/Codeception/Application.php:112
/var/www/html/vendor/codeception/codeception/app.php:45
/var/www/html/vendor/codeception/codeception/app.php:46
/var/www/html/vendor/codeception/codeception/codecept:7
/var/www/html/vendor/bin/codecept:120
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
composer show
)behat/gherkin dev-master 01379b1 Gherkin DSL parser for PHP
codeception/codeception 5.0.x-dev ed4af7f BDD-style testing framework
codeception/lib-asserts 2.1.0 Assertion methods used by Codeception core and Asserts module
codeception/stub 4.1.0 Flexible Stub wrapper for PHPUnit's Mock Builder
myclabs/deep-copy 1.x-dev 928a96f Create deep copies (clones) of your objects
nikic/php-parser 4.x-dev 0ffddce A PHP parser written in PHP
phar-io/manifest dev-master 36d8a21 Component for reading phar.io manifest information from a PHP Archive (PHAR)
phar-io/version 3.2.1 Library for handling version information and constraints
phpunit/php-code-coverage dev-main 913f51a Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator dev-main 83f6271 FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker dev-main 5994330 Invoke callables with a timeout
phpunit/php-text-template dev-main 9914010 Simple template engine.
phpunit/php-timer dev-main fe67739 Utility class for timing
phpunit/phpunit dev-main b79f52f The PHP Unit Testing framework.
psr/container dev-master 90db7b9 Common Container Interface (PHP FIG PSR-11)
psr/event-dispatcher dev-master e275e2d Standard interfaces for event handling.
psy/psysh dev-main 6c8c0fd An interactive shell for modern PHP.
sebastian/cli-parser dev-main 9215d45 Library for parsing CLI options
sebastian/code-unit dev-main 362736b Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup dev-main cd740da Looks up which function or method a line of code belongs to
sebastian/comparator dev-main 5d09783 Provides the functionality to compare PHP values for equality
sebastian/complexity dev-main 27d3bd5 Library for calculating the complexity of PHP code units
sebastian/diff dev-main 2c9aad8 Diff implementation
sebastian/environment dev-main 54b3f6e Provides functionality to handle HHVM/PHP environments
sebastian/exporter dev-main d6e9b3c Provides the functionality to export PHP variables for visualization
sebastian/global-state dev-main 3b3c08e Snapshotting of global state
sebastian/lines-of-code dev-main a1e716d Library for counting the lines of code in PHP source code
sebastian/object-enumerator dev-main ac568e5 Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector dev-main 4bf3974 Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context dev-main 8343512 Provides functionality to recursively process PHP variables
sebastian/type dev-main 1a33327 Collection of value objects that represent the types of the PHP type system
sebastian/version dev-main a7fa65c Library that helps with managing the version number of Git-hosted PHP projects
symfony/console 6.3.x-dev 2655810 Eases the creation of beautiful and testable command line interfaces
symfony/css-selector 6.3.x-dev 88453e6 Converts CSS selectors to XPath expressions
symfony/deprecation-contracts dev-main e2d1534 A generic function and convention to trigger deprecation notices
symfony/event-dispatcher 6.3.x-dev 3aa5237 Provides tools that allow your application components to communicate with each other by dispatching events and lis...
symfony/event-dispatcher-contracts dev-main 0ad3b6f Generic abstractions related to dispatching event
symfony/finder 6.3.x-dev f5891f0 Finds files and directories via an intuitive fluent interface
symfony/polyfill-ctype dev-main ea208ce Symfony polyfill for ctype functions
symfony/polyfill-intl-grapheme dev-main 875e90a Symfony polyfill for intl's grapheme_* functions
symfony/polyfill-intl-normalizer dev-main 8c4ad05 Symfony polyfill for intl's Normalizer class and related functions
symfony/polyfill-mbstring dev-main f9c7aff Symfony polyfill for the Mbstring extension
symfony/service-contracts dev-main a8c9ced Generic abstractions related to writing services
symfony/string 6.3.x-dev 0120462 Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unif...
symfony/var-dumper 6.3.x-dev efc8f5d Provides mechanisms for walking through any arbitrary PHP variable
symfony/yaml 6.3.x-dev 55071ed Loads and dumps YAML files
theseer/tokenizer 1.2.1 A small library for converting tokenized PHP source code into XML and potentially other formats
Hello! I have in my postgres DB table with 1 serial column (id) and not able to insert a row into this table in my test. I could insert a row into any other table that has more than 1 column, but not into the table that has the only id column. Is it possible, maybe with another method?
Based on PDO documentation lastInsertId can be string|false
, but Codeception\Lib\Driver\Db::lastInsertId
has a string
return value, so tables without auto increment field could fail with type error. Tried to upgrade using MS SQL Server in my tests.
Probably a simple cast to string could solve the issue, but not sure if it has any implications on other code.
hi
Could you please create the tag for 3.1.1 from master?
Looks like the tag is missing, I assume it is a core problem for many users, since we use just tagged package (enterprise policy, I think it's not unique.)
For example it is missing from 3.1.0 tag but in master branch:
#48
thank you.
best regards,
selyem
I tested a composer dev-2.0 version and noted a decreased performance caused by
"require": {
"codeception/codeception": "*@dev"
}
I don't know where the benefit of this is when it is still paired with a <4.0 conflict but can't this be replaced by "4.*@dev" with the same result but better performance?
The problem is that many packages earlier codeception versions require (including symfony) are included in the process to find the correct version of each package. The conflict attribute seems to have effect just very late.
There are existing different variation of configurations in the codeception sub-packages:
This is a suggestion for a new function that waits for a value to appear in the database.
That would be helpful for many engineers in order to reduce actual needs of using explicit waiting when running tests.
In the example below, the actual waiting time (0.5 seconds) could also be an argument and many more improvements that you guys could think of :)
Thanks for reading and for your great work!
Proof of concept:
/**
* Waits for a certain value to appear in the database.
*
* @param string $expectedValue Expected value to be used in assertion.
* @param string $table DB Table.
* @param string $field Field of db table.
* @param array $criteria Criteria for db query.
* @param int $maxNumberOfRetries Maximum number of retries.
*
* @throws Exception
*/
public function waitForValueInDb( $expectedValue, $table, $field, $criteria, $maxNumberOfRetries = 10 ) {
$actualValue = null;
for ( $i = 0; $i <= $maxNumberOfRetries; $i++ ) {
$actualValue = $this->grabFromDatabase( $table, $field, $criteria );
if ( $actualValue !== false ) {
continue;
}
$this->wait( 0.5 );
}
$this->assertEquals( $expectedValue, $actualValue, "Expected value wasn't matched with the actual one fetched from db." );
}
http=>https
While testing a REST API I found myself needing an entire entry from the database to make sure my GET /table/«id»
was implemented correctly.
However, I just found a method to retrieve a field from the database, not an entire entry.
As I'm not experienced with testing yet I would like to know some opinions about implementing a grabEntryFromDatabase
method in the Db module, so we can use it to get pure information from the db and then use that to test what the system is doing.
Currently I'm using my own models to get the needed information, but this is the same the API is doing and the test is almost redundant...
Also, if there's any better practice on this, please let me know (:
module-db/src/Codeception/Lib/Driver/Db.php
Line 348 in 1858892
This new addition broke all usages of haveInDatabase of null data for a certain column.
Example of fail:
$I->haveInDatabase('table_name', ['column_name' => null]);
Results in:
[TypeError] Codeception\Lib\Driver\Db::isBinary(): Argument #1 ($string) must be of type string, null given, called in /app/vendor/codeception/module-db/src/Codeception/Lib/Driver/Db.php on line 297
In src/Codeception/Lib/Driver/PostgreSql.php, the schema is hard-coded to "public" in method cleanup. In my setup, where the schema used for testing is not public, this causes tests to fail with a ModuleException:
[ModuleException] Db: SQLSTATE[42501]: Insufficient privilege: 7 ERROR: must be owner of schema public
The schema is taken into account in "load" method, and this should also be brought into cleaning up the test database.
composer show
)I have a problem when running unit tests using module-db
My tests pass when the are run individually, when I run them as a suite only the first test passes, but other tests fail.
My configurations are as follow:
- Db:
dsn: 'mysql:host=localhost;dbname=test'
user: 'root'
password: ''
dump: 'tests/_data/database/empty_db.sql'
populate: true # run populator before all tests
cleanup: true # run populator before each test
reconnect: true
populator: 'mysql -u $user -h $host $dbname < $dump'
skip_cleanup_if_failed: true,
initial_queries:
- 'CREATE DATABASE IF NOT EXISTS test;'
- 'USE test;'
and the output that I see on the screen is just normal:
[Connecting To Db] {"config":{"populate":true,"cleanup":false,"reconnect":true,"waitlock":0,"dump":"tests/_data/database/empty_db.sql","populator":"mysql -u $user -h $host $dbname < $dump","skip_cleanup_if_failed":true,"dsn":"mysql:host=localhost;dbname=test","user":"root","password":""},"options":[]}
[Db] Connected to default test
[Db] Executing Populator: `mysql -u root -h localhost test < tests/_data/database/empty_db.sql`
[Db] Populator Finished.
[Db] Disconnected from default
[Connecting To Db] {"config":{"populate":true,"cleanup":false,"reconnect":true,"waitlock":0,"dump":"tests/_data/database/empty_db.sql","populator":"mysql -u $user -h $host $dbname < $dump","skip_cleanup_if_failed":true,"dsn":"mysql:host=localhost;dbname=test","user":"root","password":""},"options":[]}
[Db] Connected to default test
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:19:13","Test note asasas 2010","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:08:38","Test note asasas 2001","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:08:13","Test note asasas 2","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 16:29:44","Test note asasas 1","M009"]
[Query] INSERT INTO `users` (`id`, `USER_CODE`, `radiususer`, `active`, `deleted`, `LEVEL_CODE`, `user_password`, `USER_NAME`, `USER_EMAIL`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["109","fsahli-notoken","iavasco:[email protected]",1,0,0,"pass","F. Sahli (Inter Act)","[email protected]"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_ADDRESS`, `LOC_POSTAL`, `LOC_CITY`, `LOC_COUNTRY`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["M009","M009","M009","10","","","","",1,"Koning Stadhouderlaan","MK_1AN_GPRS",0,0,"2014-02-27 08:53:40"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_POSTAL`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["P644","P644","P633","6","7381BL",1,"Hooiland 32","POWERLINE_PM",199649.5785,465711.177,"2014-02-27 08:53:40"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_POSTAL`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["P643","P643","P633","6","7381BL",1,"Hooiland 29","POWERLINE_PM",199819.791,465691.7586,"2014-02-27 08:53:40"]
[Query] INSERT INTO `department` (`DEPT_CODE`, `DEPT_DESC`, `LAST_CHANGE`) VALUES (?, ?, ?)
[Parameters] ["M009","Koning Stadhouderlaan","2014-02-27 08:53:40"]
[Query] INSERT INTO `department` (`DEPT_CODE`, `DEPT_DESC`) VALUES (?, ?)
[Parameters] ["P644","Hooiland 32"]
[Query] SELECT count(*) FROM `logbook`
[Query] SELECT count(*) FROM `users`
[Query] SELECT count(*) FROM `location`
[Query] SELECT count(*) FROM `department`
[Query] SELECT count(*) FROM `logbook` WHERE `USER_CODE` = ?
[Parameters] ["fsahli-notoken"]
+ NotePersistenceGetOneEntryTest: Get one entry (14.28s)
+ NotePersistenceTest: Test__construct (0.00s)
[Connecting To Db] {"config":{"populate":true,"cleanup":false,"reconnect":true,"waitlock":0,"dump":"tests/_data/database/empty_db.sql","populator":"mysql -u $user -h $host $dbname < $dump","skip_cleanup_if_failed":true,"dsn":"mysql:host=localhost;dbname=test","user":"root","password":""},"options":[]}
[Db] Connected to default test
[Db] Executing Populator: `mysql -u root -h localhost test < tests/_data/database/empty_db.sql`
[Db] Populator Finished.
[Db] Disconnected from default
[Connecting To Db] {"config":{"populate":true,"cleanup":false,"reconnect":true,"waitlock":0,"dump":"tests/_data/database/empty_db.sql","populator":"mysql -u $user -h $host $dbname < $dump","skip_cleanup_if_failed":true,"dsn":"mysql:host=localhost;dbname=test","user":"root","password":""},"options":[]}
[Db] Connected to default test
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:19:13","Test note asasas 2010","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:08:38","Test note asasas 2001","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 17:08:13","Test note asasas 2","M009"]
[Query] INSERT INTO `logbook` (`USER_CODE`, `LOGTIME`, `LOGTEXT`, `LOC_CODE`) VALUES (?, ?, ?, ?)
[Parameters] ["fsahli-notoken","2022-06-21 16:29:44","Test note asasas 1","M009"]
[Query] INSERT INTO `users` (`id`, `USER_CODE`, `radiususer`, `active`, `deleted`, `LEVEL_CODE`, `user_password`, `USER_NAME`, `USER_EMAIL`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["109","fsahli-notoken","iavasco:[email protected]",1,0,0,"pass","F. Sahli (Inter Act)","[email protected]"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_ADDRESS`, `LOC_POSTAL`, `LOC_CITY`, `LOC_COUNTRY`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["M009","M009","M009","10","","","","",1,"Koning Stadhouderlaan","MK_1AN_GPRS",0,0,"2014-02-27 08:53:40"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_POSTAL`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["P644","P644","P633","6","7381BL",1,"Hooiland 32","POWERLINE_PM",199649.5785,465711.177,"2014-02-27 08:53:40"]
[Query] INSERT INTO `location` (`LOC_CODE`, `display_code`, `DEPT_CODE`, `LOC_ZONE`, `LOC_POSTAL`, `LOC_ACTIVE`, `LOC_DESC`, `LOC_TYPE`, `LOC_XPOS`, `LOC_YPOS`, `LAST_CHANGE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[Parameters] ["P643","P643","P633","6","7381BL",1,"Hooiland 29","POWERLINE_PM",199819.791,465691.7586,"2014-02-27 08:53:40"]
[Query] INSERT INTO `department` (`DEPT_CODE`, `DEPT_DESC`, `LAST_CHANGE`) VALUES (?, ?, ?)
[Parameters] ["M009","Koning Stadhouderlaan","2014-02-27 08:53:40"]
[Query] INSERT INTO `department` (`DEPT_CODE`, `DEPT_DESC`) VALUES (?, ?)
[Parameters] ["P644","Hooiland 32"]
[Query] SELECT count(*) FROM `logbook`
[Query] SELECT count(*) FROM `users`
[Query] SELECT count(*) FROM `location`
[Query] SELECT count(*) FROM `department`
x NotePersistenceGetOneEntryTest: Get entries (15.06s)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Time: 00:29.374, Memory: 12.00 MB
There was 1 failure:
---------
1) NotePersistenceGetOneEntryTest: Get entries
Test tests\test_database\NotePersistenceGetOneEntryTest.php:testGetEntries
Failed asserting that actual size 0 matches expected size 4.
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\Constraint\Constraint.php:121
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\Constraint\Constraint.php:55
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\Assert.php:2344
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\Assert.php:286
D:\laragon\www\tcn\tests\test_database\NotePersistenceGetOneEntryTest.php:326
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\TestCase.php:1526
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\TestCase.php:1132
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\TestResult.php:722
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\TestCase.php:884
D:\laragon\www\tcn\vendor\phpunit\phpunit\src\Framework\TestSuite.php:677
D:\laragon\www\tcn\vendor\codeception\phpunit-wrapper\src\Runner.php:117
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\SuiteManager.php:161
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\Codecept.php:208
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\Codecept.php:162
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\Command\Run.php:609
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\Command\Run.php:442
D:\laragon\www\tcn\vendor\symfony\console\Command\Command.php:298
D:\laragon\www\tcn\vendor\symfony\console\Application.php:1024
D:\laragon\www\tcn\vendor\symfony\console\Application.php:299
D:\laragon\www\tcn\vendor\symfony\console\Application.php:171
D:\laragon\www\tcn\vendor\codeception\codeception\src\Codeception\Application.php:117
D:\laragon\www\tcn\vendor\codeception\codeception\app.php:46
D:\laragon\www\tcn\vendor\codeception\codeception\app.php:47
D:\laragon\www\tcn\vendor\codeception\codeception\codecept:6
D:\laragon\www\tcn\vendor\bin\codecept:112
FAILURES!
Tests: 3, Assertions: 23, Failures: 1.
[Db] Disconnected from default
[Db] Disconnected from default
can you please check and let me know
Best regards,
Firas
Hi,
I need a function to check, if a table exists in the database or not. Maybe it would be possible to extend the functions (dont)SeeInDatabase to do this with empty search parameters.
Thx
The call to $this->isBinary()
added in #48 broke a bunch of our tests that were passing float parameters with the following error
[TypeError] Codeception\Lib\Driver\Db::isBinary(): Argument #1 ($string) must be of type string, float given, called in /tmp/wordpress-latest/src/wp-content/plugins/crm/vendor/codeception/module-db/src/Codeception/Lib/Driver/Db.php on line 299
A fix might be to add an is_string()
check before the attempt to call $this->isBinary()
.
CC: @cybd @Arhell @Naktibalda
Currently we have configuration params cleanup
and skip_cleanup_if_failed
.
Despite their names sound similar, they are responsible for completely different things: cleanup
controls the database re-creation before each test, and skip_cleanup_if_failed
controls whether records, added by haveInDatabase()
should be erased after the test.
It would be good to distinguish these two 'cleanups' in documentation and in the names of config params in next major versions.
For example, to rename cleanup
to repopulate
(since we have populate
responsible for initial database creation).
Hello everyone,
When running my unit test I get an error message saying
[PHPUnit\Framework\Error\Notice] Undefined index: default
Is there a solution for this error?
This SQL use in dump:
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
`value` longtext COLLATE utf8mb4_unicode_520_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
LOCK TABLES `test` WRITE;
/*!40000 ALTER TABLE `test` DISABLE KEYS */;
INSERT INTO `test` VALUES (122,'test','//*');
/*!40000 ALTER TABLE `test` ENABLE KEYS */;
UNLOCK TABLES;
Hello
I insert data to db (PostgreSQL) whith DB module
$I->haveInDatabase("pictograms_tags_uk-UA",{"id":289,"tag_url_title":"Hello tag_url_title","description":"Hello description"})
have error
[PDOException] SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "pictograms_tags_uk-ua" does not exist
Provide console output if related. Use
-vvv
mode for more details.
# paste output here
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Lib/Driver/Db.php:307
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Lib/Driver/PostgreSql.php:161
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Module/Db.php:748
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Module/Db.php:722
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Step.php:266
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Scenario.php:72
/var/www/project-name/tests/_support/_generated/ApiTesterActions.php:4980
/var/www/project-name/tests/_support/Helper/TestHelper.php:156
/var/www/project-name/tests/_support/Helper/TestHelper.php:71
/var/www/project-name/tests/api/Dev/DevCest.php:48
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Lib/Di.php:127
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Test/Cest.php:138
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Test/Cest.php:147
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Test/Cest.php:82
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Test/Test.php:88
/var/www/project-name/vendor/phpunit/phpunit/src/Framework/TestSuite.php:746
/var/www/project-name/vendor/codeception/phpunit-wrapper/src/Runner.php:118
/var/www/project-name/vendor/codeception/codeception/src/Codeception/SuiteManager.php:158
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Codecept.php:193
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Codecept.php:160
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Command/Run.php:502
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Command/Run.php:397
/var/www/project-name/vendor/symfony/console/Command/Command.php:255
/var/www/project-name/vendor/symfony/console/Application.php:1011
/var/www/project-name/vendor/symfony/console/Application.php:272
/var/www/project-name/vendor/symfony/console/Application.php:148
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Application.php:107
/var/www/project-name/vendor/codeception/codeception/codecept:43
i use print_r in
/var/www/project-name/vendor/codeception/codeception/src/Codeception/Lib/Driver/Db.php:287
and see two query
first query:
[Query] INSERT INTO "pictograms_tags_uk-UA" ("id", "tag_url_title", "description") VALUES (?, ?, ?) [Parameters] [289,"Hello tag_url_title","Hello description"]
after this request comes the next
SELECT a.attname FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) WHERE i.indrelid = 'pictograms_tags_uk-UA'::regclass AND i.indisprimary
Actual result:
there is an error in the second request "SELECT"
This query use:
WHERE i.indrelid = 'pictograms_tags_uk-UA'::regclass
Expected Result
if table name contain sign "-"
need use double quotes
WHERE i.indrelid = "pictograms_tags_uk-UA"::regclass
The first request for insert was executed correctly, the data appeared in the table, but immediately after the second request an error occurs
composer show
)P.S. Sorry for my English...
Hi,
seems like the documentation for the 'cleanup' configuration option ist not correct:
cleanup: false - whether the dump should be reloaded before each test
It think more correct would be:
cleanup: false - whether all database tables should be dropped
I am not quite sure if this dropping happens once or before each test.
The docs mention the 'clearing' of the database, but not in connection with this option.
Make this more precise would be great!
Error message:
Error: Call to a member function inTransaction() on null in <PROJECT_DIR>/vendor/codeception/module-db/src/Codeception/Lib/Driver/Db.php on line 94
The error did not occur when using Codeception 4.
Maybe it has to do with a different order of PHP internally calling __destruct()
methods on objects.
I should note that the errors occur when running wp-browsers own test suite against Codeception 5 (Alpha). wp-browser extends the native Db
class, but does never call __destruct()
directly or set $dbh
to null
.
The following patch fixes that behavior:
diff --git a/src/Codeception/Lib/Driver/Db.php b/src/Codeception/Lib/Driver/Db.php
index b69017e..c83203c 100755
--- a/src/Codeception/Lib/Driver/Db.php
+++ b/src/Codeception/Lib/Driver/Db.php
@@ -91,7 +91,7 @@ class Db
public function __destruct()
{
- if ($this->dbh->inTransaction()) {
+ if ($this->dbh && $this->dbh->inTransaction()) {
$this->dbh->rollBack();
}
Might be related: Codeception/Codeception#5072
Specific timezone when use Db Model connect to mysql , then the test logic won't rely on database config.
Can't achieve this for now.
Provide console output if related. Use
-vvv
mode for more details.
# paste output here
Provide test source code if related
// paste test
composer show
)# paste suite config here
I'm using UUID as binary(16) in MySQL tables.
My test is failed when I'm trying to test seeInDatabase using UUID as filter criteria.
Test failed with error:
[JsonException] Malformed UTF-8 characters, possibly incorrectly encoded
php vendor/bin/codecept run unit Codeception/Module/Db/MySqlDbTest:testSeeInDatabaseWithBinary -vvv
Console output with -vvv
mode:
Codeception PHP Testing Framework v5.0.10 https://helpukrainewin.org
actor is empty
Unit Tests (1) --------------------------------------------------------------------------------------------------------------------------------------------------------------
Modules:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- MySqlDbTest: See in database with binary [Connecting To Db] {"config":{"populate":true,"cleanup":true,"reconnect":true,"waitlock":0,"dump":"tests/data/dumps/mysql.sql","populator":null,"skip_cleanup_if_failed":false,"dsn":"mysql:host=host.docker.internal;port=3102;dbname=codeception","user":"root","password":"codeception"},"options":[]}
[Db] Connected to default codeception
[Db] Disconnected from default
[Connecting To Db] {"config":{"populate":true,"cleanup":true,"reconnect":true,"waitlock":0,"dump":"tests/data/dumps/mysql.sql","populator":null,"skip_cleanup_if_failed":false,"dsn":"mysql:host=host.docker.internal;port=3102;dbname=codeception","user":"root","password":"codeception"},"options":[]}
[Db] Connected to default codeception
[Query] SELECT count(*) FROM `users` WHERE `uuid` = ?
[Parameters] ["u0011ufffdufffdKu0001ufffdrufffdufffdu001du0002Bufffdu0012u0000u0006"]
E MySqlDbTest: See in database with binary(0.19s)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Time: 00:00.213, Memory: 12.00 MB
There was 1 error:
1) MySqlDbTest: See in database with binary
Test tests/unit/Codeception/Module/Db/MySqlDbTest.php:testSeeInDatabaseWithBinary
[JsonException] Malformed UTF-8 characters, possibly incorrectly encoded
/var/www/html/src/Codeception/Module/Db.php:839
/var/www/html/tests/unit/Codeception/Module/Db/AbstractDbTest.php:69
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:1067
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:634
/var/www/html/vendor/codeception/codeception/src/Codeception/Test/TestCaseWrapper.php:148
/var/www/html/vendor/codeception/codeception/src/Codeception/Test/Test.php:170
/var/www/html/vendor/codeception/codeception/src/Codeception/Suite.php:130
/var/www/html/vendor/codeception/codeception/src/Codeception/SuiteManager.php:148
/var/www/html/vendor/codeception/codeception/src/Codeception/Codecept.php:260
/var/www/html/vendor/codeception/codeception/src/Codeception/Codecept.php:216
/var/www/html/vendor/codeception/codeception/src/Codeception/Command/Run.php:435
/var/www/html/vendor/symfony/console/Command/Command.php:326
/var/www/html/vendor/symfony/console/Application.php:1063
/var/www/html/vendor/symfony/console/Application.php:320
/var/www/html/vendor/symfony/console/Application.php:174
/var/www/html/vendor/codeception/codeception/src/Codeception/Application.php:112
/var/www/html/vendor/codeception/codeception/app.php:45
/var/www/html/vendor/codeception/codeception/app.php:46
/var/www/html/vendor/codeception/codeception/codecept:7
/var/www/html/vendor/bin/codecept:120
ERRORS!
Tests: 1, Assertions: 1, Errors: 1.
[Db] Disconnected from default
Provide test source code if related
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` binary(16) DEFAULT NULL,
`name` varchar(30) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`is_active` bit(1) DEFAULT b'1',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `users`(`id`,`uuid`, `name`,`email`, `is_active`,`created_at`) values (1,0x11edc34b01d972fa9c1d0242ac120006,'davert','[email protected]', b'1','2012-02-01 21:17:04');
public function testSeeInDatabaseWithBinary()
{
$this->module->seeInDatabase('users', ['uuid' => hex2bin('11edc34b01d972fa9c1d0242ac120006')]);
}
composer show
)root@400b115c4f29:/var/www/html# composer show
behat/gherkin dev-master 01379b1 Gherkin DSL parser for PHP
codeception/codeception 5.0.x-dev ed4af7f BDD-style testing framework
codeception/lib-asserts 2.1.0 Assertion methods used by Codeception core and Asserts module
codeception/stub 4.1.0 Flexible Stub wrapper for PHPUnit's Mock Builder
myclabs/deep-copy 1.x-dev 928a96f Create deep copies (clones) of your objects
nikic/php-parser 4.x-dev 0ffddce A PHP parser written in PHP
phar-io/manifest dev-master 36d8a21 Component for reading phar.io manifest information from a PHP Archive (PHAR)
phar-io/version 3.2.1 Library for handling version information and constraints
phpunit/php-code-coverage dev-main 489650a Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator dev-main 83f6271 FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker dev-main 5994330 Invoke callables with a timeout
phpunit/php-text-template dev-main 9914010 Simple template engine.
phpunit/php-timer dev-main fe67739 Utility class for timing
phpunit/phpunit dev-main 38f35a7 The PHP Unit Testing framework.
psr/container dev-master 90db7b9 Common Container Interface (PHP FIG PSR-11)
psr/event-dispatcher dev-master e275e2d Standard interfaces for event handling.
psy/psysh dev-main 6c8c0fd An interactive shell for modern PHP.
sebastian/cli-parser dev-main 9215d45 Library for parsing CLI options
sebastian/code-unit dev-main 362736b Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup dev-main cd740da Looks up which function or method a line of code belongs to
sebastian/comparator dev-main 5d09783 Provides the functionality to compare PHP values for equality
sebastian/complexity dev-main 27d3bd5 Library for calculating the complexity of PHP code units
sebastian/diff dev-main 2c9aad8 Diff implementation
sebastian/environment dev-main 54b3f6e Provides functionality to handle HHVM/PHP environments
sebastian/exporter dev-main d6e9b3c Provides the functionality to export PHP variables for visualization
sebastian/global-state dev-main 3b3c08e Snapshotting of global state
sebastian/lines-of-code dev-main a1e716d Library for counting the lines of code in PHP source code
sebastian/object-enumerator dev-main ac568e5 Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector dev-main 4bf3974 Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context dev-main 8343512 Provides functionality to recursively process PHP variables
sebastian/type dev-main 1a33327 Collection of value objects that represent the types of the PHP type system
sebastian/version dev-main a7fa65c Library that helps with managing the version number of Git-hosted PHP projects
symfony/console 6.3.x-dev 2655810 Eases the creation of beautiful and testable command line interfaces
symfony/css-selector 6.3.x-dev efc0747 Converts CSS selectors to XPath expressions
symfony/deprecation-contracts dev-main e2d1534 A generic function and convention to trigger deprecation notices
symfony/event-dispatcher 6.3.x-dev 7fa6112 Provides tools that allow your application components to communicate with each other by dispatching events and lis...
symfony/event-dispatcher-contracts dev-main 0ad3b6f Generic abstractions related to dispatching event
symfony/finder 6.3.x-dev f5891f0 Finds files and directories via an intuitive fluent interface
symfony/polyfill-ctype dev-main ea208ce Symfony polyfill for ctype functions
symfony/polyfill-intl-grapheme dev-main 875e90a Symfony polyfill for intl's grapheme_* functions
symfony/polyfill-intl-normalizer dev-main 8c4ad05 Symfony polyfill for intl's Normalizer class and related functions
symfony/polyfill-mbstring dev-main f9c7aff Symfony polyfill for the Mbstring extension
symfony/service-contracts dev-main a8c9ced Generic abstractions related to writing services
symfony/string 6.3.x-dev 599f0f0 Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unif...
symfony/var-dumper 6.3.x-dev 42237ee Provides mechanisms for walking through any arbitrary PHP variable
symfony/yaml 6.3.x-dev 55071ed Loads and dumps YAML files
theseer/tokenizer 1.2.1 A small library for converting tokenized PHP source code into XML and potentially other formats
This issue proposes the addition of PSR12 validation using PHPCS to improve the code quality and maintainability of the project.
By integrating PHPCS into the CI process, we can catch basic issues before they are merged into the master and we can ensure that all new contributions adhere to the PSR12 standard, leading to a cleaner and more maintainable codebase.
A helper runs code to modify the database in _beforeSuite
in order to add control rows before any tests are run.
The code crashes upon trying to run SQL as the connection has been terminated. This was new behaviour added by Codeception/Codeception@5e2c999
Easiest fix would be to create a public method on Db
to ensure that the connection is open before running code if config has reconnect. The quickest route would just be to make connect()
public.
composer show
) not relevant config:
Db:
dsn: 'mysql:host=localhost;dbname=XXXX;charset=utf8'
user: 'root'
password: ''
dump: 'tests/_data/schema.sql'
populate: true
cleanup: false
reconnect: true
Hi, found this little issue, I get an error when insert a row into a table that has NO sequence, one possible use case - it could happen with UUID as primary key that are generated on an application side, so it's not completely imaginary case :)
I'm using postgres:15
, codeception/module-db
looks like version 3.1.0,
and for example I have a table (for simplicity, integer primary key, no sequence)
create table t
(
c integer not null primary key
);
Then I call \Codeception\Module\Db::haveInDatabase
($this->tester->haveInDatabase('t', ['c' => 1]);
) in my test and see in the console
[DB error] SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "t_c_seq" does not exist
Row is inserted, but after it is trying to extract last inserted ID and (cause it's not possible) it fails.
Happens here in \Codeception\Lib\Driver\PostgreSql::lastInsertId
public function lastInsertId(string $tableName): string
{
$sequenceName = $this->getQuotedName($tableName . '_id_seq');
$lastSequence = null;
try {
$lastSequence = $this->getDbh()->lastInsertId($sequenceName);
} catch (PDOException $exception) {
// in this case, the sequence name might be combined with the primary key name
}
if (!$lastSequence) {
$primaryKeys = $this->getPrimaryKey($tableName);
$pkName = array_shift($primaryKeys);
// next line we get an error
$lastSequence = $this->getDbh()->lastInsertId($this->getQuotedName($tableName . '_' . $pkName . '_seq'));
}
return $lastSequence;
}
And I guess technically that is not an error, because we never should be checking for a last inserted ID in those cases.
Not really sure how to better handle this case, maybe it is possible to add some additional checks before calling \Codeception\Lib\Driver\Db::lastInsertId
, trying to detect if a sequence for the given table even exists. If there are no sequence - no need to call \Codeception\Lib\Driver\Db::lastInsertId
maybe?
In that case I found this monster here https://dba.stackexchange.com/questions/260975/postgresql-how-can-i-list-the-tables-to-which-a-sequence-belongs
SELECT t.oid::regclass AS table_name,
a.attname AS column_name,
s.relname AS sequence_name
FROM pg_class AS t
JOIN pg_attribute AS a
ON a.attrelid = t.oid
JOIN pg_depend AS d
ON d.refobjid = t.oid
AND d.refobjsubid = a.attnum
JOIN pg_class AS s
ON s.oid = d.objid
WHERE d.classid = 'pg_catalog.pg_class'::regclass
AND d.refclassid = 'pg_catalog.pg_class'::regclass
AND d.deptype IN ('i', 'a')
AND t.relkind IN ('r', 'P')
AND s.relkind = 'S';
Maybe it is possible to filter by table and if there is no sequences - return 0 or smth like that. But I'm not sure how to handle different postgresql's version issues - if there's any...
Or add a custom exception and throw it in the lastInsertId
method, checking sequence's existence before calling \PDO::lastInsertId
. Don't like that one though) But the names for a sequence are building and checking inside this method..
Would be happy to discuss or just hear your thoughts about it, and if I'm lucky even make MR :)
I could try to provide a test that covers that case and fails?
I wanted to check that $I->dontSeeInDatabase
from a list of values. Instead of writing
$I->dontSeeInDatabase('someTable', ['foo' => 'cond1']);
$I->dontSeeInDatabase('someTable', ['foo' => 'cond2']);
$I->dontSeeInDatabase('someTable', ['foo' => 'cond3']);
I ended up writing
$I->dontSeeInDatabase('someTable', [
'foo' => ['cond1', 'cond2', 'cond3']
]);
hoping that it would generate the following query SELECT count(*) FROM someTable WHERE foo IN ('cond1', 'cond2', 'cond3')
and assert that the result must be 0. However I ended up getting an exception, saying array-to-string conversion - obviously enough since this is not supported.
Do you think this is something good to have, or just bad test design on my part?
Currently, all records, added by haveInDatabase()
method during test, are automatically removed after the end of the test.
Although this is a documented behaviour, for me it adds more confusion than profit.
In case when I need all the changes, made during test, to disappear after the test, I can't rely solely on this behaviour, because changes may be done not only by haveInDatabase()
. So I still need to use other things for keeping tests isolated (wrapping tests in transactions, or to re-populate database from dump before each test, etc).
And in other case, when I do not need tests isolation, I am ok with the fact that each test changes something in database, so auto-erasing some records only adds confusion for me.
So, I'd like to be able to turn this behaviour off in my tests.
Currently we have a skip_cleanup_if_failed
configuration parameter, but it does not give full control over the auto-erase, because allows to omit it only when tests fail (which should be the default behaviour, IMHO). Also, its name is confusing (see issue #67).
Let's add another boolean configuration parameter, responsible for this auto-erase. For example, auto_erase
, or cleanup
(could be used after renaming current cleanup
to repopulate
- see issue #67)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.