Testing BigDb Orms and Databases
A built-in test class is provided to make testing YOUR orms extremely quick and easy. You'll define some data to test, implement a couple initialization methods, and that's it.
NOTICE: The built-in tests are under development.
You can always add your own test methods as needed.
Run Tests / CLI Options
Tests are run via taeluf/tester, using the vendor/bin/phptest
command.
phptest [options]
phptest -class MyOrmTestClass -test CreateRowFromForm
vendor/bin/phptest
-class <ClassName> - tells tester to only run tests for the given class
-test <TestName> - tells tester to only run the named test
-num_tests <int num_to_run> - tells BigDb's OrmTester how many semi-random data sets to generate & test
-data "<DataIndices>" - where the ints are the index within the source data to use.
DataIndices will be printed in the cli for failing datasets, so you can re-run tests
DataIndices may be like "status:0, show_history:1, type:4, title:0, html_body:0, photo_id:1, story_id:0, tag:1"
-seed <int random_generator_seed> - Specify a seed to use for random selection of data, so tests can be repeated identically
-rand_count <int num_rands_to_run> - Tells BigDb's OrmTester how many times to call mt_rand() before running your test. If you use -data to limit your dataset, & -seed to specify a seed, then -rand_count is also needed to fix the state of the random generator before running your dataset test. If you use
--verbose - print additional debug output (Be sure to use the two dashes: --verbose)
Notes
- Most tests will normalize milliseconds to 0 for any
created_at
orupdated_at
property on an ORM. This is because MySql (in my experience) does not store milliseconds. - NOFIX: OCCASIONALLY tests will incorrectly pass or fail due to timing related issues with generating DateTime values. I think this happens because one DateTime value is generated at the very end of a second, and the next DateTime is generated at the very beginning of the next second. I'm 98% sure this is the problem, and I'm not going to fix it.
Features
The built-in tests cover:
- Create Rows by setting ORM properties directly, then calling
$orm->save()
- Create Rows by setting ORM properties from Form values, then calling
$orm->save()
- Read rows from the database and instantiate ORMs from that data
- Read rows from the databse, instantiate ORMs, and fill-in Forms
- Update rows by setting ORM properties directly, then calling
$orm->save()
- Update rows by setting ORM properties from Form values, then calling
$orm->save()
- Delete rows directly via
$orm->delete()
- Delete rows through form submission.
- Create ORM from db values
- Create ORM from
Note: If your ORM class does not extend from BigFormOrm, then the form-related tests are skipped Note: Both valid AND invalid data will be tested
How To Write Tests
- create
class MyOrmTest extends Tlf\BigDb\OrmTester
- in
config/secret.json
, define the following:mysql.host, mysql.dbname, mysql.user, mysql.password
.-
Alternate: Override
public function get_pdo(): \PDO{}
-
Alternate: Override
- implement
public function get_bigdb(\PDO $pdo): \Tlf\BigDb {}
- Instantiate and return a BigDb instance - Set
public string $orm_class = 'Your\FullyQualified\OrmClassName';
-
Alternate: Override
public function get_orm(\PDO $pdo, \Tlf\BigDb $db): \Tlf\BigFormOrm {}
-
Alternate: Override
- Initialize Tables & Data:
- Override
public function prepare(){}
to create tables in your db. Callparent::prepare()
after tables are created. - Setup
public array $create_before_test = [...]
like the example below to insert data duringparent::prepare()
- optionally implement
$this->will_run_test(string $test_method_name)
to setup table data before EACH test - optionally call
$this->create_before_test($this->create_before_test)
to empty table & re-insert test data any time.
- Override
Sample Test Class
<?php
namespace DecaturVote\News\Test\Db;
class ArticleTest extends \Tlf\BigDb\OrmTester {
/** The orm class to instantiate & test. Alternatively override get_orm(...)*/
public string $orm_class = 'DecaturVote\\News\\Orm\\Article';
/** Array of methods to call on your ORM after it is loaded from DB. This might be used to load an article's body from disk. */
public array $call_after_dbload = ['getBody'];
/** Initial rows to setup before tests are run. All tables listed will be emptied before inserting initial data. */
public array $create_before_test = [
'article'=>[
'columns'=>[],
'rows'=>[],
],
'file' =>[
'columns'=> ['id', 'stored_name', 'download_name', 'is_public', 'alt_text', 'file_type'],
'rows'=> [
[1, "test-stored-name", "test-download-name", 1, "test alt text", 'txt'],
[66, "test-stored-name2", "test-download-name2", 1, "test alt text2", 'txt'],
]
],
];
/** Initialize your BigDb instance */
public function get_bigdb(\PDO $pdo): \Tlf\BigDb {
$db = new \DecaturVote\News\Db\BigNewsDb($pdo, new \DecaturVote\News\Test\NewsIntegration($pdo));
return $db;
}
/** data arrays are covered below */
public array $valid_form_data = [...];
public array $invalid_form_data = [...];
public array $valid_orm_properties = [...];
public array $invalid_orm_properties = [...];
}
Data Arrays
All the data arrays use the same format, where a key points to an array of possible values.
Those possible values may be VALID or INVALID, depending on which array you're defining.
Tests will then generate random datasets from those arrays of possible values.
<?php
public array $valid_form_data = [
'key' => ['value1', 'value2', 'value3'],
'status'=>['public', 'private'],
'show_history' => ['1', '0'],
'type'=> ['original-report', 'meta-report', 'summary', 'opinion', 'fact-check', 'blog'],
'title'=>['Programming is hard and slow'],
'html_body'=>['<p>Coding is tough. It takes a lot of time. You gotta learn a lot, write tests, and wow.</p>'],
'photo_id'=>['', '1', '66',],
'tag'=>[[], ['1','2','3']],
];
This will be converted into a row many times to complete a test. Every possible value will be tested, but not every possible combination will be tested. Many combinations will be tested, but no particular combinations are guaranteed.
The above possible form data will be converted to a row like:
<?php
[ 'key' => 'value1',
'status' => 'public',
'show_history' => '1',
'type' => 'summary',
'title' => 'Programming is hard and slow',
'html_body' => '...',
'photo_id' => '1',
'tag' => ['1','2','3']
]
Notice all these values are strings (except tag which is an array of strings). That's because this is sample form data, and form data always submits as string values (in my personal experience).