3 namespace Drupal\Tests\simpletest\Unit;
5 use Composer\Autoload\ClassLoader;
6 use Drupal\Core\Extension\Extension;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\simpletest\Exception\MissingGroupException;
9 use Drupal\simpletest\TestDiscovery;
10 use Drupal\Tests\UnitTestCase;
11 use org\bovigo\vfs\vfsStream;
14 * @coversDefaultClass \Drupal\simpletest\TestDiscovery
17 class TestDiscoveryTest extends UnitTestCase {
20 * @covers ::getTestInfo
21 * @dataProvider infoParserProvider
23 public function testTestInfoParser($expected, $classname, $doc_comment = NULL) {
24 $info = TestDiscovery::getTestInfo($classname, $doc_comment);
25 $this->assertEquals($expected, $info);
28 public function infoParserProvider() {
29 // A module provided unit test.
33 'name' => 'Drupal\Tests\simpletest\Unit\TestDiscoveryTest',
34 'group' => 'simpletest',
35 'description' => 'Tests \Drupal\simpletest\TestDiscovery.',
36 'type' => 'PHPUnit-Unit',
39 'Drupal\Tests\simpletest\Unit\TestDiscoveryTest',
46 'name' => 'Drupal\Tests\Core\DrupalTest',
47 'group' => 'DrupalTest',
48 'description' => 'Tests \Drupal.',
49 'type' => 'PHPUnit-Unit',
52 'Drupal\Tests\Core\DrupalTest',
55 // Functional PHPUnit test.
59 'name' => 'Drupal\FunctionalTests\BrowserTestBaseTest',
60 'group' => 'browsertestbase',
61 'description' => 'Tests BrowserTestBase functionality.',
62 'type' => 'PHPUnit-Functional',
65 'Drupal\FunctionalTests\BrowserTestBaseTest',
68 // kernel PHPUnit test.
69 $tests['phpunit-kernel'] = [
72 'name' => '\Drupal\Tests\file\Kernel\FileItemValidationTest',
74 'description' => 'Tests that files referenced in file and image fields are always validated.',
75 'type' => 'PHPUnit-Kernel',
78 '\Drupal\Tests\file\Kernel\FileItemValidationTest',
81 // Simpletest classes can not be autoloaded in a PHPUnit test, therefore
82 // provide a docblock.
86 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
87 'group' => 'simpletest',
88 'description' => 'Tests the Simpletest UI internal browser.',
89 'type' => 'Simpletest',
92 'Drupal\simpletest\Tests\ExampleSimpleTest',
95 * Tests the Simpletest UI internal browser.
102 // Test with a different amount of leading spaces.
106 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
107 'group' => 'simpletest',
108 'description' => 'Tests the Simpletest UI internal browser.',
109 'type' => 'Simpletest',
112 'Drupal\simpletest\Tests\ExampleSimpleTest',
115 * Tests the Simpletest UI internal browser.
123 // Make sure that a "* @" inside a string does not get parsed as an
128 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
129 'group' => 'simpletest',
130 'description' => 'Tests the Simpletest UI internal browser. * @',
131 'type' => 'Simpletest',
134 'Drupal\simpletest\Tests\ExampleSimpleTest',
137 * Tests the Simpletest UI internal browser. * @
144 // Multiple @group annotations.
148 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
150 'description' => 'Tests the Simpletest UI internal browser.',
151 'type' => 'Simpletest',
154 'Drupal\simpletest\Tests\ExampleSimpleTest',
157 * Tests the Simpletest UI internal browser.
165 // @dependencies annotation.
169 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
170 'description' => 'Tests the Simpletest UI internal browser.',
171 'type' => 'Simpletest',
172 'requires' => ['module' => ['test']],
173 'group' => 'simpletest',
176 'Drupal\simpletest\Tests\ExampleSimpleTest',
179 * Tests the Simpletest UI internal browser.
187 // Multiple @dependencies annotation.
191 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
192 'description' => 'Tests the Simpletest UI internal browser.',
193 'type' => 'Simpletest',
194 'requires' => ['module' => ['test', 'test1', 'test2']],
195 'group' => 'simpletest',
198 'Drupal\simpletest\Tests\ExampleSimpleTest',
201 * Tests the Simpletest UI internal browser.
203 * @dependencies test, test1, test2
209 // Multi-line summary line.
213 'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
214 'description' => 'Tests the Simpletest UI internal browser. And the summary line continues an there is no gap to the annotation.',
215 'type' => 'Simpletest',
216 'group' => 'simpletest',
219 'Drupal\simpletest\Tests\ExampleSimpleTest',
222 * Tests the Simpletest UI internal browser. And the summary line continues an
223 * there is no gap to the annotation.
233 * @covers ::getTestInfo
235 public function testTestInfoParserMissingGroup() {
236 $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
237 $doc_comment = <<<EOT
239 * Bulk delete storages and fields, and clean up afterwards.
242 $this->setExpectedException(MissingGroupException::class, 'Missing @group annotation in Drupal\KernelTests\field\BulkDeleteTest');
243 TestDiscovery::getTestInfo($classname, $doc_comment);
247 * @covers ::getTestInfo
249 public function testTestInfoParserMissingSummary() {
250 $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
251 $doc_comment = <<<EOT
256 $info = TestDiscovery::getTestInfo($classname, $doc_comment);
257 $this->assertEmpty($info['description']);
260 protected function setupVfsWithTestClasses() {
261 vfsStream::setup('drupal');
270 class FunctionalExampleTest {}
279 'FunctionalExampleTest.php' => $test_file,
280 'FunctionalExampleTest2.php' => str_replace(['FunctionalExampleTest', '@group example'], ['FunctionalExampleTest2', '@group example2'], $test_file),
283 'KernelExampleTest3.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTest3', '@group example2'], $test_file),
284 'KernelExampleTestBase.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTestBase', '@group example2'], $test_file),
285 'KernelExampleTrait.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTrait', '@group example2'], $test_file),
286 'KernelExampleInterface.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleInterface', '@group example2'], $test_file),
296 * @covers ::getTestClasses
298 public function testGetTestClasses() {
299 $this->setupVfsWithTestClasses();
300 $class_loader = $this->prophesize(ClassLoader::class);
301 $module_handler = $this->prophesize(ModuleHandlerInterface::class);
303 $test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
306 'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
308 $test_discovery->setExtensions($extensions);
309 $result = $test_discovery->getTestClasses();
310 $this->assertCount(2, $result);
311 $this->assertEquals([
313 'Drupal\Tests\test_module\Functional\FunctionalExampleTest' => [
314 'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest',
315 'description' => 'Test description',
316 'group' => 'example',
317 'type' => 'PHPUnit-Functional',
321 'Drupal\Tests\test_module\Functional\FunctionalExampleTest2' => [
322 'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest2',
323 'description' => 'Test description',
324 'group' => 'example2',
325 'type' => 'PHPUnit-Functional',
327 'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
328 'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
329 'description' => 'Test description',
330 'group' => 'example2',
331 'type' => 'PHPUnit-Kernel',
338 * @covers ::getTestClasses
340 public function testGetTestClassesWithSelectedTypes() {
341 $this->setupVfsWithTestClasses();
342 $class_loader = $this->prophesize(ClassLoader::class);
343 $module_handler = $this->prophesize(ModuleHandlerInterface::class);
345 $test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
348 'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
350 $test_discovery->setExtensions($extensions);
351 $result = $test_discovery->getTestClasses(NULL, ['PHPUnit-Kernel']);
352 $this->assertCount(2, $result);
353 $this->assertEquals([
356 'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
357 'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
358 'description' => 'Test description',
359 'group' => 'example2',
360 'type' => 'PHPUnit-Kernel',
367 * @covers ::getPhpunitTestSuite
368 * @dataProvider providerTestGetPhpunitTestSuite
370 public function testGetPhpunitTestSuite($classname, $expected) {
371 $this->assertEquals($expected, TestDiscovery::getPhpunitTestSuite($classname));
374 public function providerTestGetPhpunitTestSuite() {
376 $data['simpletest-webtest'] = ['\Drupal\rest\Tests\NodeTest', FALSE];
377 $data['simpletest-kerneltest'] = ['\Drupal\hal\Tests\FileNormalizeTest', FALSE];
378 $data['module-unittest'] = [static::class, 'Unit'];
379 $data['module-kerneltest'] = ['\Drupal\KernelTests\Core\Theme\TwigMarkupInterfaceTest', 'Kernel'];
380 $data['module-functionaltest'] = ['\Drupal\FunctionalTests\BrowserTestBaseTest', 'Functional'];
381 $data['module-functionaljavascripttest'] = ['\Drupal\Tests\toolbar\FunctionalJavascript\ToolbarIntegrationTest', 'FunctionalJavascript'];
382 $data['core-unittest'] = ['\Drupal\Tests\ComposerIntegrationTest', 'Unit'];
383 $data['core-unittest2'] = ['Drupal\Tests\Core\DrupalTest', 'Unit'];
384 $data['core-kerneltest'] = ['\Drupal\KernelTests\KernelTestBaseTest', 'Kernel'];
385 $data['core-functionaltest'] = ['\Drupal\FunctionalTests\ExampleTest', 'Functional'];
386 $data['core-functionaljavascripttest'] = ['\Drupal\FunctionalJavascriptTests\ExampleTest', 'FunctionalJavascript'];
392 * Ensure that classes are not reflected when the docblock is empty.
394 * @covers ::getTestInfo
396 public function testGetTestInfoEmptyDocblock() {
397 // If getTestInfo() performed reflection, it won't be able to find the
398 // class we asked it to analyze, so it will throw a ReflectionException.
399 // We want to make sure it didn't do that, because we already did some
400 // analysis and already have an empty docblock. getTestInfo() will throw
401 // MissingGroupException because the annotation is empty.
402 $this->setExpectedException(MissingGroupException::class);
403 TestDiscovery::getTestInfo('Drupal\Tests\simpletest\ThisTestDoesNotExistTest', '');
407 * Ensure TestDiscovery::scanDirectory() ignores certain abstract file types.
409 * @covers ::scanDirectory
411 public function testScanDirectoryNoAbstract() {
412 $this->setupVfsWithTestClasses();
413 $files = TestDiscovery::scanDirectory('Drupal\\Tests\\test_module\\Kernel\\', vfsStream::url('drupal/modules/test_module/tests/src/Kernel'));
414 $this->assertNotEmpty($files);
415 $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTestBase', $files);
416 $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTrait', $files);
417 $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleInterface', $files);
418 $this->assertArrayHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTest3', $files);
423 class TestTestDiscovery extends TestDiscovery {
426 * @var \Drupal\Core\Extension\Extension[]
428 protected $extensions = [];
430 public function setExtensions(array $extensions) {
431 $this->extensions = $extensions;
437 protected function getExtensions() {
438 return $this->extensions;
443 namespace Drupal\simpletest\Tests;
445 use Drupal\simpletest\WebTestBase;
448 * Tests the Simpletest UI internal browser.
452 class ExampleSimpleTest extends WebTestBase {