Skip to content

Commit

Permalink
New tests towards better cov in some classes with low metrics
Browse files Browse the repository at this point in the history
Note that initially I was planning to add this to v4 series but,
as far as it requires changes to Psalm config, I've moved it to
v5.

- MoodlePluginCI\Bridge\Moodle : 21% => 100%
- MoodlePluginCI\Bridge\MessDetectorRenderer : 31% => 100%
  • Loading branch information
stronk7 committed Jun 3, 2024
1 parent f88d288 commit 395dd25
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 3 deletions.
8 changes: 8 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
<RedundantPropertyInitializationCheck errorLevel="suppress"/>
<MissingConstructor errorLevel="info"/>

<!-- There are some include statements in tests that psalm cannot resolve,
but they are correct, part of the mocked Moodle environment. -->
<UnresolvableInclude>
<errorLevel type="suppress">
<directory name="tests"/>
</errorLevel>
</UnresolvableInclude>

<!-- Test classes are, apparently, not used but, for sure, they are used by PHPUnit. -->
<UnusedClass>
<errorLevel type="suppress">
Expand Down
110 changes: 107 additions & 3 deletions tests/Bridge/MoodleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,116 @@
namespace MoodlePluginCI\Tests\Bridge;

use MoodlePluginCI\Bridge\Moodle;
use MoodlePluginCI\Tests\FilesystemTestCase;

class MoodleTest extends \PHPUnit\Framework\TestCase
/**
* Test the \MoodlePluginCI\Bridge\Moodle class.
*
* Note that various unit tests are run in a separate process to avoid
* conflicts with global state when including Moodle's config.php or
* core_component (mocked) class.
*
* @covers \MoodlePluginCI\Bridge\Moodle
*/
class MoodleTest extends FilesystemTestCase
{
public function testGetBranch(): void
/**
* @runInSeparateProcess
*/
public function testGetConfigExists(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
$moodle = new Moodle($this->tempDir);

$this->assertSame('exists', $moodle->getConfig('exists'));
}

/**
* @runInSeparateProcess
*/
public function testGetConfigNotExists(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
$moodle = new Moodle($this->tempDir);

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Failed to find $CFG->notexists in Moodle config file');
$moodle->getConfig('notexists');
}

/**
* @runInSeparateProcess
*/
public function testGetConfigNoConfigFile(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$moodle = new Moodle($this->tempDir);

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Failed to find Moodle config file');
$moodle->getConfig('wwwroot');
}

/**
* @runInSeparateProcess
*/
public function testComponentInstallDirectoryExists(): void
{
$moodle = new Moodle(__DIR__ . '/../Fixture/moodle');
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
$moodle = new Moodle($this->tempDir);

// Initially we tried to mock the core_component class with Mockery, and everything
// worked fine, but the use of Reflection that we have in the code to be tested.
// Hence, we have changed to load a minimal core_component (Fixture/moodle/lib/classes/component.php)
// class that will be used instead of the (core) original.
require_once $this->tempDir . '/lib/classes/component.php';

$this->assertSame('/path/to/mod/test', $moodle->getComponentInstallDirectory('mod_test'));
}

/**
* @runInSeparateProcess
*/
public function testComponentInstallDirectoryNotExists(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
$moodle = new Moodle($this->tempDir);

// Initially we tried to mock the core_component class with Mockery, and everything
// worked fine, but the use of Reflection that we have in the code to be tested.
// Hence, we have changed to load a minimal core_component (Fixture/moodle/lib/classes/component.php)
// class that will be used instead of the (core) original.
require_once $this->tempDir . '/lib/classes/component.php';

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('The component unknown_test has an unknown plugin type of unknown');
$moodle->getComponentInstallDirectory('unknown_test');
}

public function testGetBranchCorrect(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
$moodle = new Moodle($this->tempDir);

$this->assertSame(39, $moodle->getBranch());
}

public function testGetBranchIncorrect(): void
{
$this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);

// Let's edit the version.php file to convert the correct (string) branch into incorrect (integer) branch.
$contents = file_get_contents($this->tempDir . '/version.php');
$contents = preg_replace("/'39'/", '39', $contents);
file_put_contents($this->tempDir . '/version.php', $contents);

$moodle = new Moodle($this->tempDir);
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Failed to find Moodle branch version');
$moodle->getBranch();
}
}
10 changes: 10 additions & 0 deletions tests/Command/MessDetectorCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ public function testExecute(): void
$this->assertSame(0, $commandTester->getStatusCode());
}

public function testExecuteWithProblems(): void
{
$commandTester = $this->executeCommand(__DIR__ . '/../Fixture/phpmd');

$this->assertSame(0, $commandTester->getStatusCode()); // PHPMD always return 0, no matter the violations/errors.
$this->assertStringContainsString('Constant testConst should be defined in uppercase', $commandTester->getDisplay());
$this->assertStringContainsString('long variable names like $reallyVeryLongVariableName', $commandTester->getDisplay());
$this->assertStringContainsString('Unexpected end of token stream in file', $commandTester->getDisplay());
}

public function testExecuteNoFiles(): void
{
// Just random directory with no PHP files.
Expand Down
41 changes: 41 additions & 0 deletions tests/Fixture/moodle/lib/classes/component.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Moodle Plugin CI package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2024 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

/**
* Minimal core_component core class.
*
* This is a minimal fixture of the Moodle core_component class, just to be able
* to use it in the tests, only including the methods that we are going to need to
* invoke.
*
* Note that we haven't been able to use Mockery for this, because the code to be
* tested is using Reflection on this class, so we cannot aliases/overload or
* use similar strategies to mock it.
*/
class core_component {

public static function get_component_directory($component) {
return '/path/to/' . str_replace('_', '/', $component);
}

public static function normalize_component($component) {
return explode('_', $component, 2);
}

protected static function fetch_plugintypes() {
return [
['mod' => '/path/to/mod', 'local' => '/path/to/local'],
[], // We don't need this.
[], // We don't need this.
];
}
}
23 changes: 23 additions & 0 deletions tests/Fixture/phpmd/Problems.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Moodle Plugin CI package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2024 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

/**
* This fixture class is used to test the PHPMD command.
*
* It contains 2 PHPMD naming violations and 1 parsing error.
*/
class Problems {
const testConst = 1;
protected $reallyVeryLongVariableName = true;
}

class unfinishedFixtureClass {
33 changes: 33 additions & 0 deletions tests/Fixture/tiny-config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php // Moodle configuration file

unset($CFG);
global $CFG;
$CFG = new stdClass();

$CFG->dbtype = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost = 'localhost';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'root';
$CFG->dbpass = '';
$CFG->prefix = 'mdl_';
$CFG->dboptions = [
'dbport' => '',
];

$CFG->wwwroot = 'http://localhost/moodle';
$CFG->dataroot = '/path/to/moodledata';
$CFG->admin = 'admin';

$CFG->directorypermissions = 02777;

// Show debugging messages.
$CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = 1;

// Extra config.
$CFG->exists = 'exists';

// require_once(__DIR__.'/lib/setup.php');
// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!

0 comments on commit 395dd25

Please sign in to comment.