From d0acabcbe5bb17fb283201b3332ba824f167e9d7 Mon Sep 17 00:00:00 2001 From: Deltik Date: Tue, 13 Feb 2018 07:48:29 -0600 Subject: [PATCH] Added code coverage support and a unit test --- README.md | 34 ++- codeception.yml | 5 + composer.json | 2 +- e107 | 2 +- tests/acceptance.suite.yml | 2 + tests/unit/TreeModelTest.php | 386 +++++++++++++++++++++++++++++++++++ 6 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 tests/unit/TreeModelTest.php diff --git a/README.md b/README.md index c877838ae..f1faa4c2c 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,11 @@ e107 Test Suites ```sh php -d allow_url_fopen=On -d display_errors=On ./vendor/bin/codecept run --step --debug ``` + * **All tests with code coverage report:** + ```sh + /opt/cpanel/ea-php71/root/usr/bin/php -d zend_extension=/opt/alt/php71/usr/lib64/php/modules/xdebug.so -d allow_url_fopen=On ./vendor/bin/codecept run --coverage --coverage-xml --coverage-html + ``` + > **Note:** This command is specific to cPanel EasyApache PHP 7.1 and CloudLinux PHP Selector. See the "Code Coverage" section below for details. * **Unit tests:** ```sh ./vendor/bin/codecept run unit @@ -71,7 +76,7 @@ The test suites can deploy themselves onto a cPanel account automatically. To set up automatically deployed tests, edit `secrets.yml` in the root folder of this repository and input the following configuration information: -``` +```yaml cpanel: enabled: true hostname: 'SHARED-HOSTNAME.YOUR-HOSTING-PROVIDER.EXAMPLE' @@ -92,3 +97,30 @@ If you do not have a cPanel account that meets the requirements, you can deploy 5. Put the app on the web server and note its URL. 6. Write the URL to `tests/acceptance.suite.yml` in your copy of this repository where the `url` setting for the `PhpBrowser` module is. 7. Write the database configuration to `codeception.yml` in your copy of this repository under the `\Helper\DelayedDb` module. + +## Code Coverage + +You can generate code coverage reports for all PHP files in the app. Code coverage is enabled for local tests (unit and functional tests) but disabled for remote tests (acceptance tests) by default. + +The reports may take minutes to be generated. + +### Requirements + +* **[Xdebug](https://xdebug.org/)** – You'll have to figure out the best way to [install Xdebug](https://xdebug.org/docs/install) in your environment. + +### Sample Commands + +These commands run all tests and generate a code coverage report in HTML format and [Clover](https://bitbucket.org/atlassian/clover) XML format: + +* Using [cPanel EasyApache 4](https://documentation.cpanel.net/display/EA4/PHP+Home) with PHP 7.1 and Xdebug from [CloudLinux PHP Selector](https://docs.cloudlinux.com/php_selector.html): + ```sh + /opt/cpanel/ea-php71/root/usr/bin/php -d zend_extension=/opt/alt/php71/usr/lib64/php/modules/xdebug.so -d allow_url_fopen=On ./vendor/bin/codecept run --coverage --coverage-xml --coverage-html + ``` +* Using the Xdebug module that you installed with PECL: + ```sh + php zend_extension=/usr/local/php/modules/xdebug.so -d allow_url_fopen=On ./vendor/bin/codecept run --coverage --coverage-xml --coverage-html + ``` + +### Output + +The generated coverage reports are stored in `./tests/_output/` relative to the root of your copy of this repository. diff --git a/codeception.yml b/codeception.yml index 6adf266e3..d03266adc 100644 --- a/codeception.yml +++ b/codeception.yml @@ -7,6 +7,11 @@ paths: actor_suffix: Tester settings: bootstrap: _bootstrap.php +coverage: + enabled: true + include: + - e107/*.php + - e107/**/*.php params: - secrets.yml extensions: diff --git a/composer.json b/composer.json index f08a0b979..688322d96 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require-dev": { "codeception/codeception": "^2.3", - "twig/twig": ">= 1.28" + "twig/twig": ">=1.28" } } diff --git a/e107 b/e107 index de7fb1d1a..d1a69b0c1 160000 --- a/e107 +++ b/e107 @@ -1 +1 @@ -Subproject commit de7fb1d1a0b64a20866c7dd6ab4cab935c225bd7 +Subproject commit d1a69b0c16ad06c45078b428aa12913df9959966 diff --git a/tests/acceptance.suite.yml b/tests/acceptance.suite.yml index 8a440698a..db9b2ddfa 100644 --- a/tests/acceptance.suite.yml +++ b/tests/acceptance.suite.yml @@ -5,6 +5,8 @@ # If you need both WebDriver and PHPBrowser tests - create a separate suite. actor: AcceptanceTester +coverage: + enabled: false modules: enabled: - PhpBrowser: diff --git a/tests/unit/TreeModelTest.php b/tests/unit/TreeModelTest.php new file mode 100644 index 000000000..9ea464f0a --- /dev/null +++ b/tests/unit/TreeModelTest.php @@ -0,0 +1,386 @@ +getMethod('arrayToTree'); + $method->setAccessible(true); + $this->tree = $method->invoke(null, $this->sample_rows, $this->sample_key, $this->sample_parent_key); + } + + protected function _after() + { + } + + // tests + public function testTreeIsAnArray() + { + $this->assertTrue(is_array($this->tree)); + } + + public function testTreeRootNodeIsTheOnlyRootNode() + { + $this->assertEquals(count($this->tree), 1); + } + + public function testTreeRootNodeHasCorrectKeyValuePair() + { + $key = $this->sample_key; + $this->assertArrayHasKey($key, $this->tree[0]); + $this->assertEquals($this->tree[0][$key], 0); + } + + public function testTreeRootNodeHasChildren() + { + $this->assertArrayHasKey('_children', $this->tree[0]); + $this->assertTrue(is_array($this->tree[0]['_children'])); + } + + public function testTreeParentsAreAssignedCorrectly() + { + $key = $this->sample_key; + $parent_key = $this->sample_parent_key; + $l0_id = $this->tree[0][$key]; + $l1_id = $this->tree[0]['_children'][0][$key]; + $l1_parent = $this->tree[0]['_children'][0][$parent_key]; + $l2_id = $this->tree[0]['_children'][0]['_children'][0][$key]; + $l2_parent = $this->tree[0]['_children'][0]['_children'][0][$parent_key]; + + $this->assertEquals($l0_id, $l1_parent); + $this->assertEquals($l1_id, $l2_parent); + } + + public function testTreeValuesAreStoredAsExpected() + { + $l1_0 = $this->tree[0]['_children'][0]; + $l1_1 = $this->tree[0]['_children'][1]; + $l2_0 = $this->tree[0]['_children'][0]['_children'][0]; + $l2_1 = $this->tree[0]['_children'][0]['_children'][1]; + + $this->assertEquals($l1_0['link_name'], "General"); + $this->assertEquals($l1_1['link_name'], "Nodes"); + $this->assertEquals($l2_0['link_name'], "Home"); + $this->assertEquals($l2_1['link_name'], "Downloads"); + } + + public function testTreeValuesAreOrderedCorrectly() + { + $order_key = 'link_order'; + $l1_0 = $this->tree[0]['_children'][0][$order_key]; + $l1_1 = $this->tree[0]['_children'][1][$order_key]; + $l1_2 = $this->tree[0]['_children'][2][$order_key]; + $l2_0 = $this->tree[0]['_children'][0]['_children'][0][$order_key]; + $l2_1 = $this->tree[0]['_children'][0]['_children'][1][$order_key]; + $l2_2 = $this->tree[0]['_children'][0]['_children'][2][$order_key]; + $l2_3 = $this->tree[0]['_children'][0]['_children'][3][$order_key]; + + $this->assertLessThanOrEqual($l1_1, $l1_0); + $this->assertLessThanOrEqual($l1_2, $l1_1); + $this->assertLessThanOrEqual($l2_1, $l2_0); + $this->assertLessThanOrEqual($l2_2, $l2_1); + $this->assertLessThanOrEqual($l2_3, $l2_2); + } + + protected $sample_rows = + array ( + 1 => + array ( + 'link_id' => '1', + 'link_name' => 'General', + 'link_url' => '/index.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon2.png', + 'link_category' => '1', + 'link_order' => '1', + 'link_parent' => '0', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 2 => + array ( + 'link_id' => '6', + 'link_name' => 'Home', + 'link_url' => '/index.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon18.png', + 'link_category' => '1', + 'link_order' => '1', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 3 => + array ( + 'link_id' => '10', + 'link_name' => 'Main Website', + 'link_url' => 'https://www.deltik.org/', + 'link_description' => 'The Official Deltik Website', + 'link_button' => 'deltik-favicon.png', + 'link_category' => '1', + 'link_order' => '1', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 4 => + array ( + 'link_id' => '2', + 'link_name' => 'Downloads', + 'link_url' => '/download.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/download_32.png', + 'link_category' => '1', + 'link_order' => '2', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 5 => + array ( + 'link_id' => '9', + 'link_name' => 'Nodes', + 'link_url' => '', + 'link_description' => '', + 'link_button' => 'icon14.png', + 'link_category' => '1', + 'link_order' => '2', + 'link_parent' => '0', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 6 => + array ( + 'link_id' => '11', + 'link_name' => 'My Deltik', + 'link_url' => 'https://my.deltik.org/', + 'link_description' => 'User Control Panel for all of Deltik's Features', + 'link_button' => 'deltik_my-favicon.png', + 'link_category' => '1', + 'link_order' => '2', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '255', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 7 => + array ( + 'link_id' => '3', + 'link_name' => 'Members', + 'link_url' => '/user.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon20.png', + 'link_category' => '1', + 'link_order' => '3', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 8 => + array ( + 'link_id' => '8', + 'link_name' => 'Register', + 'link_url' => '/signup.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/deltik-favicon.png', + 'link_category' => '1', + 'link_order' => '3', + 'link_parent' => '0', + 'link_open' => '0', + 'link_class' => '252', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 9 => + array ( + 'link_id' => '12', + 'link_name' => 'x10Deltik', + 'link_url' => 'https://x10.deltik.org/', + 'link_description' => 'Deltik Additional Resources Website', + 'link_button' => 'deltik_x10-favicon.png', + 'link_category' => '1', + 'link_order' => '3', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '255', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 10 => + array ( + 'link_id' => '7', + 'link_name' => 'Online Users', + 'link_url' => '/online.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon22.png', + 'link_category' => '1', + 'link_order' => '4', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 11 => + array ( + 'link_id' => '15', + 'link_name' => 'Deltik Docs', + 'link_url' => 'https://man.deltik.org/', + 'link_description' => 'Manual Pages of Deltik', + 'link_button' => 'deltik_docs-favicon.png', + 'link_category' => '1', + 'link_order' => '4', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '255', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 12 => + array ( + 'link_id' => '14', + 'link_name' => 'Legacy Deltik Products', + 'link_url' => 'https://products.deltik.org/', + 'link_description' => 'Legacy Deltik Products', + 'link_button' => 'deltik_products-favicon.png', + 'link_category' => '1', + 'link_order' => '5', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 13 => + array ( + 'link_id' => '16', + 'link_name' => 'Site Stats', + 'link_url' => '/{e_PLUGIN}log/stats.php?1', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon11.png', + 'link_category' => '1', + 'link_order' => '5', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 14 => + array ( + 'link_id' => '4', + 'link_name' => 'Submit News', + 'link_url' => '/submitnews.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon26.png', + 'link_category' => '1', + 'link_order' => '6', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 15 => + array ( + 'link_id' => '13', + 'link_name' => 'Deltik Minecraft Server', + 'link_url' => 'https://mc.deltik.org/', + 'link_description' => 'Deltik Minecraft Server', + 'link_button' => 'deltik_mc-favicon.png', + 'link_category' => '1', + 'link_order' => '6', + 'link_parent' => '9', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 16 => + array ( + 'link_id' => '17', + 'link_name' => 'Newsfeeds', + 'link_url' => '/{e_PLUGIN}newsfeed/newsfeed.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/html.png', + 'link_category' => '1', + 'link_order' => '7', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 17 => + array ( + 'link_id' => '18', + 'link_name' => 'About Us', + 'link_url' => '/page.php?4', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/deltik-favicon.png', + 'link_category' => '1', + 'link_order' => '8', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + 18 => + array ( + 'link_id' => '5', + 'link_name' => 'Contact Us', + 'link_url' => '/contact.php', + 'link_description' => '', + 'link_button' => '{e_IMAGE}icons/icon19.png', + 'link_category' => '1', + 'link_order' => '9', + 'link_parent' => '1', + 'link_open' => '0', + 'link_class' => '0', + 'link_function' => '', + 'link_sefurl' => '', + 'link_owner' => '', + ), + ); +}