From 4c57c67e2f1b821e2ef8aa0b00448ff24ce92201 Mon Sep 17 00:00:00 2001 From: Barney Laurance Date: Sun, 16 Jun 2019 20:56:00 +0100 Subject: [PATCH] Add end to end tests that invoke psalm as a separate process (#1798) * Add end to end tests that invoke psalm as a separate process * Assert that psalm --init creates config file --- composer.json | 3 +- tests/EndToEnd/PsalmEndToEndTest.php | 150 ++++++++++++++++++ .../DummyProjectWithErrors/composer.json | 11 ++ .../src/FileWithErrors.php | 6 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 tests/EndToEnd/PsalmEndToEndTest.php create mode 100644 tests/fixtures/DummyProjectWithErrors/composer.json create mode 100644 tests/fixtures/DummyProjectWithErrors/src/FileWithErrors.php diff --git a/composer.json b/composer.json index 84b196210..f12aaf301 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,8 @@ "squizlabs/php_codesniffer": "3.4.0", "bamarni/composer-bin-plugin": "^1.2", "psalm/plugin-phpunit": "^0.6", - "phpmyadmin/sql-parser": "^5.0" + "phpmyadmin/sql-parser": "^5.0", + "symfony/process": "^4.3" }, "suggest": { "ext-igbinary": "^2.0.5" diff --git a/tests/EndToEnd/PsalmEndToEndTest.php b/tests/EndToEnd/PsalmEndToEndTest.php new file mode 100644 index 000000000..efea703de --- /dev/null +++ b/tests/EndToEnd/PsalmEndToEndTest.php @@ -0,0 +1,150 @@ +mustRun(); + } + + public static function tearDownAfterClass(): void + { + chdir(self::$previousWorkingDir); + self::recursiveRemoveDirectory(self::$tmpDir); + parent::tearDownAfterClass(); + } + + public function setUp(): void + { + @unlink('psalm.xml'); + copy(__DIR__ . '/../fixtures/DummyProjectWithErrors/src/FileWithErrors.php', 'src/FileWithErrors.php'); + parent::setUp(); + } + + public function testHelpReturnsMessage(): void + { + $this->assertStringContainsString('Usage:', $this->runPsalm(['--help'])['STDOUT']); + } + + public function testVersion(): void + { + $this->assertStringStartsWith('Psalm 3', $this->runPsalm(['--version'])['STDOUT']); + } + + public function testInit(): void + { + $this->assertStringStartsWith('Config file created', $this->runPsalm(['--init'])['STDOUT']); + $this->assertFileExists('psalm.xml'); + } + + public function testAlter(): void + { + $this->runPsalm(['--init']); + + $this->assertStringContainsString( + 'No errors found!', + $this->runPsalm(['--alter', '--issues=all'])['STDOUT'] + ); + + $this->assertSame(0, $this->runPsalm([])['CODE']); + } + + public function testPsalter(): void + { + $this->runPsalm(['--init']); + (new Process([$this->psalter, '--alter', '--issues=InvalidReturnType']))->mustRun(); + $this->assertSame(0, $this->runPsalm([])['CODE']); + } + + public function testPsalm(): void + { + $this->runPsalm(['--init']); + $result = $this->runPsalm([], true); + $this->assertStringContainsString('InvalidReturnType', $result['STDOUT']); + $this->assertStringContainsString('InvalidReturnStatement', $result['STDOUT']); + $this->assertStringContainsString('2 errors', $result['STDOUT']); + $this->assertSame(1, $result['CODE']); + } + + /** + * @param array $args + * @return array{STDOUT: string, STDERR: string, CODE: int|null} + */ + private function runPsalm(array $args, bool $shouldFail = false): array + { + $process = new Process(array_merge([$this->psalm], $args)); + + if (! $shouldFail) { + $process->mustRun(); + } else { + $process->run(); + $this->assertGreaterThan(0, $process->getExitCode()); + } + + return [ + 'STDOUT' => $process->getOutput(), + 'STDERR' => $process->getErrorOutput(), + 'CODE' => $process->getExitCode() + ]; + } + + /** from comment by itay at itgoldman dot com at + * https://www.php.net/manual/en/function.rmdir.php#117354 + */ + private static function recursiveRemoveDirectory(string $src): void + { + $dir = opendir($src); + while (false !== ( $file = readdir($dir))) { + if (( $file != '.' ) && ( $file != '..' )) { + $full = $src . '/' . $file; + if (is_dir($full)) { + self::recursiveRemoveDirectory($full); + } else { + unlink($full); + } + } + } + closedir($dir); + rmdir($src); + } +} diff --git a/tests/fixtures/DummyProjectWithErrors/composer.json b/tests/fixtures/DummyProjectWithErrors/composer.json new file mode 100644 index 000000000..3f46bb5cf --- /dev/null +++ b/tests/fixtures/DummyProjectWithErrors/composer.json @@ -0,0 +1,11 @@ +{ + "name": "acme/sample-project", + "description": "A sample project to be used when testing Psalm", + "type": "project", + "require": {}, + "autoload": { + "psr-4": { + "Acme\\SampleProject\\": "src/" + } + } +} diff --git a/tests/fixtures/DummyProjectWithErrors/src/FileWithErrors.php b/tests/fixtures/DummyProjectWithErrors/src/FileWithErrors.php new file mode 100644 index 000000000..7d909056c --- /dev/null +++ b/tests/fixtures/DummyProjectWithErrors/src/FileWithErrors.php @@ -0,0 +1,6 @@ +