From f61488fcf8f1d68f77d8f6feee8d7098150b32e8 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sun, 17 Mar 2024 19:02:28 +0100 Subject: [PATCH] New tests towards better cov in some classes with low metrics 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% --- psalm.xml | 8 ++ tests/Bridge/MoodleTest.php | 110 +++++++++++++++++- tests/Command/MessDetectorCommandTest.php | 10 ++ .../Fixture/moodle/lib/classes/component.php | 41 +++++++ tests/Fixture/phpmd/Problems.php | 23 ++++ tests/Fixture/tiny-config.php | 33 ++++++ 6 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 tests/Fixture/moodle/lib/classes/component.php create mode 100644 tests/Fixture/phpmd/Problems.php create mode 100644 tests/Fixture/tiny-config.php diff --git a/psalm.xml b/psalm.xml index 7d325c7f..4096cab8 100644 --- a/psalm.xml +++ b/psalm.xml @@ -30,6 +30,14 @@ + + + + + + + diff --git a/tests/Bridge/MoodleTest.php b/tests/Bridge/MoodleTest.php index cb0a5e57..c1eed1d7 100644 --- a/tests/Bridge/MoodleTest.php +++ b/tests/Bridge/MoodleTest.php @@ -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(); + } } diff --git a/tests/Command/MessDetectorCommandTest.php b/tests/Command/MessDetectorCommandTest.php index 60d02dbb..d116f52c 100644 --- a/tests/Command/MessDetectorCommandTest.php +++ b/tests/Command/MessDetectorCommandTest.php @@ -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. diff --git a/tests/Fixture/moodle/lib/classes/component.php b/tests/Fixture/moodle/lib/classes/component.php new file mode 100644 index 00000000..ccd5279a --- /dev/null +++ b/tests/Fixture/moodle/lib/classes/component.php @@ -0,0 +1,41 @@ + '/path/to/mod', 'local' => '/path/to/local'], + [], // We don't need this. + [], // We don't need this. + ]; + } +} diff --git a/tests/Fixture/phpmd/Problems.php b/tests/Fixture/phpmd/Problems.php new file mode 100644 index 00000000..a396113e --- /dev/null +++ b/tests/Fixture/phpmd/Problems.php @@ -0,0 +1,23 @@ +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!